MySQL主從延時這麼長,要怎麼優化?

MySQL主從複製讀寫分離是互聯網常見的數據庫架構,該架構最使人詬病的地方就是,在數據量較大併發量較大的場景下,主從延時會比較嚴重。

 

爲何主從延時這麼大?mysql


:MySQL使用單線程重放RelayLog。算法

 

應該怎麼優化,縮短重放時間?sql

:多線程並行重放RelayLog能夠縮短期。數據庫

 

多線程並行重放RelayLog有什麼問題?


:須要考慮如何分割RelayLog,纔可以讓多個數據庫實例多個線程並行重放RelayLog,不會出現不一致。多線程

 

爲何會出現不一致?架構

:若是RelayLog隨機的分配給不一樣的重放線程,假設RelayLog中有這樣三條串行的修改記錄:併發

update account set money=100 where uid=58;微服務

update account set money=150 where uid=58;工具

update account set money=200 where uid=58;優化

 

若是單線程串行重放:能保證全部從庫與主庫的執行序列一致。

畫外音:最後money都將爲200。

 

若是多線程隨機分配重放:多重放線程併發執行這3個語句,誰最後執行是不肯定的,最終從庫數據可能與主庫不一樣。

畫外音:多個從庫可能money爲100,150,200不肯定。

 

如何分配,多個從庫多線程重放,也能獲得一致的數據呢?

:相同庫上的寫操做,用相同的線程來重放RelayLog;不一樣庫上的寫操做,能夠併發用多個線程併發來重放RelayLog。

 

如何作到呢?

:設計一個哈希算法,hash(db-name) % thread-num,庫名hash以後再模上線程數,就能很輕易作到,同一個庫上的寫操做,被同一個重放線程串行執行。

畫外音:不一樣庫上的重放,是並行的,就起到了加速作用。

 

這個方案有什麼不足?

:不少公司對MySQL的使用是「單庫多表」,若是是這樣的話,仍然只有一個庫,仍是不能提升RelayLog的重放速度。

 

啓示:將「單庫多表」的DB架構模式升級爲「多庫多表」的DB架構模式。

畫外音:數據量大併發量大的互聯網業務場景,「多庫」模式還具有着其餘不少優點,例如:

(1)很是方便的實例擴展:DBA很容易將不一樣的庫擴展到不一樣的實例上;

(2)按照業務進行庫隔離:業務解耦,進行業務隔離,減小耦合與相互影響;

(3)很是方便微服務拆分:每一個服務擁有本身的實例就方便了;

 

「單庫多表」的場景,多線程並行重放RelayLog還能怎麼優化?

:即便只有一個庫,事務在主庫上也是併發執行的,既然在主庫上能夠並行執行,在從庫上也應該可以並行執行呀?

 

新思路:將主庫上同時並行執行的事務,分爲一組,編一個號,這些事務在從庫上的回放能夠並行執行(事務在主庫上的執行都進入到prepare階段,說明事務之間沒有衝突,不然就不可能提交),沒錯,MySQL正是這麼作的。

 

解法:基於GTID的並行複製。

從MySQL5.7開始,將組提交的信息存放在GTID中,使用mysqlbinlog工具,能夠看到組提交內部的信息:

20181014 23:52 server_id 58 XXX GTID last_committed=0 sequence_numer=1

20181014 23:52 server_id 58 XXX GTID last_committed=0 sequence_numer=2

20181014 23:52 server_id 58 XXX GTID last_committed=0 sequence_numer=3

20181014 23:52 server_id 58 XXX GTID last_committed=0 sequence_numer=4


和原來的日誌相比,多了last_committed和sequence_number。

 

什麼是last_committed?

答:它是事務提交時,上次事務提交的編號,若是具有相同的last_committed,說明它們在一個組內,能夠併發回放執行。

 

總結

MySQL並行複製,縮短主從同步時延的方法,體現着這樣的一些架構思想:

  • 多線程是一種常見的縮短執行時間的方法;

畫外音:例如,不少crontab能夠用多線程,切分數據,並行執行。

  • 多線程併發分派任務時,必須保證冪等性:MySQL提供了「按照庫冪等」,「按照commit_id冪等」兩種方式,很值得借鑑;

畫外音:例如,羣消息,能夠按照group_id冪等;用戶消息,能夠按照user_id冪等。

 

具體到MySQL主從同步延時:

    • mysql5.5:不支持並行複製,大夥快升級MySQL版本;

    • mysql5.6:按照庫並行複製,建議使用「多庫」架構;

    • mysql5.7:按照GTID並行複製;

相關文章
相關標籤/搜索