在談這個特性之前,我們先來看看MySQL的複製架構衍生史。 MySQL的複製分為四種:
普通的replication,非同步同步。 搭建簡單,使用非常廣泛,從mysql誕生之初,就產生了這種架構,性能非常好,可謂非常成熟。 但是這種架構資料是異步的,所以有遺失資料庫的風險。
semi-sync replication,半同步。效能,功能都介於非同步和全同步中間。從mysql5.5開始誕生,目的是為了折中上述兩種架構的效能以及優缺點。
sync replication,全同步。目前官方5.7基於Group replication的全同步技術處在labs版本,離正式整合已經不遠。全同步技術帶來了更多的資料一致性保障。相信是未來同步技術一個重要方向,值得期待。
mysql cluster。 基於NDB引擎,搭建也簡單,本身也比較穩定,是mysql裡面對資料保護最可靠的架構,也是目前唯一資料完全同步的架構,資料零遺失。不過對業務比較挑剔,限制也較多。
我們今天談論第二種架構。我們知道,普通的replication,也就是mysql的非同步複製,依賴mysql二進位日誌也即binary log進行資料複製。例如兩台機器,一台主機(master),另外一台是從機(slave)。
正常的複製為:事務一(t1)寫入binlog buffer;dumper 執行緒通知slave有新的事務t1;binlog buffer 進行checkpoint;slave的io執行緒接收到t1並寫入到自己的relay log;slave的sql線程寫入到本機的資料庫。 這時,master和slave都能看到這項新的事務,即使master掛了,slave可以提升為新的master。
異常的複製為:事務一(t1)寫入binlog buffer;dumper 執行緒通知slave有新的事務t1;binlog buffer 進行checkpoint;slave因為網路不穩定,一直沒有收到t1;master 掛掉,slave提升為新的master,t1遺失。
很大的問題是:主機和從機事務更新的不同步,就算是沒有網路或其他系統的異常,當業務並發上來時,slave因為要順序執行master批量事務,導致很大的延遲。
為了彌補以上幾種場景的不足,mysql從5.5開始推出了半同步。即在master的dumper執行緒通知slave後,增加了一個ack,也就是是否成功收到t1的標誌碼。也就是dumper執行緒除了發送t1到slave,還承擔了接收slave的ack工作。如果出現異常,沒有收到ack,那麼將自動降級為普通的複製,直到異常修復。
我們可以看到半同步帶來的新問題:
#如果例外發生,會降級為普通的複製。 那麼從機出現資料不一致的幾率會減少,並不是完全消失。
主機dumper執行緒承擔的工作變多了,這顯然會降低整個資料庫的效能。
在MySQL 5.5和5.6使用MySQL 5.7 深度解析: 半同步複製技術的模式下, 即如果slave 沒有收到事務,也就是還沒有寫入到relay log 之前,網路出現異常或不穩定,此時剛好master掛了,系統切換到從機,兩邊的資料就會出現不一致。 在此情況下,slave會少一個事務的資料。
隨著MySQL 5.7版本的發布,半同步複製技術升級為全新的Loss-less Semi-Synchronous Replication架構,其成熟度、資料一致性與執行效率得到顯著的提升。
新版本的semi sync 增加了rpl_semi_sync_master_wait_point參數, 來控制半同步模式下主函式庫在傳回給會話交易成功之前提交交易的方式。
此參數有兩個值:
AFTER_COMMIT(5.6預設值)
master將每個交易寫入binlog ,傳遞到slave 刷新到磁碟(relay log),同時主庫提交事務。 master等待slave 回饋收到relay log,只有收到ACK後master才將commit OK結果回饋給客戶端。
AFTER_SYNC(5.7預設值,但5.6無此模式)
master 將每個交易寫入binlog , 傳遞到slave 刷新到磁碟(relay log)。 master等待slave 回饋接收到relay log的ack之後,再提交交易並且回傳commit OK結果給客戶端。 即使主函式庫crash,所有在主函式庫上已經提交的交易都能保證已經同步到slave的relay log中。
因此5.7引入了MySQL 5.7 深度解析: 半同步複製技術模式,帶來的主要收益是解決MySQL 5.7 深度解析: 半同步複製技術導致的master crash主從間資料不一致問題,因此在引入MySQL 5.7 深度解析: 半同步複製技術模式後,所有提交的資料已經都被複製,故障切換時資料一致性將會提升。
舊版的semi sync 受限於dump thread ,原因是dump thread 承擔了兩份不同且又十分頻繁的任務:傳送binlog 給slave ,還需要等待slave反饋信息,而且這兩個任務是串行的,dump thread 必須等待slave 返回之後才會傳送下一個events 事務。 dump thread 已然成為整個半同步提高效能的瓶頸。在高並發業務場景下,這樣的機制會影響資料庫整體的TPS 。
為了解決上述問題,在5.7版本的semi sync 框架中,獨立出一個 ack collector thread ,專門用來接收slave 的回饋訊息。這樣master 上有兩個執行緒獨立工作,可以同時傳送binlog 到slave ,和接收slave的回饋。
MySQL 5.7 新增了rpl_semi_sync_MySQL 5.7 深度解析: 半同步複製技術參數,可以用來控制主函式庫接受多少個slave寫事務成功回饋,給高可用架構切換提供了彈性。
如圖所示,當count值為2時,master需等待兩個slave的ack。
舊版半同步複製在主提交binlog的寫會話和dump thread讀binlog的操作都會對binlog新增互斥鎖,導致binlog檔案的讀寫是串行化的,存在並發度的問題。
MySQL 5.7 對binlog lock進行了以下兩方面優化:
1. 移除了dump thread對binlog的互斥鎖
2. 加入了安全邊際保證binlog的讀取安全性
MySQL 5.7 引入了新的變數slave-parallel- type,其可配置的值有:
1. DATABASE (5.7之前預設值),基於庫的平行複製方式;
2. LOGICAL_CLOCK (5.7新增值),基於群組提交的平行複製方式;
MySQL 5.6版本也支援所謂的平行複製,但並行只是基於DATABASE的,也就是基於函式庫的。如果用戶的MySQL資料庫實例中存在多個DATABASE ,對於從機複製的速度的確可以有比較大的幫助,如果用戶實例僅有一個庫,那麼就無法實現並行回放,甚至性能會比原來的單線程更差。
MySQL5.7中增加了一個新的平行模式:為同時進入COMMIT階段的交易分配相同的序號,這些擁有相同序號的事務在備庫是可以並發執行的。
MySQL 5.7真正實現的平行複製,這其中最主要的原因就是slave伺服器的回放與主機是一致的即master伺服器上是怎麼並行執行的slave上就怎樣進行並行回放。不再有庫的並行複製限制,對於二進位日誌格式也無特殊的要求(基於庫的平行複製也沒有要求)。
因此下面的序列中可以並發的序列為(其中前面一個數字為last_committed ,後面一個數字為sequence_number ):
trx1 1…..2 trx2 1………….3 trx3 1…………………….4 trx4 2……………………….5 trx5 3…………………………..6 trx6 3………………………………7 trx7 6………………………………..8
備庫並行規則:當分發一個事務時,其last_committed 序號比目前正在執行的交易的最小sequence_number要小時,則允許執行。因此:
1. trx1執行,last_commit2. trx1執行完成後,last_commit 3. trx2執行完成後,last_commit 4. trx3、trx4、trx5完成後,last_commit
我們認為MySQL 5.7版對半同步複製技術的最佳化,使得其成熟度和執行效率都得到了質的提升。我們建議在使用MySQL 5.7作為生產環境的部署時,可以使用半同步技術作為高可用與讀寫分離方案的資料複製方案。
以上是MySQL 5.7 深度解析: 半同步複製技術的詳細內容。更多資訊請關注PHP中文網其他相關文章!