溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何理解MySQL多線程復(fù)制

發(fā)布時(shí)間:2021-11-16 15:09:38 來(lái)源:億速云 閱讀:215 作者:柒染 欄目:MySQL數(shù)據(jù)庫(kù)

這篇文章給大家介紹如何理解MySQL多線程復(fù)制,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

Enhanced Multi-threaded Slaves

首先梳理下傳統(tǒng)MySQL/MariaDB主備復(fù)制基本原理:

        主從復(fù)制通過三個(gè)線程來(lái)完成,在master節(jié)點(diǎn)運(yùn)行的binlog dump的線程,I/O線程和SQL線程運(yùn)行在slave 節(jié)點(diǎn)

  •         master節(jié)點(diǎn)的Binlog dump線程,當(dāng)slave節(jié)點(diǎn)與master正常連接的時(shí)候,master把更新的binlog 內(nèi)容推送到slave節(jié)點(diǎn)。

  •             slave節(jié)點(diǎn)的I/O 線程 ,該線程通過讀取master節(jié)點(diǎn)binlog日志名稱以及偏移量信息將其拷貝到本地relay log日志文件。

  •         slave節(jié)點(diǎn)的SQL線程,該線程讀取relay log日志信息,將在master節(jié)點(diǎn)上提交的事務(wù)在本地回放,達(dá)到與主庫(kù)數(shù)據(jù)保持一致的目的。

問題1:

        Master節(jié)點(diǎn)的數(shù)據(jù)庫(kù)實(shí)例并發(fā)跑多個(gè)線程同時(shí)提交事務(wù),提交的事務(wù)按照邏輯的時(shí)間(數(shù)據(jù)庫(kù)LSN號(hào))順序地寫入binary log日志,,slave節(jié)點(diǎn)通過I/O線程寫到本地的relay log日志,但是slave節(jié)點(diǎn)只有SQL單線程來(lái)執(zhí)行relay log中的日志信息重放主庫(kù)提交得事務(wù),造成主備數(shù)據(jù)庫(kù)存在延遲(lag)

思考1:

        那么為了減少主備數(shù)據(jù)同步延遲時(shí)間,由于備庫(kù)只有單線程補(bǔ)償數(shù)據(jù)的原因而造成延遲,那么能否使slave節(jié)點(diǎn)同時(shí)運(yùn)行多個(gè)如SQL線程一樣的功能來(lái)重放在主庫(kù)執(zhí)行的事務(wù)?答案當(dāng)然是:可以!但是我們需要解決以下問題:

        1、slave本地的relay log記錄的是master 的binary log日志信息,日志記錄的信息按照事務(wù)的時(shí)間先后順序記錄,那么為了保證主備數(shù)據(jù)一致性,slave節(jié)點(diǎn)必須按照同樣的順序執(zhí)行,如果順序不一致容易造成主備庫(kù)數(shù)據(jù)不一致的風(fēng)險(xiǎn)。

        如:

                在master節(jié)點(diǎn)提交T1和T2事務(wù)按照以下順序

1.  State0: x= 1, y= 1

2.  T1: { x:= Read(y);          

3.          x:= x+1;        

4.          Write(x);        

5.          Commit; }

6. 
State1: x= 2, y= 1

7.  T2: { y:= Read(x);

8.            y:=y+1;          

9.           Write(y);          

10.          Commit; }

11.
State2: x= 2, y= 3   

            slave節(jié)點(diǎn)執(zhí)行T1和T2相反的順序:

1.  State0: x= 1, y= 1

2.  T2: { y:= Read(x);

3.            y:= y+1;

4.            Write(y);

5.            Commit; }

6. 
State1: x= 1, y= 2

7.  T1: { x:= Read(y);

8.            x:=x+1;

9.            Write(x);

10.           Commit; }

11.
State2: x= 3, y= 2

