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