《MySQL 5.7并行復制實踐》要點:
本文介紹了MySQL 5.7并行復制實踐,希望對您有用。如果有疑問,可以聯(lián)系我們。
MySQL 5.7并行復制原理
MySQL 從 5.6 開始引入了多庫并行主從復制,但是其并行只是基于 Schema
的,也就是基于庫的.如果用戶的 MySQL 數(shù)據(jù)庫實例中存在多個 Schema
,對于從機復制的速度的確可以有比較大的幫助.MySQL 5.6 并行復制的架構如下所示:
在上圖的紅色框框部分就是實現(xiàn)并行復制的關鍵所在.在 MySQL 5.6 版本之前,Slave 服務器上有兩個線程 I/O 線程和 SQL 線程.I/O 線程負責接收二進制日志(更準確的說是二進制日志的 event ),SQL 線程進行回放二進制日志.如果在 MySQL 5.6 版本開啟并行復制功能,那么SQL線程就變?yōu)榱?Coordinator
線程,Coordinator
線程主要負責以前兩部分的內(nèi)容:
Worker
線程執(zhí)行事務的二進制日志.DDL
,亦或者是事務跨 Schema
操作,則等待所有的 Worker
線程執(zhí)行完成之后,再執(zhí)行當前的日志.這意味著 Coordinator
線程并不是僅將日志發(fā)送給 Worker
線程,自己也可以回放日志,但是所有可以并行的操作交付由 Worker
線程完成.Coordinator
線程與 Worker
是典型的生產(chǎn)者與消費者模型.
上述機制實現(xiàn)的基于 Schema
的并行復制存在兩個問題,首先是 Crash Safe
功能不好做,因為可能之后執(zhí)行的事務由于并行復制的關系先完成執(zhí)行,那么當發(fā)生 Crash 的時候,這部分的處理邏輯是比較復雜的.從代碼上看,5.6 這里引入了 Low-Water-Mark
標記來解決該問題,從設計上看,其是希望借助于日志的冪等性來解決該問題,不過 5.6 的二進制日志回放還不能實現(xiàn)冪等性.另一個最為關鍵的問題是這樣設計的并行復制效果并不高,如果用戶實例僅有一個庫,那么就無法實現(xiàn)并行回放,甚至性能會比原來的單線程更差.而單庫多表是比多庫多表更為常見的一種情形.
MySQL 5.7 才可稱為真正的并行復制,這其中最為主要的原因就是 Slave 服務器的回放與主機是一致的即 Master 服務器上是怎么并行執(zhí)行的 Slave 上就怎樣進行并行回放.不再有庫的并行復制限制,對于二進制日志格式也無特殊的要求(基于庫的并行復制也沒有要求).
從 MySQL 官方來看,其并行復制的原本計劃是支持表級的并行復制和行級的并行復制,行級的并行復制通過解析 ROW 格式的二進制日志的方式來完成.但是最終出現(xiàn)的是在開發(fā)計劃中稱為:MTS: Prepared transactions slave parallel applier
.
該并行復制的思想最早是由 MariaDB 的 Kristain 提出,并已在 MariaDB 10 中出現(xiàn),MySQL 5.7 并行復制的思想簡單易懂,一言以蔽之:一個組提交的事務都是可以并行回放,因為這些事務都已進入到事務的 Prepare
階段,則說明事務之間沒有任何沖突(否則就不可能提交).
為了兼容 MySQL 5.6 基于庫的并行復制,5.7 引入了新的變量 slave-parallel-type
,其可以配置的值有:
如何知道事務是否在一組中,又是一個問題,因為原版的 MySQL 并沒有提供這樣的信息.在 MySQL 5.7版本中,其設計方式是將組提交的信息存放在 GTID
中.那么如果用戶沒有開啟 GTID
功能,即將參數(shù) gtid_mode
設置為 OFF 呢?故 MySQL 5.7 又引入了稱之為 Anonymous_Gtid
的二進制日志 event
類型,如:
mysql> SHOW BINLOG EVENTS in 'mysql-bin.000011'; | mysql-bin.000011 | 123 | Previous_gtids | 88 | 194 | f11232f7-ff07-11e4-8fbb-00ff55e152c6:1-2 | | mysql-bin.000011 | 194 | Anonymous_Gtid | 88 | 259 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' | | mysql-bin.000011 | 259 | Query | 88 | 330 | BEGIN | | mysql-bin.000011 | 330 | Table_map | 88 | 373 | table_id: 108 (aaa.t) | | mysql-bin.000011 | 373 | Write_rows | 88 | 413 | table_id: 108 flags: STMT_END_F | ......
這意味著在 MySQL 5.7 版本中即使不開啟 GTID
,每個事務開始前也是會存在一個 Anonymous_Gtid
,而這 GTID
中就存在著組提交的信息.
組提交是個比較好玩的方式,我們根據(jù) MySQL 的
binlog
可以發(fā)現(xiàn)較之原來的二進制日志內(nèi)容多了last_committed
和sequence_number
.$ mysqlbinlog mysql-bin.000011 |grep last_committed #170607 11:24:57 server id 353306 end_log_pos 876350 CRC32 0x92093332 GTID last_committed=654 sequence_number=655 #170607 11:24:58 server id 353306 end_log_pos 880406 CRC32 0x344fdf71 GTID last_committed=655 sequence_number=656 #170607 11:24:58 server id 353306 end_log_pos 888700 CRC32 0x4ba2b05b GTID last_committed=656 sequence_number=657
上面是沒有開啟組提交的一個日志,我們可以看得到 binlog
當中有兩個參數(shù) last_committed
和 sequence_number
,我們可以看到,下一個事務在主庫配置好組提交以后,last_committed
永遠都和上一個事務的 sequence_number
是相等的.這也很容易理解,因為事務是順序提交的.
下面看一下組提交模式的事務:
$ mysqlbinlog mysql-bin.000012|grep last_commit #170609 10:11:07 server id 353306 end_log_pos 75629 CRC32 0xd54f2604 GTID last_committed=269 sequence_number=270 #170609 10:13:03 server id 353306 end_log_pos 75912 CRC32 0x43675b14 GTID last_committed=270 sequence_number=271 #170609 10:13:24 server id 353306 end_log_pos 76195 CRC32 0x4f843438 GTID last_committed=270 sequence_number=272
我們可以看到最后兩個事務的 last_committed
是相同的,這意味著這兩個事務是作為一個組提交的,兩個事務在 Perpare
階段獲取相同的 last_committed
而且相互不影響,最終是會作為一個組進行提交.這就是所謂的組提交.組提交的事務是可以在從機進行并行回放的.
上述的 last_committed
和 sequence_number
代表的就是所謂的 LOGICAL_CLOCK
.
這里一共使用了二臺機器,MySQL 版本都為 5.7.18.
MySQL 安裝比較簡單,在 「MySQL 5.7多源復制實踐」一文中我們也講了,這里就不在重復講了.如果你還不會安裝,可以先參考此文安裝好 MySQL .
MySQL 5.7的并行復制建立在組提交的基礎上,所有在主庫上能夠完成 Prepared
的語句表示沒有數(shù)據(jù)沖突,就可以在 Slave 節(jié)點并行復制.
關于 MySQL 5.7 的組提交,我們要看下以下的參數(shù):
mysql> show global variables like '%group_commit%'; +-----------------------------------------+-------+ | Variable_name ? ? ? ? ? ? ? ? ? ? ? ? ? | Value | +-----------------------------------------+-------+ | binlog_group_commit_sync_delay ? ? ? ? ?| 0 ? ? | | binlog_group_commit_sync_no_delay_count | 0 ? ? | +-----------------------------------------+-------+ 2 rows in set (0.00 sec)
要開啟 MySQL 5.7 并行復制需要以下二步,首先在主庫設置 binlog_group_commit_sync_delay
的值大于0 .
mysql> set global binlog_group_commit_sync_delay=10;
這里簡要說明下 binlog_group_commit_sync_delay
和 binlog_group_commit_sync_no_delay_count
參數(shù)的作用.
binlog_group_commit_sync_delay
全局動態(tài)變量,單位微妙,默認0,范圍:0~1000000(1秒).
表示
binlog
提交后等待延遲多少時間再同步到磁盤,默認0 ,不延遲.當設置為 0 以上的時候,就允許多個事務的日志同時一起提交,也就是我們說的組提交.組提交是并行復制的基礎,我們設置這個值的大于 0 就代表打開了組提交的功能.
binlog_group_commit_sync_no_delay_count
全局動態(tài)變量,單位個數(shù),默認0,范圍:0~1000000.
表示等待延遲提交的最大事務數(shù),如果上面參數(shù)的時間沒到,但事務數(shù)到了,則直接同步到磁盤.若
binlog_group_commit_sync_delay
沒有開啟,則該參數(shù)也不會開啟.
其次要在 Slave 主機上設置如下幾個參數(shù):
# 過多的線程會增加線程間同步的開銷,建議4-8個Slave線程. slave-parallel-type=LOGICAL_CLOCK slave-parallel-workers=4
或者直接在線啟用也是可以的:
mysql> stop slave; Query OK, 0 rows affected (0.07 sec) mysql> set global slave_parallel_type='LOGICAL_CLOCK'; Query OK, 0 rows affected (0.00 sec) mysql> set global slave_parallel_workers=4; Query OK, 0 rows affected (0.00 sec) mysql> start slave; Query OK, 0 rows affected (0.06 sec) mysql> show variables like 'slave_parallel_%'; +------------------------+---------------+ | Variable_name ? ? ? ? ?| Value ? ? ? ? | +------------------------+---------------+ | slave_parallel_type ? ?| LOGICAL_CLOCK | | slave_parallel_workers | 4 ? ? ? ? ? ? | +------------------------+---------------+ 2 rows in set (0.00 sec)
當前的 Slave 的 SQL 線程為 Coordinator
(協(xié)調(diào)器),執(zhí)行 Relay log
日志的線程為 Worker
(當前的 SQL 線程不僅起到協(xié)調(diào)器的作用,同時也可以重放 Relay log
中主庫提交的事務).
我們上面設置的線程數(shù)是 4 ,從庫就能看到 4 個 Coordinator
(協(xié)調(diào)器)進程.
開啟 MTS 功能后,務必將參數(shù) master-info-repository
設置為 TABLE ,這樣性能可以有 50%~80% 的提升.這是因為并行復制開啟后對于 master.info
這個文件的更新將會大幅提升,資源的競爭也會變大.
在 MySQL 5.7 中,推薦將 master-info-repository
和 relay-log-info-repository
設置為 TABLE ,來減小這部分的開銷.
master-info-repository = table relay-log-info-repository = table relay-log-recovery = ON
復制的監(jiān)控依舊可以通過 SHOW SLAVE STATUS\G
,但是 MySQL 5.7 在 performance_schema
架構下多了以下這些元數(shù)據(jù)表,用戶可以更細力度的進行監(jiān)控:
mysql> use performance_schema; mysql> show tables like 'replication%'; +---------------------------------------------+ | Tables_in_performance_schema (replication%) | +---------------------------------------------+ | replication_applier_configuration ? ? ? ? ? | | replication_applier_status ? ? ? ? ? ? ? ? ?| | replication_applier_status_by_coordinator ? | | replication_applier_status_by_worker ? ? ? ?| | replication_connection_configuration ? ? ? ?| | replication_connection_status ? ? ? ? ? ? ? | | replication_group_member_stats ? ? ? ? ? ? ?| | replication_group_members ? ? ? ? ? ? ? ? ? | +---------------------------------------------+ 8 rows in set (0.00 sec)
文章來自微信公眾號:運維之美
轉載請注明本頁網(wǎng)址:
http://www.snjht.com/jiaocheng/2207.html