MySQL 5.6改進(jìn):

        MySQL 5.6版本引入并發(fā)復(fù)制(schema級(jí)別),基于schema級(jí)別的并發(fā)復(fù)制核心思想:“不同schema下的表并發(fā)提交時(shí)的數(shù)據(jù)不會(huì)相互影響,即slave節(jié)點(diǎn)可以用對(duì)relay log中不同的schema各分配一個(gè)類似SQL功能的線程,來(lái)重放relay log中主庫(kù)已經(jīng)提交的事務(wù),保持?jǐn)?shù)據(jù)與主庫(kù)一致”??梢奙ySQL5.6版本的并發(fā)復(fù)制,一個(gè)schema分配一個(gè)類似SQL線程的功能。

實(shí)現(xiàn)1:      

         slave節(jié)點(diǎn)開啟并發(fā)復(fù)制(slave_parallel_workers=3)如下圖,當(dāng)前的slave的SQL線程為Coordinator(協(xié)調(diào)器),執(zhí)行relay log日志的線程為worker(當(dāng)前的SQL線程不僅起到協(xié)調(diào)器的作用,同時(shí)也可以重放relay log中主庫(kù)提交的事務(wù))

1.  +-----+-------------+-----------+------+---------+-------+--------------------------------------------------------+------------------+

2.  | Id  | User        | Host      | db   | Command | Time  | State                                                  | Info             |

3.  +-----+-------------+-----------+------+---------+-------+--------------------------------------------------------+------------------+

4.  |   1 | system user |           | NULL | Connect | 29923 | Slave has read all relay log; waiting for more updates | NULL             |

5.  |   2 | system user |           | NULL | Connect | 29923 | Waiting for an event from Coordinator                  | NULL             |

6.  |   3 | system user |           | NULL | Connect | 29923 | Waiting for an event from Coordinator                  | NULL             |

7.  |   4 | system user |           | NULL | Connect | 29923 | Waiting for an event from Coordinator                  | NULL             |

問題2:

        MySQL 5.6基于schema級(jí)別的并發(fā)復(fù)制能夠解決當(dāng)業(yè)務(wù)數(shù)據(jù)的表放在不同的database庫(kù)下,但是實(shí)際生產(chǎn)中往往大多數(shù)或者全部的業(yè)務(wù)數(shù)據(jù)表都放在同一個(gè)schema下,在這種場(chǎng)景即使slave_parallel_workers>0設(shè)置也無(wú)法并發(fā)執(zhí)行relay log中記錄的主庫(kù)提交數(shù)據(jù)。 高并發(fā)的情況下,由于slave無(wú)法并發(fā)執(zhí)行同個(gè)schema下的業(yè)務(wù)數(shù)據(jù)表,依然會(huì)造成主備延遲的情況。

思考2:

        那么如果slave同時(shí)可以用多線程的方式,同時(shí)執(zhí)行一個(gè)schema下的所有業(yè)務(wù)數(shù)據(jù)表,將能大大提高slave節(jié)點(diǎn)執(zhí)行ralay log中記錄的主庫(kù)提交事務(wù)達(dá)到與主庫(kù)數(shù)據(jù)同步的目的,實(shí)現(xiàn)該功能我們需要解決什么問題?

  • 1、前面提到過為了保證主庫(kù)數(shù)據(jù)一致性,master節(jié)點(diǎn)寫入的binary log日志按照數(shù)據(jù)庫(kù)邏輯時(shí)間先后的順序并且slave節(jié)點(diǎn)執(zhí)行relay log中主庫(kù)提交的事務(wù)必須按照一致的順序否則會(huì)造成主備數(shù)據(jù)不一致的情況。

  • 2、既然要實(shí)現(xiàn)scehma下所有的業(yè)務(wù)數(shù)據(jù)表能夠并發(fā)執(zhí)行,那么slave必須得知道并發(fā)執(zhí)行relay     log中主庫(kù)提交的事務(wù)不能相互影響而且結(jié)果必須和主庫(kù)保持一致。

