DM 源碼閱讀系列文章(二)總體架構介紹

做者:張學程git

本文爲 DM 源碼閱讀系列文章的第二篇,第一篇文章 簡單介紹了 DM 源碼閱讀的目的和規劃,以及 DM 的源碼結構以及工具鏈。從本篇文章開始,咱們會正式開始閱讀 DM 的源碼。github

本篇文章主要介紹 DM 的總體架構,包括 DM 有哪些組件、各組件分別實現什麼功能、組件之間交互的數據模型和 RPC 實現。sql

總體架構

經過上面的 DM 架構圖,咱們能夠看出,除上下游數據庫及 Prometheus 監控組件外,DM 自身有 DM-master、DM-worker 及 dmctl 這 3 個組件。其中,DM-master 負責管理和調度數據同步任務的各項操做,DM-worker 負責執行具體的數據同步任務,dmctl 提供用於管理 DM 集羣與數據同步任務的各項命令。數據庫

DM-master

DM-master 的入口代碼在 cmd/dm-master/main.go,其中主要操做包括:網絡

  1. 調用 cfg.Parse 解析命令行參數與參數配置文件架構

  2. 調用 log.SetLevelByString 設置進程的 log 輸出級別函數

  3. 調用 signal.Notify 註冊系統 signal 通知,用於接受到指定信號時退出進程等工具

  4. 調用 server.Start 啓動 RPC server,用於響應來自 dmctl 與 DM-worker 的請求oop

在上面的操做中,能夠看出其中最關鍵的是步驟 4,其對應的實現代碼在 dm/master/server.go 中,其核心爲 Server 這個 struct,其中的主要 fields 包括:命令行

  • rootLis, svr:監聽網絡鏈接,分發 RPC 請求給對應的 handler。

  • workerClients:維護集羣各 DM-worker ID 到對應的 RPC client 的映射關係。

  • taskWorkers:維護用於執行各同步(子)任務的 DM-worker ID 列表。

  • lockKeeper:管理在協調處理 sharding DDL 時的 lock 信息。

  • sqlOperatorHolder:管理手動 skip/replace 指定 sharding DDL 時的 SQL operator 信息。

在本篇文章中,咱們暫時不會關注 lockKeepersqlOperatorHolder,其具體的功能與代碼實現會在後續相關文章中進行介紹。

在 DM-master Server 的入口方法 Start 中:

  1. 經過 net.Listen 初始化 rootLis 並用於監聽 TCP 鏈接(藉助 soheilhy/cmux,咱們在同一個 port 同時提供 gRPC 與 HTTP 服務)。

  2. 根據讀取的配置信息(DeployMap),初始化用於鏈接到各 DM-worker 的 RPC client 並保存在 workerClients 中。

  3. 經過 pb.RegisterMasterServer 註冊 gRPC server(svr),並將該 Server 做爲各 services 的 implementation。

  4. 調用 m.Serve 開始提供服務。

DM-master 提供的 RPC 服務包括 DM 集羣管理、同步任務管理等,對應的 service 以 Protocol Buffers 格式定義在 dm/proto/dmmaster.proto 中,對應的 generated 代碼在 dm/pb/dmmaster.pb.go 中。各 service 的具體實如今 dm/master/server.go 中(*Server)。

DM-worker

DM-worker 的結構與 DM-master 相似,其入口代碼在 cmd/dm-worker/main.go 中。各 RPC services 的 Protocol Buffers 格式定義在 dm/proto/dmworker.proto 中,對應的 generated 代碼在 dm/pb/dmworker.pb.go 中,對應的實現代碼在 dm/worker/server.go 中(*Server)。DM-worker 的啓動流程與 DM-master 相似,在此再也不額外說明。

Server 這個 struct 的主要 fields 除用於處理 RPC 的 rootLissvr 外,另外一個是用於管理同步任務與 relay log 的 worker(相關代碼在 dm/worker/worker.go 中)。

Worker 這個 struct 中,主要 fields 包括:

  • subTasks:維護該 DM-worker 上的全部同步子任務信息。

  • relayHolder:對 relay 處理單元相關操做進行簡單封裝,轉發相關操做請求給 relay 處理單元,獲取 relay 處理單元的狀態信息。

  • relayPurger:根據用戶配置及相關策略,嘗試按期對 relay log 進行 purge 操做。

