掃二維碼與項(xiàng)目經(jīng)理溝通
我們在微信上24小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
MySQL主從復(fù)制,讀寫分離是互聯(lián)網(wǎng)常見的數(shù)據(jù)庫架構(gòu),該架構(gòu)最令人詬病的地方就是,在數(shù)據(jù)量較大并發(fā)量較大的場景下,主從延時(shí)會(huì)比較嚴(yán)重。

為什么主從延時(shí)這么大?
答:MySQL使用單線程重放RelayLog。
應(yīng)該怎么優(yōu)化,縮短重放時(shí)間?
答:多線程并行重放RelayLog可以縮短時(shí)間。
多線程并行重放RelayLog有什么問題?
答:需要考慮如何分割RelayLog,才能夠讓多個(gè)數(shù)據(jù)庫實(shí)例,多個(gè)線程并行重放RelayLog,不會(huì)出現(xiàn)不一致。
為什么會(huì)出現(xiàn)不一致?
答:如果RelayLog隨機(jī)的分配給不同的重放線程,假設(shè)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;
如果單線程串行重放:能保證所有從庫與主庫的執(zhí)行序列一致。
畫外音:***money都將為200。
如果多線程隨機(jī)分配重放:多重放線程并發(fā)執(zhí)行這3個(gè)語句,誰***執(zhí)行是不確定的,最終從庫數(shù)據(jù)可能與主庫不同。
畫外音:多個(gè)從庫可能money為100,150,200不確定。
如何分配,多個(gè)從庫多線程重放,也能得到一致的數(shù)據(jù)呢?
答:相同庫上的寫操作,用相同的線程來重放RelayLog;不同庫上的寫操作,可以并發(fā)用多個(gè)線程并發(fā)來重放RelayLog。
如何做到呢?
答:設(shè)計(jì)一個(gè)哈希算法,hash(db-name) % thread-num,庫名hash之后再模上線程數(shù),就能很輕易做到,同一個(gè)庫上的寫操作,被同一個(gè)重放線程串行執(zhí)行。
畫外音:不同庫上的重放,是并行的,就起到了加速做用。
這個(gè)方案有什么不足?
答:很多公司對(duì)MySQL的使用是“單庫多表”,如果是這樣的話,仍然只有一個(gè)庫,還是不能提高RelayLog的重放速度。
啟示:將“單庫多表”的DB架構(gòu)模式升級(jí)為“多庫多表”的DB架構(gòu)模式。
畫外音:數(shù)據(jù)量大并發(fā)量大的互聯(lián)網(wǎng)業(yè)務(wù)場景,“多庫”模式還具備著其他很多優(yōu)勢,例如:
“單庫多表”的場景,多線程并行重放RelayLog還能怎么優(yōu)化?
答:即使只有一個(gè)庫,事務(wù)在主庫上也是并發(fā)執(zhí)行的,既然在主庫上可以并行執(zhí)行,在從庫上也應(yīng)該能夠并行執(zhí)行呀?
新思路:將主庫上同時(shí)并行執(zhí)行的事務(wù),分為一組,編一個(gè)號(hào),這些事務(wù)在從庫上的回放可以并行執(zhí)行(事務(wù)在主庫上的執(zhí)行都進(jìn)入到prepare階段,說明事務(wù)之間沒有沖突,否則就不可能提交),沒錯(cuò),MySQL正是這么做的。
解法:基于GTID的并行復(fù)制。
從MySQL5.7開始,將組提交的信息存放在GTID中,使用mysqlbinlog工具,可以看到組提交內(nèi)部的信息:
- 從MySQL5.7開始,將組提交的信息存放在GTID中,使用mysqlbinlog工具,可以看到組提交內(nèi)部的信息:
- 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?
答:它是事務(wù)提交時(shí),上次事務(wù)提交的編號(hào),如果具備相同的last_committed,說明它們在一個(gè)組內(nèi),可以并發(fā)回放執(zhí)行。
總結(jié)
MySQL并行復(fù)制,縮短主從同步時(shí)延的方法,體現(xiàn)著這樣的一些架構(gòu)思想:
具體到MySQL主從同步延時(shí):
【本文為專欄作者“58沈劍”原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)聯(lián)系原作者】
戳這里,看該作者更多好文

我們在微信上24小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流