內容概要
TiCDC 是一款 TiDB 增量資料同步工具,透過拉取上游 TiKV 的資料變更日誌,TiCDC 可以將資料解析為有序的行級變更資料輸出到下游。
本文是 TiCDC 原始碼解讀的第三篇,主要內容是講述 TiCDC 叢集的啟動及基本工作過程,將從如下幾個方面展開:
- TiCDC Server 啟動過程,以及 Server / Capture / Owner / Processor Manager 概念和關係
- TiCDC Changefeed 建立過程
- Etcd 在 TiCDC 叢集中的作用
- Owner 和 Processor Manager 概念介紹,以及 Owner 選舉和切換過程
- Etcd Worker 在 TiCDC 中的作用
啟動 TiCDC Server
啟動一個 TiCDC Server 時,使用的命令如下,需要傳入當前上游 TiDB 叢集的 PD 地址。
cdc server --pd=http://127.0.0.1:2379
它會啟動一個 TiCDC Server 執行例項,並且向 PD 的 ETCD Server 寫入 TiCDC 相關的後設資料,具體的 Key 如下:
/tidb/cdc/default/__cdc_meta__/capture/${capture_id}
/tidb/cdc/default/__cdc_meta__/owner/${session_id}
第一個 Key 是 Capture Key,用於註冊一個 TiCDC Server 上執行的 Capture 資訊,每次啟動一個 Capture 時都會寫入相應的 Key 和 Value。
第二個 Key 是 Campaign Key,每個 Capture 都會註冊這樣一個 Key 用於競選 Owner。第一個寫入 Owner Key 的 Capture 將成為 Owner 節點。
Server 啟動,經過了解析 Server 啟動引數,驗證引數合法性,然後建立並且執行 TiCDC Server。Server 執行的過程中,會啟動多個執行執行緒。首先啟動一個 Http Server 執行緒,對外提供 Http OpenAPI 訪問能力。其次,會建立一系列執行在 Server 級別的資源,主要作用是輔助 Capture 執行緒執行。最重要的是建立並且執行 Capture 執行緒,它是 TiCDC Server 執行的主要功能提供者。
Capture 執行時,首先會將自己的 Capture Information 投入到 ETCD 中。然後啟動兩個執行緒,一個執行 ProcessorManager
,負責所有 Processor 的管理工作。另外一個執行 campaignOwner
,其內部會負責競選 Owner,以及執行 Owner 職責。如下所示,TiCDC Server 啟動之後,會建立一個 Capture 執行緒,而 Capture 在執行過程中又會建立 ProcessorManager 和 Owner 兩個執行緒,各自負責不同的工作任務。
建立 TiCDC Changefeed
建立 changefeed 時使用的命令如下:
cdc changefeed create --server=http://127.0.0.1:8300 --sink-uri="blackhole://" --changefeed-id="blackhole-test"
其中的 server 引數標識了一個執行中的 TiCDC 節點,它記錄了啟動時候的 PD 地址。在建立 changefeed 時,server 會訪問該 PD 內的 ETCD Server,寫入一個 Changefeed 的後設資料資訊。
/tidb/cdc/default/default/changefeed/info/${changefeed_id}
/tidb/cdc/default/default/changefeed/status/${changefeed_id}
- 第一個 Key 標識了一個 Changefeed,包括該 Changefeed 的各種靜態後設資料資訊,比如
changefeed-id
,sink-uri
,以及一些其他標識執行時是為的資料。 - 第二個 Key 標識了該 Changefeed 的執行時進度,主要是記錄了
Checkpoint
和ResolvedTs
的推進情況,會不斷地週期性地更新。
Etcd 的作用
ETCD 在整個 TiCDC 叢集中承擔了非常重要的後設資料儲存功能,它記錄了 Capture 和 Changefeed 等重要資訊。同時透過不斷記錄並且更新 Changefeed 的 Checkpoint 和 ResolvedTs,保證 Changefeed 能夠穩步向前推進工作。從上圖中我們可以知道,Capture 在啟動的時候,自行將自己的後設資料資訊寫入到 ETCD 中,在此之後,Changefeed 的建立,暫停,刪除等操作,都是經由已經啟動的 TiCDC Owner 來執行的,後者負責更新 ETCD。
Owner 選舉和切換
一個 TiCDC 叢集中可以存在著多個 TiCDC 節點,每個節點上都執行著一個 campaignOwner 執行緒,負責競選 Owner,如果競選成功,則履行 Owner 的工作職責。叢集中只有一個節點會競選成功,然後執行 Owner 的工作邏輯,其他節點上的該執行緒會阻塞在競選 Owner 上。
TiCDC Owner 的選舉過程是基於 ETCD Election 實現的。每個 Capture 在啟動之後,會建立 ETCD Session,然後使用該 Session,呼叫 NewElection 方法,建立到 Owner Key /tidb/cdc/${ClusterID}/__cdc_meta/owner
的競選,然後呼叫 Election.Campaign 開始競選。基本的相關程式碼過程如下:
sess, err := concurrency.NewSession(etcdClient, ttl) // ttl is set to 10s
if err != nil {
return err
}
election := concurrency.NewElection(sess, key) // key is `/tidb/cdc/${ClusterID}/__cdc_meta/owner`
if err := election.Campaign(ctx); err != nil {
return err
}
...
感興趣的讀者 ,可以透過 Capture.Run 方法作為入口,瀏覽這部分程式碼流程,加深對該過程的理解。在真實的叢集執行過程中,多個 TiCDC 節點先後上線,在不同的時刻開始競選 Owner,第一個向 ETCD 中寫入 Owner Key 的例項將成為 Owner。如下圖所示,TiCDC-0 在 t=1 時刻寫入 Owner Key,將會成為 Owner,它在後續執行過程中如果遇到故障辭去了自己的 Ownership,那麼 TiCDC-1 將會成為新的 Owner 節點。老舊的 Owner 節點重新上線,呼叫 Election.Campaign
方法重新競選 Owner,迴圈往復。
EtcdWorker 模組
EtcdWorker 是 TiCDC 內部一個非常重要的模組,它主要負責從 ETCD 中讀取資料,對映到 TiCDC 記憶體中,然後驅動 Owner 和 ProcessorManager 執行。在具體的實現中,EtcdWorker 透過呼叫 ETCD Watch 介面,週期性地獲取到所有和 TiCDC 相關的 Key 的變化情況,然後對映到其自身維護的 GlobalReactorState
結構體中,其定義如下所示,其中記錄了 Capture,Changefeed,Owner 等資訊。
type GlobalReactorState struct {
ClusterID string
Owner map[string]struct{}
Captures map[model.CaptureID]*model.CaptureInfo
Upstreams map[model.UpstreamID]*model.UpstreamInfo
Changefeeds map[model.ChangeFeedID]*ChangefeedReactorState
....
}
Owner 和 ProcessorManager 都是一個 Reactor 介面的實現,二者都藉助 GlobalReactorState
提供的資訊來推進工作進度。具體地,Owner 透過輪詢每一個記錄在 GlobalReactorState
中的 Changefeed,讓每一個 Changefeed 都能夠被穩步推進同步狀態。同時也負責諸如 Pause / Resume / Remove 等和 Changefeed 的執行狀態相關的工作。ProcessorManager 則輪詢每一個 Processor,讓它們能夠及時更新自身的執行狀態。
總結
以上就是本文的全部內容。希望讀者能夠理解如下幾個問題:
- TiCDC Server 啟動,建立 Changefeed 和 ETCD 的互動過程。
- EtcdWorker 如何讀取 ETCD 資料並且驅動 Owner 和 Processor Manager 執行。
- TiCDC Owner 的競選和切換過程。
下一次我們將向大家介紹 TiCDC Changefeed 內部的 Scheduler 模組的工作原理。