數據同步子任務管理的代碼實現主要在 dm/worker/subtask.go 中, relay 處理單元管理的代碼實現主要在 dm/worker/relay.go 中,對 relay log 進行 purge 操做的代碼實現主要在 relay/purger pkg 中。在本篇文章中,咱們暫時只關注 DM 架構相關的實現,上述各功能的具體實現將在後續的相關文章中展開介紹。

Worker 的入口方法爲 Start,其中的主要操做包括:

  1. 經過 w.relayHolder.Start 啓動 relay 處理單元,開始從上游拉取 binlog。

  2. 經過 w.relayPurger.Start 啓動後臺 purge 線程,嘗試對 relay log 進行按期 purge。

其餘的操做主要還包括處理 Server 轉發而來的同步任務管理、relay 處理單元管理、狀態信息查詢等。

dmctl

dmctl 的入口代碼在 cmd/dm-ctl/main.go,其操做除參數解析與 signal 處理外,主要爲調用 loop 進入命令處理循環、等待用戶輸入操做命令。

loop 中,咱們藉助 chzyer/readline 提供命令行交互環境,讀取用戶輸入的命令並輸出命令執行結果。一個命令的處理流程爲:

  1. 調用 l.Readline 讀取用戶輸入的命令

  2. 判斷是否須要退出命令行交互環境(exit 命令)或須要進行處理

  3. 調用 ctl.Start 進行命令分發與處理

dmctl 的具體命令處理實如今 dm/ctl pkg 中,入口爲 dm/ctl/ctl.go 中的 Start 方法,命令的分發與參數解析藉助於 spf13/cobra。命令的具體功能實如今相應的子 pkg 中:

  • master:dmctl 與 DM-master 交互的命令,是當前 DM 推薦的命令交互方式。

  • worker:dmctl 與 DM-worker 交互的命令,主要用於開發過程當中進行 debug,當前並無實現全部 DM-worker 支持的命令,將來可能廢棄。

  • common:多個命令依賴的通用操做及 dmctl 依賴的配置信息等。

每一個 dmctl 命令,其主要對應的實現包括 3 個部分:

  1. 在各命令對應的實現源文件中,經過 New***Cmd 形式的方法建立 cobra.Command 對象。

  2. dm/ctl/ctl.go 中經過調用 rootCmd.AddCommand 添加該命令。

  3. 在各命令對應的實現源文件中,經過 ***Func 形式的方法實現參數驗證、RPC 調用等具體功能。

任務管理調用鏈示例

讓咱們用一個啓動數據同步任務的操做示例來講明 DM 中的組件交互與 RPC 調用流程。

  1. 用戶在 dmctl 命令行交互環境中輸入 start-task 命令及相應參數。

  2. dmctl 在 dm/ctl/ctl.goStart 方法中進行命令分發,請求 dm/ctl/master/start_task.go 中的 startTaskFunc 處理命令。

  3. startTaskFunc 經過 cli.StartTask 調用 DM-master 上的 RPC 方法。

  4. DM-master 中的 Server.StartTask 方法(dm/master/server.go)響應來自 dmctl 的 RPC 請求。

  5. Server.StartworkerClients 中獲取任務對應 DM-worker 的 RPC client,並經過 cli.StartSubTask 調用 DM-worker 上的 RPC 方法。

  6. DM-worker 中的 Server.StartSubTask 方法(dm/worker/server.go)響應來自 DM-master 的 RPC 請求。

  7. Server.StartSubTask 中將任務管理請求轉發給 Worker.StartSubTaskdm/worker/worker.go),並將處理結果經過 RPC 返回給 DM-master。

  8. DM-master 將 DM-worker 返回的 RPC 響應從新封裝後經過 RPC 返回給 dmctl。

  9. dmctl 經過 common.PrettyPrintResponse 輸出命令操做的 RPC 響應。

小結

在本篇文章中,咱們主要介紹了 DM 的各個組件的入口函數,最後以 dmctl 的 start-task 爲例介紹了交互的調用流程細節。下一篇文章咱們會開始介紹 DM-worker 組件內各數據同步處理單元(relay-unit, dump-unit, load-unit, sync-unit)的設計原理與具體實現。

相關文章
相關標籤/搜索