OMG,數(shù)據(jù)庫(kù)主從延遲了?。。?/h1>
前言
說(shuō)到MySQL數(shù)據(jù)庫(kù)主從延遲問(wèn)題,我還是深有體會(huì)的,因?yàn)槲抑敖?jīng)常遇到。
我之前在一家餐飲工作公司中,當(dāng)時(shí)我們的系統(tǒng)屬于訂單的下游業(yè)務(wù)系統(tǒng)。
在中午和晚上的用餐高峰期,用戶并發(fā)量還是不小的。訂單系統(tǒng)為了保證性能和高可用,做了主從分離架構(gòu)。
一個(gè)主庫(kù),兩個(gè)從庫(kù)。
圖片
主庫(kù)主要用來(lái)寫數(shù)據(jù),從庫(kù)主要是用來(lái)讀數(shù)據(jù),主庫(kù)的數(shù)據(jù)會(huì)實(shí)時(shí)同步到從庫(kù)。
但偶爾會(huì)出現(xiàn)主從延遲問(wèn)題。
1 案發(fā)現(xiàn)場(chǎng)
而我們劃菜系統(tǒng)跟訂單系統(tǒng)之間,是通過(guò)MQ進(jìn)行通信的,流程如下:
圖片
用戶下單之后,訂單系統(tǒng)會(huì)發(fā)生一條MQ消息,消息體只包含id等關(guān)鍵信息。
劃菜系統(tǒng)消費(fèi)這條MQ消息之后,會(huì)通過(guò)訂單id,調(diào)用訂單系統(tǒng)的訂單查詢接口查詢出訂單的詳情數(shù)據(jù)。
訂單查詢接口的數(shù)據(jù),是從訂單的從庫(kù)查詢出來(lái)的。
如果一旦出現(xiàn)數(shù)據(jù)庫(kù)主從同步延遲的問(wèn)題,就可能會(huì)出現(xiàn)訂單查詢接口返回的數(shù)據(jù)不完整。
會(huì)導(dǎo)致劃菜系統(tǒng)的表寫入數(shù)據(jù)失敗。
2 MySQL主從同步的原理
MySQL的主庫(kù)會(huì)將數(shù)據(jù)庫(kù)的變化,以二進(jìn)制的形式,保存到磁盤上的binlog文件中。
主從同步就是將主庫(kù)上的binlog文件,傳輸?shù)綇膸?kù)上。
這個(gè)過(guò)程通常情況下是異步的。
流程圖如下:
圖片
- 數(shù)據(jù)庫(kù)主庫(kù)的寫操作,會(huì)將數(shù)據(jù)庫(kù)的變化寫入binlog文件中。
- 主庫(kù)同時(shí)會(huì)創(chuàng)建一個(gè)Log dump線程,將binlog發(fā)送給從庫(kù)。
- 從庫(kù)的IO線程接收到binlog,會(huì)將數(shù)據(jù)庫(kù)的更新操作寫入到replay log文件中。
- 從庫(kù)的SQL線程會(huì)讀取repay log文件,并且做回放,將數(shù)據(jù)寫入到從庫(kù)中。
如果中間的任何一個(gè)環(huán)節(jié)出現(xiàn)問(wèn)題,都可能會(huì)導(dǎo)致數(shù)據(jù)庫(kù)主從延遲的問(wèn)題。
3 如何解決主從延遲問(wèn)題?
3.1 網(wǎng)絡(luò)問(wèn)題
網(wǎng)絡(luò)問(wèn)題,會(huì)導(dǎo)致binlog從主庫(kù)發(fā)生到主從時(shí),出現(xiàn)問(wèn)題。
我們可以增加網(wǎng)絡(luò)的帶寬,由100M升級(jí)到300M。
3.2 服務(wù)器性能問(wèn)題
一般情況下,主庫(kù)的性能要比從庫(kù)的要好。
如果高并發(fā)的寫入數(shù)據(jù),會(huì)導(dǎo)致產(chǎn)生大量的binlog數(shù)據(jù),在從庫(kù)通過(guò)replay log回放的過(guò)程會(huì)比較慢。
從而導(dǎo)致從庫(kù)寫入數(shù)據(jù)的速度。
這種情況下,可以升級(jí)從庫(kù)的服務(wù)器配置,跟主庫(kù)保持一致。
3.3 避免大事務(wù)問(wèn)題
業(yè)務(wù)系統(tǒng)中的大事務(wù),不光會(huì)導(dǎo)致主庫(kù)寫數(shù)據(jù)的速度變慢,還會(huì)導(dǎo)致主從數(shù)據(jù)同步時(shí),從庫(kù)寫數(shù)據(jù)的速度同樣變慢。
我們需要避免大事務(wù)問(wèn)題,對(duì)業(yè)務(wù)代碼中的大事務(wù)做排查,縮小事務(wù)的范圍。
有些業(yè)務(wù)代碼,可以放到事務(wù)之外的,盡可能放到事務(wù)之外執(zhí)行,比如:有些查詢方法。
有些可以異步執(zhí)行的代碼,盡可能異步執(zhí)行。
3.4 MySQL版本太低
MySQL的低版本,只支持單線程同步binlog,同步速度非常慢。
這種情況下,可以升級(jí)MySQL版本到5.6以上,支持多線程同步。
3.5 從庫(kù)太多
在主從同步時(shí),如果從庫(kù)太多,可能會(huì)導(dǎo)致同步速度變慢。
主從同步,要所有從庫(kù)的數(shù)據(jù),都同步成功了,才算真正的成功了。
針對(duì)這種情況,建議減少,從庫(kù)的數(shù)量,一般不建議超過(guò)5個(gè)。
4 我們的解決方案
接下來(lái),聊聊我們當(dāng)時(shí)遇到了數(shù)據(jù)庫(kù)主從延遲問(wèn)題的解決方案。
我們當(dāng)時(shí)先找運(yùn)維升級(jí)了網(wǎng)絡(luò)帶寬。
確保在高并發(fā)時(shí),帶寬不會(huì)被打滿。
然后,優(yōu)化了業(yè)務(wù)代碼,減少了代碼中的大事務(wù),將非核心業(yè)務(wù)剝離出來(lái)了,然后使用異步處理這一部分邏輯。
這樣可以減少同一時(shí)刻的數(shù)據(jù)庫(kù)寫操作。
此外,增加了自動(dòng)重試機(jī)制。
如果MQ消費(fèi)者調(diào)用訂單查詢接口時(shí),出現(xiàn)了數(shù)據(jù)不完整的情況。
我們的程序會(huì)將異常數(shù)據(jù)寫入數(shù)據(jù)庫(kù),有專門的job自動(dòng)發(fā)起重試。
經(jīng)過(guò)上面的這些優(yōu)化之后,我們數(shù)據(jù)庫(kù)主從延遲的問(wèn)題基本上被解決了。
最后留一個(gè)問(wèn)題:如果想要主從強(qiáng)制一致性該怎么辦?