作者:lan
本文為 DM 源碼閱讀系列文章的第五篇。上篇文章 介紹了 dump 和 load 兩個數據同步處理單元的設計實現,對核心 interface 實現、數據導入並發模型、數據導入暫停或中斷的恢復進行了分析。本篇文章將詳細地介紹 DM 核心處理單元 Binlog replication,內容包含 binlog 讀取、過濾、路由、轉換,以及執行等邏輯。文內涉及到 shard merge 相關邏輯功能,如 column mapping、shard DDL 同步處理,會在 shard merge 篇單獨詳細講解,這裡就不贅述了。
從上圖可以大致了解到 Binlog replication 的邏輯處理流程,對應的 邏輯入口代碼。
1.從 relay log 或者 MySQL/MariaDB 讀取 binlog events。
2.對 binlog events 進行處理轉換(transformation),這裡可以做三類操作:
3.executor 對 job 進行衝突檢測,然後根據固定規則分發給對應的 worker 執行。
4.定期保存 binlog position/gtid 到 checkpoint。
Binlog replication 支持兩種方式讀取 binlog events:
兩種方式都提供了同樣的讀取方法,處理核心都是 go-mysql。該庫主要提供了兩個功能:
更多的處理細節會在下篇關於 relay log 的文章中進行介紹,迫不及待的小夥伴可以先翻閱一下相關代碼實現。
處理程序拿到解析好的 binlog event 後,根據 binlog 的類型來對 binlog 進行分類處理。Binlog replication 主要關心以下類型的 binlog event :
Binlog replication 數據處理單元會對每一類 binlog event 進行以下的處理步驟,具體實現的處理順序可能略有差異,以代碼實現為準。
Binlog replication 會從兩個維度對 binlog event 來進行過濾:
row event過濾處理 和query event過濾處理 的實現在邏輯上面存在一些差異:
row event過濾處理
query event過濾處理
row event
query event
binlog 過濾完成之後,對於需要同步的表就會根據過濾步驟獲得的庫名和表名,通過 路由規則 轉換得到需要同步到的目標庫名和表名,在接下來的轉換步驟來使用目標庫名和表名來轉換出正確的 DML 和 DDL statement。
row event 轉換處理和 query event 轉換處理的實現存在一些差異,這裡分開來講述。
row event 轉換處理通過三個轉換函數生成對應的 statements:
generate insert sqls
write rows event
replace into statements
generate update sqls
safe mode = true
safe mode = false
generate delete sqls
query event 轉換處理:
通過轉換處理之後,將不同的 binlog event 包裝成不同的 job 發送到 executor 執行:
row event -> insert/update/delete job
query event -> ddl job
xid event -> xid job
binlog 順序同步模型要求按照 binlog 順序一個一個來同步 binlog event,這樣的順序同步勢必不能滿足高 QPS 低同步延遲的同步需求,並且不是所有的 binlog 涉及到的操作都存在衝突。Binlog replication 採用衝突檢測機制,鑒別出來需要順序執行的 jobs,在確保這些 jobs 的順序執行的基礎上,最大程度地保持其他 job 的並發執行來滿足性能方面的要求。
衝突檢測流程如下:
衝突檢測實現比較簡單,根據轉換步驟獲得每條 statement 對應的 primary/unique key 信息,來進行交集檢測,如果存在交集那麼認定是需要順序的執行兩條 statement,請參考 具體實現代碼。
primary/unique key
job 分發到對應的 worker 後,worker 根據一定的規則來批量執行這些 job,如下:
根據上面三個規則可以很快地將已經分發的 jobs 應用到下游 TiDB。
本篇文章詳細地介紹 DM 核心處理單元 Binlog replication,內容包含 binlog 讀取、過濾、路由、轉換,以及執行等邏輯。下一篇我們會對 relay log 數據處理單元的設計進行詳細的講解。
更多閱讀: