1. 程式人生 > >實時資料訂閱與分發系統概述

實時資料訂閱與分發系統概述

實時資料訂閱與分發系統可以將業務資料來源變更實時分發分發到訊息總線上,並維護訊息的統一格式,提供通用的客戶端框架供訊息生產者與下游業務接入。

一般能用於以下場景:

  • 索引構建:MySQL到ES

  • 快取管理:MySQL到Redis或本地cache

  • 資料庫映象

  • 實時備份

  • 價格變化等重要業務資訊訂閱

     

實時資料訂閱與分發系統一般都有如下幾個核心模組構成:

  • Change Data Capture(變更資料抓取,CDC):負責實時抓取業務資料來源的變更訊息;
  • 訊息中介軟體:支撐訊息的分發與堆積;
  • Client:為生產者與消費者提供統一的接入途徑,解決序列化、offset管理、監控報警等共性問題。

本文以Databus(
https://github.com/linkedin/databus)為例,來說明一個實時資料訂閱與分發系統的基本構成與原理。

1. 簡介

 

Databus 是一個實時的低延遲資料抓取系統, 它抓取業務資料來源的實時變更, 併發送到中繼(Databus Relay), 下游業務從中繼獲得變更資料進行業務處理:

根據Linkdin的介紹, Databus有以下特性:

  • 來源獨立:Databus支援多種資料來源的變更抓取,包括Oracle和MySQL。

  • 可擴充套件、高可用:Databus能擴充套件到支援數千消費者和事務資料來源,同時保持高度可用性。

  • 事務按序提交:Databus能保持來源資料庫中的事務完整性,並按照事務分組和來源的提交順序交付變更事件。

  • 低延遲:資料來源變更完成後,Databus能在微秒級內將事務提交給消費者。

  • 無限回溯:Databus對消費者支援無限回溯能力。當消費者需要產生資料的完整拷貝時(比如新的搜尋索引), 直接進行一次全量回溯即可。

2. 系統設計

 

Databus的結構與工作流如下圖:

  • 通過CDC訂閱資料庫變更

  • 將變更訊息放入Relay的快取佇列

  • 各個client對佇列中的訊息進行消費

我們可以看到,核心元件為五個部分:

1)DatabusEventProducer

負責實時資料抓取CDC, 針對MySQL資料來源, 開源方案提供了基於OpenReplicator(一個Binlog解析框架)的方案。

2)SchemaRegistry

註冊DatabusEvent對應的Schema, 所有DatabusEvent需要按Schema進行序列化, 並在訊息中保持Schema資訊。

3)DatabusRelay

基於Netty實現的一個Server, 內部維護高效能的快取訊息佇列RingBuffer,作為訂閱訊息的記憶體訊息中介軟體,保證了訊息的有序性。

4)BootstrapService

BootStrapService是特殊的DatabusClient, 它將來自DatabusRelay中的所有資料寫入MySQL, 當客戶端需要無限回溯時, 便請求BootstrapService拉取歷史資料。

有很多系統是將訊息直接投遞到kafka或者rocketMQ,就能同時實現了DatabusRelays和BootstrapService的功能。

5)ClientLib:

ClientLib就是消費客戶端Client,用來實時接收變更訊息。其中封裝了一些資料抓取細節, 比如當回溯的SCN(System Change Number)在中繼上不存在時自動請求BootstrapService, 回溯完成後切回中繼。

3. 核心模組淺析

 

DatabusRelay

DatabusRelay模組可類比為基於記憶體實現的訊息佇列, 下面是DatabusRelay的結構圖:

我們可以看到,DatabusRelay運行於Netty容器中。

 

同時,它會啟動一系列EventProducer, 從資料來源或其他Relays拉取實時增量資料並寫入EventBuffers。

EventBuffers由多RingBuffer組成, RingBuffer通過mmap進行寫盤持久化。這種設計下,使得EventProducer與DatabusRelay在同一個Netty容器中, 避免了rpc呼叫,效率更高。

所有的增量資料, 都有一個System Change Number(SCN), 這個SCN由EventProducer產生, 保證全域性遞增, DatabusRelay需要記錄每個RingBuffer目前的MaxSCN(類似Kafka的offset), 並使用MaxSCN Reader/Writer進行持久化。持久化方式是本地檔案儲存。

DatabusClient

DatabusClient用於消費來自DatabusRelay的資料, 它作為一個lib提供給需要接入的服務。下面是官方給出的DatabusClient架構圖:

 

客戶端程式碼以回撥形式註冊到DatabusClient上, 並宣告自己關心的資源。

啟動後, Client通過讀取當前checkpoint, 假如checkpoint在Relay中不存在, 那麼啟動Relay Puller 和 Bootstrap Puller分別從Relay和Bootstrap Service拉取資料, 並寫入本地EventBuffer, Dispatcher不斷poll EventBuffer中的資料, 分發到Callback Driver上, 並通知Checkpoint Persistence Provider記錄當前讀取的checkpoint(即SCN)。

這樣就能實現對訂閱訊息的全量回溯, 向客戶端程式碼遮蔽Relay與Boostrap Service的差異。

4. 擴充套件性

 

在上面的DataBus Relay的架構圖可以看到

Event Producer除了可以訂閱資料來源之外,還能訂閱其他Relays,可以通過Relay Chaining進行擴充套件。在Follower Relay中使用RelayEventProducer, 從Master Relay拉取資料, 這兩個Relay就組成了Master和Follower的鏈式結構。當然,這種設計會使得變更資料在多個Relay中冗餘,有些浪費空間。

都看到最後了,原創不易,點個關注,點個贊吧~
知識碎片重新梳理,構建Java知識圖譜:github.com/saigu/JavaK…(歷史文章查閱非常方便)