Double Sync Replication
—— 對 MySQL 原生複製可靠性的改進
阿里巴巴云計算 彭立勛
原生異步 Replication 機制
異步復制存在的缺陷
• 主庫事務提交并不需要備庫 ACK
• 備庫無法得知拖取的是否是最新的日志
• 宕機后無法利用備庫本身的信息得知是否跟主庫一致
• 所以,備庫無法及時得知主庫的狀態
原生 Semi-Sync Replication 機制
SemiSync 存在的缺陷
• 主庫事務提交需要備庫 ACK
• 網絡超時后備庫降級為異步復制
• 超時設太小,則經常發生超時
• 超時設太大,則經常導致主庫 hang
• 網絡恢復后需要追趕日志,追趕期間備庫狀態依然不可知
• 因為無法得知宕機時備庫是否跟主庫是 SemiSync 狀態
• 所以依然無法得知備庫是否跟上主庫
• 因此, SemiSync 并沒有解決異步復制的根本缺陷
異步復制 /SemiSync 存在的問題
我們要達成的目標
• 前提
• 主機保證可用性 5 個 9
• 網絡保證可用性 5 個 9
• 宕機瞬時沒有發生網絡超時
• 目標
• 備庫隨時可以得知自己的狀態(跟主庫同步 或 沒有跟主庫同步)
• 在確認跟主庫不同步時,通知應用參與數據補償,并且告知所缺數據范圍
• 在確認跟主庫同步時,可以保證備庫執行到跟主庫一致狀態再提供服務
• 核心:避免備庫狀態不可知!
攻破 SemiSync 的缺點
• SemiSync 一旦超時斷開,即使網絡恢復,依然需要補償拖取斷開期
間的日志
• 如果 SemiSync 超時斷開,網絡恢復后不再補償數據,只發最新日志,如何
?
• 只要宕機時網絡正常,備庫始終會知道主庫最新位點
• 依此可以判斷備庫是否跟主庫日志有差異
• 備庫如果只接收最新數據,那么中斷期間的數據如何處理?
• 異步復制可以在不影響主庫提交的情況下拖取日志
• 利用異步復制的日志可以進行完整的日志回放
結合兩種復制
• 異步復制( Async_Channel )
• 拖取連續日志,保證備庫接收的日志不中斷
• 接收到日志后直接執行
• 半同步復制( Sync_Channel )
• 拖取最新日志,保證備庫始終知道最新的日志位置
• 接收到日志后并不執行,只保留位置
• 一致性判斷
• 比較異步復制和半同步復制的日志段,可以判斷備庫日志可否連續接上
結合兩種復制
兩個通道如何做到( 1 )
• 多源復制可以在一個 Slave 上創建多個獨立通道分別進行復制
• 問題 1 :同一個 ServerID 發起兩個通道到 Master , Master 會認為
是原 Slave 斷開沒有主動發起 close 連接,從而會踢掉先連上的通道
• 解決:可以將 SemiSync 通道偽裝一個 ServerID ,避免被踢
兩個通道如何做到( 2 )
• 問題 2 :一個 Slave 同時有一個非 SemiSync 通道和一個 SemiSync
通道,而 SemiSync 設置是保存在全局的
• 解決:把 SemiSync 改為 Per-Channel 的設置,將 SemiSyncSlave 類
轉移到 Master_info 結搆體中
如何判斷兩個通道日志是否連續
• 利用兩個通道收到的 GTID 序號作對比
• 利用兩個通道收到日志的 Log_file_name 和 Log_file_pos
• 如果半同步通道的日志起始點小於等於異步通道結束點,那么備庫
其實有完整的日志,反之備庫無法跟上主庫
如何判斷兩個通道日志是否連續
CASE 1: 無需補償
• 備庫兩通道數據結束點完全一致
CASE 2: 無法補償
• 備庫兩通道數據合集存在斷點
CASE 3: 可以補償
• 備庫兩通道數據合集沒有斷點
如何補償數據
• 利用半同步通道收到的日志,在異步通道應用完日志后,啟用半同
步通道應用日志
• 利用 GTID 來過濾重復 Event
• 提供 REPAIR SLAVE 命令來嘗試補償數據并返回備庫狀態,根據
Result 列的結果判斷備庫是否跟主庫一致
THANKS!

8 彭立勳-double binlog方案