實(shí)現(xiàn)2:

        MySQL 5.7 引入Enhanced Muti-threaded slaves,當(dāng)slave配置slave_parallel_workers>0并且global.slave_parallel_type=‘LOGICAL_CLOCK’,可支持一個(gè)schema下,slave_parallel_workers個(gè)的worker線程并發(fā)執(zhí)行relay log中主庫(kù)提交的事務(wù)。但是要實(shí)現(xiàn)以上功能,需要在master機(jī)器標(biāo)記binary log中的提交的事務(wù)哪些是可以并發(fā)執(zhí)行,雖然MySQL 5.6已經(jīng)引入了binary log group commit,但是沒有將可以并發(fā)執(zhí)行的事務(wù)標(biāo)記出來(lái)。

我們用命令 mysqlbinlog -vvv mysqlbinlog.0000003 | grep -i last_committed    MySQL 5.7master機(jī)器上可以看到last_committed 和sequence_number

1.  #151223 15:11:28 server id 15102  end_log_pos 14623 CRC32 0x767a33fa GTID      last_committed=18         sequence_number=26

2.   

3.  #151223 15:11:28 server id 15102  end_log_pos 15199 CRC32 0x7dd1bf05  GTID     last_committed=26         sequence_number=27

4.   

5.  #151223 15:11:28 server id 15102  end_log_pos 15773 CRC32 0xb01dc76e  GTID     last_committed=26         sequence_number=28

6.   

7.  #151223 15:11:28 server id 15102  end_log_pos 16347 CRC32 0x7a8e0ee8  GTID     last_committed=26         sequence_number=29

8.   

9.  #151223 15:11:28 server id 15102  end_log_pos 16921 CRC32 0x92516d17  GTID     last_committed=26         sequence_number=30

10.  

11. #151223 15:11:28 server id 15102  end_log_pos 17495 CRC32 0xeb14a51e  GTID     last_committed=26         sequence_number=31

12.  

13. #151223 15:11:28 server id 15102  end_log_pos 18071 CRC32 0x750667d0  GTID     last_committed=26         sequence_number=32

14.  

15. #151223 15:11:28 server id 15102  end_log_pos 18645 CRC32 0xcaed6159  GTID     last_committed=26         sequence_number=33

16.  

17. #151223 15:11:28 server id 15102  end_log_pos 19219 CRC32 0x62408408  GTID     last_committed=26         sequence_number=34

18.  

19. #151223 15:11:28 server id 15102  end_log_pos 19793 CRC32 0x5cf46239  GTID     last_committed=33         sequence_number=35

slave機(jī)器的relay log last_committed相同的事務(wù)(sequence_num不同)可以并發(fā)執(zhí)行。從上面截取的信息可以看出last_committed=26的事務(wù)一共有8個(gè):從sequence_number=27~24。假設(shè)當(dāng)slave_parallel_workers=7時(shí),Coordinator線程(SQL線程)分配這一組事務(wù)到worker中排隊(duì)去執(zhí)行。這里可以看出增加master庫(kù)binary log group commit組中事務(wù)的數(shù)量可以提高slave機(jī)器并發(fā)處理事務(wù)的數(shù)量,MySQL5.7引入 binlog_group_commit_sync_delay和 binlog_group_commit_sync_no_delay_count參數(shù)即提高binary log組提交并發(fā)數(shù)量。MySQL等待binlog_group_commit_sync_delay毫秒的時(shí)間直到binlog_group_commit_sync_no_delay_count個(gè)事務(wù)數(shù)時(shí),將進(jìn)行一次組提交。

總結(jié):

       MySQL 5.7 GA版本推出的 Enhanced Multi-threaded Slaves功能,徹底解決了之前版本主備數(shù)據(jù)復(fù)制延遲的問題,開啟該功能參數(shù)如下:

1.  # slave機(jī)器

2.  slave-parallel-type=LOGICAL_CLOCK

3.  #slave-parallel-type=DATABASE #兼容MySQL 5.6基于schema級(jí)別的并發(fā)復(fù)制

4.  slave-parallel-workers=16 #開啟多線程復(fù)制

5.  master_info_repository=TABLE

6.  relay_log_info_repository=TABLE

7.  relay_log_recovery=ON

關(guān)于如何理解MySQL多線程復(fù)制就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI