1. 程式人生 > >DM 原始碼閱讀系列文章(七)定製化資料同步功能的實現

DM 原始碼閱讀系列文章(七)定製化資料同步功能的實現

作者:王相

本文為 DM 原始碼閱讀系列文章的第七篇,在 上篇文章 中我們介紹了 relay log 的實現,主要包括 relay log 目錄結構定義、relay log 資料的處理流程、主從切換支援、relay log 的讀取等邏輯。本篇文章我們將會對 DM 的定製化資料同步功能進行詳細的講解。

在一般的資料同步中,上下游的資料是一一對應的,即上下游的庫名、表名、列名以及每一列的值都是相同的,但是很多使用者因為業務的原因希望 DM 在同步資料到 TiDB 時進行一些定製化的轉化。下面我們將主要介紹資料同步定製化中的庫表路由(Table routing)、黑白名單(Black & white table lists)、列值轉化(Column mapping)、binlog 過濾(Binlog event filter)四個主要功能的實現。值得注意的是,由於其他一些工具(例如 TiDB Lightning 和 TiDB Binlog)也需要類似的功能,所以這四個功能都以 package 的形式維護在

tidb-tools 專案下,這樣方便使用和維護。

庫表路由(Table routing

庫表路由顧名思義就是對庫名和表名根據一定的路由規則進行轉換。比如使用者在上游多個 MySQL 例項或者 schema 有多個邏輯上相同的表,需要把這些表的資料同步到 TiDB 叢集的同一個表中,這個時候就可以使用 table-router 功能,如下圖所示:

該功能實現在 pkg/table-router 中,庫表路由的規則定義在結構 TableRule 中,其中的屬性 SchemaPatternTablePattern 用於配置原庫名和表名的模式,TargetSchemaTargetTable

用於配置目標庫和表名,即符合指定 pattern 的庫和表名都將轉化成目標庫名和表名。

使用結構 Table 對路由規則進行維護,Table 提供瞭如下方法:

方法說明
AddRule增加規則
UpdateRule修改規則
RemoveRule刪除規則
Route獲取路由後的結果

Table 結構中組合了 SelectorSelector 用於管理指定模式的庫、表的規則,提供如下方法:

方法說明
Insert增加規則
Match查詢指定的庫、表匹配到的規則
Remove刪除規則
AllRules返回所有的規則

Selector 的底層實現是 trieSelector

,使用了單詞查詢樹的結構來維護庫、表與規則的對應關係,感興趣的同學可以閱讀程式碼深入瞭解一下。 trieSelector 中使用 cache 快取了庫、表到規則的對映關係,這樣可以減少相同庫、表匹配規則的資源消耗。除了 table routing,以下的列值轉化和 binlog 過濾功能也都使用了 Selector,在下面的介紹中就不再贅述。

黑白名單(black & white table lists

黑白名單功能用來選擇同步哪些庫和表,以及不同步哪些庫和表,這部分程式碼維護在 pkg/filter 中。

黑白名單規則配置在 Rules 結構中,該結構包括 DoTablesDoDBsIgnoreTablesIgnoreDBs 四個屬性,下面以判斷表 test.t 是否應該被過濾的例子說明配置的作用:

  1. 首先 schema 過濾判斷。

    • 如果 do-dbs 不為空,則判斷 do-dbs 中是否存在一個匹配的 schema。
      • 如果存在,則進入 table 過濾判斷。
      • 如果不存在,則過濾 test.t
    • 如果 do-dbs 為空並且 ignore-dbs 不為空,則判斷 ignore-dbs 中是否存在一個匹配的 schema。
      • 如果存在,則過濾 test.t
      • 如果不存在,則進入 table 過濾判斷。
    • 如果 do-dbsignore-dbs 都為空,則進入 table 過濾判斷。
  2. 進行 table 過濾判斷。

    • 如果 do-tables 不為空,則判斷 do-tables 中是否存在一個匹配的 table。
      • 如果存在,則同步 test.t
      • 如果不存在,則過濾 test.t
    • 如果 ignore-tables 不為空,則判斷 ignore-tables 中是否存在一個匹配的 table。
      • 如果存在,則過濾 test.t
      • 如果不存在,則同步 test.t
    • 如果 do-tablesignore-tables 都為空,則同步 test.t

使用 Filter 對黑白名單進行管理,Filter 提供了 ApplyOn 方法來判斷一組 table 中哪些表可以同步。

列值轉化(Column mapping

列值轉化功能用於對指定列的值做一些轉化,主要用於分庫分表的同步場景。比較典型的場景是:在上游分表中使用自增列作為主鍵,這樣資料在同步到 TiDB 的一個表時會出現主鍵衝突,因此我們需要根據一定規則對主鍵做轉化,保證每個主鍵在全域性仍然是唯一的。

該功能實現在 pkg/column-mapping 中的 PartitionID:修改列的值的最高几位為 PartitionID 的值(只能作用於 Int64 型別的列)。

程式碼中使用 Rule 來設定 column mapping 的規則,Rule 的屬性及說明如下表所示:

屬性說明
PatternSchema匹配規則的庫的模式可以設定為指定的庫名,也可以使用萬用字元 “*” 和 “?”
PatternTable匹配規則的表的模式可以設定為指定的表名,也可以使用萬用字元 “*” 和 “?”
SourceColumn需要轉化的列列名
TargetColumn轉化後的值儲存到哪個列列名
Expression轉化表示式目前只支援 PartitionID
Arguments轉化所需要的引數Expression 為 PartitionID,引數為 InstanceID、schema 名稱字首、table 名稱字首以及字首與 ID 的分割符號

Expression 為 PartitionID 的配置和轉化的計算方式都較為複雜,下面舉個例子說明。

例如 Arguments 為 [1, “test”, “t”, “_”]1 表示資料庫例項的 InstanceID“test” 為庫名稱的字首,“t” 為表名稱的字首,“_” 為字首與 ID 的分隔符,則表 test_1.t_2SchemaID1TableID2。轉化列值時需要對 InstanceIDSchemaIDTableID 進行一定的位移計算,然後與原始的值進行或運算得出一個新的值。對於具體的計算方式,可以檢視程式碼 partitionIDcomputePartitionID。下面是一個 PartitionID 邏輯簡化後的示意圖:

使用 Mapping 結構對 column mapping 的規則進行管理,Mapping 提供列如下方法:

方法說明
AddRole增加規則
UpdateRule修改規則
RemoveRule刪除規則
HandleRowValue獲取轉化結果

binlog 過濾(binlog event filter

binlog 過濾功能支援過濾指定型別的 binlog,或者指定模式的 query,該功能維護在 pkg/binlog-filter 中。某些使用者不希望同步一些指定型別的 binlog,例如 drop table 和 truncate table,這樣就可以在下游仍然儲存這些表的資料作為備份,或者某些 SQL 語句在 TiDB 中不相容,希望可以在同步中過濾掉,都可以通過配置 binlog event filter 功能來實現。

首先需要對 binlog 進行分類,可以檢視程式碼 Event Type List。然後再定義過濾規則 BinlogEventRule,包括以下屬性:

屬性說明
SchemaPattern匹配規則的庫的模式可以設定為指定的庫名,也可以使用萬用字元 “*” 和 “?”
TablePattern匹配規則的表的模式可以設定為指定的表名,也可以使用萬用字元 “*” 和 “?”
Events規則適用於哪些型別的 binlogbinlog event 的型別
SQLPattern匹配的 SQL 的模式SQL 語句的模式,支援適用正則表示式
Action是否對符合上面要求的 binlog 進行過濾Ignore 或者 Do

例如,TiDB 對 ADD PARTITIONDROP PARTITION 語句不相容,在同步時需要過濾掉相關的 SQL 語句,就可以在 DM 中使用如下配置:

filter-partition-rule:
    schema-pattern: "*"
    sql-pattern: ["ALTER\\s+TABLE[\\s\\S]*ADD\\s+PARTITION", "ALTER\\s+TABLE[\\s\\S]*DROP\\s+PARTITION"]
    action: Ignore

如果需要過濾掉所有的 DROP DATABASE 語句,則可以在 DM 中使用如下配置:

 filter-schema-rule:
    schema-pattern: "*"
    events: ["drop database"]
    action: Ignore

程式碼中通過 BinlogEvent 結構對 binlog event 過濾規則做統一的管理,BinlogEvent 提供瞭如下的方法:

方法說明
AddRule增加規則
UpdateRule修改規則
RemoveRule刪除規則
Filter判斷指定的 binlog 是否應該過濾

小結

以上就是定製化資料同步功能中庫表路由(Table routing)、黑白名單(Black & white table lists)、列值轉化(Column mapping)、binlog 過濾(Binlog event filter)的實現介紹。歡迎大家閱讀相關程式碼深入瞭解,也歡迎給我們提 pr 優化程式碼。下一篇我們將介紹 DM 是如何支援上游 online DDL 工具(pt-osc,gh-ost)的 DDL 同步場景的。

原文閱讀https://www.pingcap.com/blog-cn/dm-source-code-reading-7/

相關推薦

DM 原始碼閱讀系列文章定製資料同步功能實現

作者:王相 本文為 DM 原始碼閱讀系列文章的第七篇,在 上篇文章 中我們介紹了 relay log 的實現,主要包括 relay

DM 原始碼閱讀系列文章Online Schema Change 同步支援

作者:lan 本文為 DM 原始碼閱讀系列文章的第八篇,上篇文章 對 DM 中的定製化資料同步功能進行詳細的講解,包括庫表路由(T

DM 原始碼閱讀系列文章shard DDL 與 checkpoint 機制的實現

作者:張學程 本文為 DM 原始碼閱讀系列文章的第九篇,在 上篇文章 中我們詳細介紹了 DM 對 online schema ch

DM 原始碼閱讀系列文章測試框架的實現

作者:楊非 本文為 DM 原始碼閱讀系列文章的第十篇,之前的文章已經詳細介紹過 DM 資料同步各元件的實現原理和程式碼解析,相信大

TiDB 原始碼閱讀系列文章初識 TiDB 原始碼

本文為 TiDB 原始碼閱讀系列文章的第二篇,第一篇文章介紹了 TiDB 整體的架構,知道 TiDB 有哪些模組,分別是做什麼的,從哪裡入手比較好,哪些可以忽略,哪些需要仔細閱讀。 這篇文章是一篇入門文件,難度係數比較低,其中部分內容可能大家在其他渠道已經看過

TiKV 原始碼解析系列文章gRPC Server 的初始和啟動流程

作者:屈鵬 本篇 TiKV 原始碼解析將為大家介紹 TiKV 的另一週邊元件—— grpc-rs。grpc-rs 是 PingCA

TiDB Binlog 原始碼閱讀系列文章Pump server 介紹

作者: satoru 在 上篇文章 中,我們介紹了 TiDB 如何通過 Pump client 將 binlog 發往 Pump,

TiDB 原始碼閱讀系列文章二十Table Partition

作者:肖亮亮 Table Partition 什麼是 Table Partition Table Partition 是指根據一定規則,將資料庫中的一張表分解成多個更小的容易管理的部分。從邏輯上看只有一張表,但是底層卻是由多個物理分割槽組成。相信對有關係型資料庫使用背景的使用者來

TiDB 原始碼閱讀系列文章十九tikv-client

上篇文章 中,我們介紹了資料讀寫過程中 tikv-client 需要解決的幾個具體問題,本文將繼續介紹 tikv-client 裡的兩個主要的模組——負責處理分散式計算的 copIterator 和執行二階段提交的 twoPhaseCommitter。 copIterator cop

TiDB 原始碼閱讀系列文章二十一基於規則的優化 II

在 TiDB 原始碼閱讀系列文章(七)基於規則的優化 一文中,我們介紹了幾種 TiDB 中的邏輯優化規則,包括列剪裁,最大最小消除,投影消除,謂詞下推和構建節點屬性,本篇將繼續介紹更多的優化規則:聚合消除、外連線消除和子查詢優化。 聚合消除 聚合消除會檢查 SQL 查詢中 Group By 語句所使用的列是否

TiKV 原始碼解析系列文章Prometheus

開發十年,就只剩下這套架構體系了! >>>   

讀logback原始碼系列文章——記錄日誌

今天晚上本來想來寫一下Logger怎麼記錄日誌,以及Appender元件。不過9點才從丈母孃家回來,又被幾個兄弟喊去喝酒,結果回來晚了,所以時間就只夠寫一篇Logger類的原始碼分析了。Appender找時間再寫 上篇部落格介紹了LoggerContext怎麼生成Logger

讀logback原始碼系列文章——記錄日誌的實際工作類Encoder

本系列的部落格從logback怎麼對接slf4j開始,逐步介紹了LoggerContext、Logger、ContextInitializer、Appender、Action等核心元件。跟讀logback的原始碼到這個程度,雖然不能說精通,不過至少日常的配置,和簡單的自定義擴

TiKV 原始碼解析系列文章十一Storage

作者:張金鵬 背景知識 TiKV 是一個強一致的支援事務的分散式 KV 儲存。TiKV 通過 raft 來保證多副本之間的強一致,

Java系列文章

java 學習JVMJVM系列:類裝載器的體系結構 JVM系列:Class文件檢驗器JVM系列:安全管理器JVM系列:策略文件Java垃圾回收機制深入剖析Classloader(一)--類的主動使用與被動使用深入剖析Classloader(二)-根類加載器,擴展類加載器與系統類加載器深入理解JVM—JVM內存

openstack系列文章

cnblogs 調度器 5.5 min 代碼位置 虛機 inux latest 階段 學習 openstack 的系列文章 - Nova Nova 基本概念 Nova 架構 openstack Log Nova 組件介紹 Nova 操作介紹 1. Nova 基本概念

SVM支援向量機系列理論 線性支援向量機與L2正則 Platt模型

7.1 軟間隔SVM等價於最小化L2正則的合頁損失 上一篇 說到, ξi ξ i \xi_i 表示偏離邊界的度量,若樣本點

Spring Boot乾貨系列預設日誌logback配置解析

前言 今天來介紹下Spring Boot如何配置日誌logback,我剛學習的時候,是帶著下面幾個問題來查資料的 如何引入日誌? 日誌輸出格式以及輸出方式如何配置? 程式碼中如何使用? 正文       Spring Boot在所有

Git 系列文章——GitHub 介紹

正文之前 相信大部分都人都知道 GitHub,對,就是被微軟收購的全球最大交友網站。目前博主還處於學生階段,所以一直處於這樣的迴圈中: git add git commit git pull git push 但是本著要深入學習的心態,以及目前參加掘金翻譯

Git 系列文章—— Git 基本用法

正文之前 上一篇文章簡單介紹了 Git 和 GitHub,這一篇文章用一個倉庫來作為例子介紹 Git 的基本用法,而不是單純地列出每一條 Git 命令 這篇文章來自我的部落格 正文 1. 倉庫的初始操作 初始化 首先我先在本地存放 GitHub 倉庫的資料夾