作者介紹
賀春旸,普惠金融mysql專家,《mysql管理之道》第一版、第二版作者。曾任職于中國移動飛信、機鋒安卓市場,擁有豐富的資料庫管理經驗。目前緻力于mysql、linux等開源技術的研究。
mysql異步複制及semi-sync半同步複制,它們都基于mysql binlog,原生複制是完全異步的,master不需要保證slave接收并執行了binlog,能夠保證master最大性能,但是slave可能存在延遲,主備資料無法保證一緻性,在不停服務的前提下如果master當機,提升slave為新的主庫,就會丢失資料。
semi-sync在異步複制基礎上增加了資料保護的考慮,這樣一來master必須确認slave收到binlog後(但不保證slave執行了事務)才能最終送出事務,若再結合mha(master high availability)高可用架構,此時master挂掉之後,slave可以在apply完所有relay log後切換成master提供讀寫服務。
semi-sync半同步複制工作原理,如下圖所示。

相對于mysql源生複制和semi-sync半同步複制,group replication全同步複制的差異是:
全同步複制,主備無延遲,一個節點當機後其他兩個節點可以立即提供服務,而semi-sync需要應用(執行)完所有relay log,并依賴第三方高可用軟體實作資料不丢失;
事務沖突檢測保證資料一緻性,多個節點可以同時讀寫資料,可以極大簡化資料通路;
行級别并行複制,mysql 5.7/mariadb 10.0之前slave sql線程隻有一個,這個長期飽受诟病,是導緻slave落後master的主要原因。
1 group replication的工作原理
使用的是基于認證的複制,其流程如下圖所示:
當用戶端發起commit指令時(此時仍然沒有發生真正的commit),所有本事務内對資料庫的更改行的主鍵都會被搜集到一個寫入集(writeset)中,該寫入集随後會被複制到其他節點,該寫入集會在每個節點上使用搜尋到的主鍵進行确認性認證測試來判斷該寫入集是否可以被應用。如果認證測試失敗,寫入集會被丢棄并且原始事務會被復原;如果認證成功,事務會被送出并且寫入集會被在剩餘節點進行應用。最終,這意味着所有伺服器以相同的順序接收同一組事務。
其他節點隻要驗證成功了,就會傳回成功的信号,即使目前資料并沒有真正的寫入目前節點,固這裡的全同步複制,其實是虛拟的全同步複制。這段時間内,資料是有延遲的,但很小,如果應用程式通路的是遠端節點,讀到的資料是未改變之前的舊資料。固在生産環境裡,對資料延遲要求很苛刻的情況下,建議在一個主節點上讀寫,避免造成資料不一緻的情況發生。
(注:galera通過設定參數wsrep_causal_reads = on可以避免,這種情況下需要等待遠端節點應用完事務後,才傳回用戶端讀取請求,這将增加讀取的響應時間。group replication未發現相關參數,如有朋友知道也請告知。)
而真正意義上的全同步複制,是要等所有節點事務都送出落地,才成功傳回用戶端。是以虛拟全同步複制的性能會更好一些。
group replication内部實作了flow control限流措施,作用就是協調各個節點,保證所有節點執行事務的速度大于隊列增長速度,進而避免丢失事務。實作原理和簡單:整個group replication叢集中,同時隻有一個節點可以廣播消息(資料),每個節點都會獲得廣播消息的機會(獲得機會後也可以不廣播),當慢節點的待執行隊列超過一定長度後,它會廣播一個fc_pause消息,是以節點收到消息後都會暫緩廣播消息并不提供寫操作,直到該慢節點的待執行隊列長度減小到一定長度後,group replication資料同步又開始恢複。
變量參數:
group_replication_flow_control_applier_threshold = 25000
group_replication_flow_control_certifier_threshold = 25000
待執行隊列長度超過該值時,flow control被觸發,預設是25000。
2 group replication的特性和注意事項
全同步複制,事務要麼在所有節點都送出,要麼都復原;
多主複制,可以在任意節點進行寫操作;
在從伺服器上并行應用事件,真正意義上的并行複制;
節點自動配置--故障節點自動從叢集中移除,當故障節點再次加入叢集,無需手工備份目前資料庫并拷貝至故障節點;
應用程式的相容性:無需更改應用程式,原生的mysql接口;
生産環境上叢集推薦配置3個節點;
每個節點都包含完整的資料副本;
各個節點的同步複制,通過gtid binlog row實作。
優點:
真正的多主架構,任何節點都可以進行讀寫,無需進行讀寫分離;
(注:生産環境建議隻在一台機器上寫,由于叢集是樂觀鎖并發控制,事務沖突的情況會在commit階段發生。如果有兩個事務在叢集中不同的節點上對同一行寫入并送出,失敗的節點将復原,用戶端傳回報錯,作為dba你不想被一群開發投訴的話,還是默默的開啟single-primary寫入模式)
無集中管理,可以在任何時間點失去任何一個節點,叢集将正常工作不受影響;
節點當機不會導緻資料丢失;
對應用透明。
缺點:
加入新節點,開銷大,需要複制完整的資料。
不能有效的解決寫擴充問題,磁盤空間滿了,無法自動擴容,不能像mongodb分片那樣自動移動chunk做balance
有多少個節點就有多少份重複的資料
由于事務送出需要跨節點通訊(分布式事務),寫入會比主從複制慢
對網絡要求非常高,如果網絡出現波動或機房被arp攻擊,造成兩個節點失聯,group replication叢集發生腦裂,服務将不可用。
下面是官方叢集節點投票示意圖,如果是3個節點,必須滿足大多數節點2個投票,這裡很像mongodb副本集的算法吧^_^
叢集自身不提供vip機制,也沒有像mongodb副本集那樣提供java/php用戶端api接口實作故障切換(需要開發自己寫,成本較高),需要結合第三方haproxy軟體(建議2塊網卡做bond0)+自定義腳本實作秒級故障切換,另通過代理方式,性能會降低,因為多了一層網絡轉發。
局限性:
目前的複制僅僅支援innodb存儲引擎;
每張表必須有主鍵;
隻支援ipv4網絡;
叢集最大支援9個節點;
不支援savepoints;
不支援serializable隔離級别在multi-primary多主模式;
不支援外鍵在multi-primary多主模式;
整個叢集的寫入吞吐量是由最弱的節點限制,如果有一個節點變得緩慢,比如硬碟故障(raid10壞了一塊盤),那麼整個叢集将是緩慢的。為了穩定的高性能要求,所有的節點應使用統一的硬體。
3 group replication的使用
single-primary模式配置環境:
1、設定host解析
三台伺服器的配置如下:
# cat /etc/hosts
192.168.17.133 node1
192.168.17.134 node2
192.168.17.135 node3
2、編輯/etc/my.cnf配置參數(三個節點按照如下設定)
log-bin = /data/mysql57/binlog/mysql-bin
binlog_format = row
sync_binlog = 1
binlog_checksum = none
log_slave_updates = 1
gtid_mode = on
enforce_gtid_consistency = on
master_info_repository = table
relay_log_info_repository = table
3、安裝插件
install plugin group_replication soname 'group_replication.so';
4、設定叢集參數(三個節點都執行)
set global transaction_write_set_extraction = "xxhash64";
set global group_replication_start_on_boot = on;
set global group_replication_bootstrap_group = off;
set global group_replication_group_name =
"13dd01d4-d69e-11e6-9c80-000c2937cddb";
set global group_replication_local_address = '192.168.17.133:6606';
set global group_replication_group_seeds =
'192.168.17.133:6606,192.168.17.134:6606,192.168.17.135:6606';
set global group_replication_single_primary_mode = on;
注:group_replication_group_name名字要通過select uuid()來生成
group_replication_local_address在節點2和節點3上改成本地ip位址
執行完了,别忘了修改my.cnf裡加入到配置檔案裡。
5、節點加入叢集
primary節點上執行
set sql_log_bin=0;
grant replication slave,replication client on *.* to 'repl'@'%' identified by 'repl';
flush privileges;
set sql_log_bin=1;
change master to master_user='repl',
master_password='repl' for channel
'group_replication_recovery';
set global group_replication_bootstrap_group=on;
start group_replication;
select * from performance_schema.replication_group_members;
set global group_replication_bootstrap_group=off;
注:待replication_group_members表查詢結果member_state字段狀态為online,再執行關閉初始化。
兩台secondary上執行
如下圖所示,代表叢集已經成功運作。
4 group replication的維護
假如secondary節點當機,重新開機後由于種種原因加入叢集失敗,現需要重新恢複,步驟如下:
1、在另一台secondary節點上mysqldump全量
mysqldump -uroot -p123456 -q --single-transaction
--master-data=2 -b yourdb > /root/yourdb.sql
這一步會自動在yourdb.sql裡生成
set @@global.gtid_purged='23e510dc-d30b-11e6-a4c6-b82a72d18b06:1,4d1fd6ec-d2fd-11e6-ae4b-549f3503ab31:1-1543112:2003786-2003789:3003787,e4e34dd3-d2fa-11e6-984b-b82a72d18b06:1';
2、導入進去
再執行下面的語句即可
5 group replication總結
由于5.7.17版本剛剛ga,是以直接上生産環境風險太高,至少1年後小版本超過5.7.40以後再考慮。
原文釋出時間為:2017-01-12
本文來自雲栖社群合作夥伴dbaplus