DB與ES組合應用內的數據實時同步

?問題?

1. 同步實時性:數據在DB更新后需多久才更新到Elasticsearch,多久的時間是應用系統可以接受范圍,一般需要控制在1s以內,如果是分鐘以上,屬于離線同步。

2.數據一致性,數據頻繁在DB變更修改,更新到ES后如何保證數據與DB一致,在容許的時間范圍內應用系統查詢的數據有效可接受的,如果變更出現覆蓋等,那數據是無效的,應用系統是不可接受的,如何修復。

?同步模式

1.推送Push模式,數據源主動將變更數據推送到目標源,如RabbitMQ,服務端會主動MQ發送到客戶端。

2. 拉取Pull模式,目標源定時去數據源拉取變更數據,如Mysql數據庫的數據主從同步,Slave會去Master拉取變更數據。

3. 推拉結合,數據源與目標源之間,既有推送方式也有拉取方式,此種模式一般會借助于中間媒介實現,如基于Kafka的游戲日志應用,數據源(采集端)會將日志數據發送到Kafka集群,目標源會定期的從Kafka拉取數據更新。

技術方案

1. 同步雙寫,更新DB時同步更新ES。此技術方案最簡單,附帶問題最多,數據沖突,數據覆蓋,數據丟失,處處是坑,謹慎選擇。

2. 異步雙寫,更新DB之后,記錄一條MQ,MQ通知消費端,消費端反向查詢DB數據,最后更新到ES。此技術方案與業務系統耦合嚴重,需要每個業務專門編寫相關程序,不利于快速響應需求。

3. CDC,全稱Change Data Capture,變更數據捕捉,從數據庫內部捕捉變更數據,將變更數據推送到中間程序中,中間程序邏輯實現同步推送到ES。CDC機制速度極快,數據精準,與應用程序耦合少,可抽象脫離業務系統,適合大規模使用。?

CDC機制原有設計是為了同類型數據庫之間數據同步,應用在主從同步高可用方面,所以同類型數據庫之間數據同步非常容易實現,數據庫廠商本身天然支持,經過多年實戰驗證高效可靠。幾乎所有數據庫產品都支持:Postgresql 有 Logical Decoding,Sqlserver 有 Change data capture 和 Change Tracking,Oralce 有 Redo log和 Oralce Golden Gate,Mongodb 有 Replicate sets,Elasticsearch 有 Translog。

相反,在異構數據庫之間實現數據同步是比較復雜的,數據鏈路長,中間涉及到的技術點特別多,且每一步都非常關鍵。

Mysql同步到ES

數據從Mysql同步到ES主要涉及到幾個技術關鍵點

1.Binlog機制

2.Canal中間件

3.Kakfa中間件

4.同步應用程序(業務型開發中間件)

Binlog機制

Binlog是Mysql自帶功能機制,設計之初是為了數據庫之間主從同步;

1.Master主庫,啟動Binlog機制,將變更數據寫入Binlog文件

2.Slave從庫,從Master主庫拉取binlon數據,回放Binlog,更新從庫數據啟用Binlog注意:

? ? ?Master主庫一般會有多臺Slave訂閱,且Master主庫要支持業務系統實時變更操作,服務器資源會有瓶頸

? ? ? 需要同步的數據表一定要有主鍵

Canal中間件

Canal是Mysql的中間件產品,專門應用在數據同步

1.偽裝Slave從庫,

2.訂閱Mysql同步

3.拉取Binlog變更數據,

4.回放Binlog變更數據,

5.解析Binlog數據為Json,報文記錄了新舊數據,數據庫數據表,更新方式;

6.輸出變更數據,并保證變更順序,輸出目的源支持很多,常規的一般輸出到kafka

????配置cannal注意點

1.Canal基于Jvm運行,數據處理能力不如Mysql,Canal需要配置集群模式。一組Canal集群不能支持太多的數據庫實例。

2.若是數據庫做了水平的分庫分表,原有Canal是不能識別為一類數據源,需要稍微修改部分代碼

3.建議Canal訂閱Slave從機,因為Master是業務主庫,主庫承擔的業務系統職責太多

4. Binlog日志模式建議啟動Gtid,Canal訂閱的數據庫如果出現故障,需要基于此切換到其他數據庫。

5.數據輸出到Kafka,若數據庫是做了分庫分表的,需要修改Canal部分代碼。

6.設置Kafka分區鍵相同,保障相同數據變更順序。

Kafka中間件

使用Kafka作為中間緩存,主要基于以下方面考慮

1.分區特性,Kafka支持分區,并發性能好,數據吞吐能力超過mysql,性能不會成為瓶頸

2.分區順序存儲,Kafka數據存儲是有順序的,設置好主鍵,保障Binlog變更順序

3.消費順序,客戶端消費Kafk數據,會基于Offset,按順序消費,保障Binlog變更順序

4.消費組:嚴格意義上講,Kafka并非消息隊列,應算消息流,一個數據表可能會映射到多個索引,這就需要設置不同的消費組,保障多個消費組之間不沖突覆蓋,同樣的變更數據有多次重復消費

同步程序

同步程序當前基于Java自主開發,當前的主流同步工具不能很好支持自定義需求,主要包括兩大程序

1. 同步任務調度程序

同步調度配置,配置同步任務,配置同步映射關系,DB到ES的映射,Kafka到ES的映射

同步調度分配,同步任務操作,啟動、停止、重新設置;同步任務分配,指定并行度等。

2.同步任務執行程序

執行任務,將數據從Kafka經過映射寫入到ES中,主要由四大模塊組成

(1)Kafka模塊,拉取消費數據,記錄消費位置

(2)Mapper模塊,執行映射過程,數據表與索引映射,表字段與索引字段映射,生成指定的Json格式數據

(3)Elastic模塊,將Mapper生成好的Json數據提交到ES中,Bulk局部更新,設置doc_as_upsert為true,成功則提交消費記錄位置,失敗則走異常邏輯

(4)Schedule模塊,基于線程級別執行同步任務,支持同步任務啟動暫停等狀態操作,實時匯總同步任務的狀態指標數據

數據同步全過程

1. 數據從DB更新到ES,中間經過多個環節,同步模式既有推送,也拉取,且多次結合完成。

2. Mysql寫入到本地binlog,推送模式

3. Canal讀取binlog寫入Kafka,先是拉取模式,后是推送模式

4. Worker同步程序從Kafka讀寫數據,經過處理寫入到ES,先是拉取模式,后是推送模式


注意事項

DB到ES實時同步整體項目鏈路很長,且涉及技術點較多,任意環節都會導致一些問題,特別注意:

1. DB刷數據問題,由于DB是批量更新,會出現部分性能瓶頸

2. DB多表關聯深度問題,DB多表直接關聯最好的關系是1對1,主要ES映射也可以基于主鍵關聯更新,無需反向查詢

3. ES高級類型限制問題,ES本身支持很多高級數據類型,但這些在同步程序中最好不要使用


有待探索問題

1.數據校驗,DB數據雖然同步到ES中,但目前是沒有有效的方法去校驗正確性的,傳統的方式校驗方式是隨機兩邊查詢對比,非常的低效,需要探討更好的數據比對方法;

2. 數據修復,當數據發現不正確時需要自動能夠修復,但由于數據校驗的低效,數據修復的準確性有待考量

3. 技術演進,數據同步程序基于Java開發,但做了很多非業務時間工作,程序大量的工作在調度,考慮引入Flink平臺,由平臺負責底層資源調度,上層只需配置同步映射。


? ?采取CDC這種方案也是基于馬蜂窩已有的經驗分享,設計思路一樣,技術實現不一樣。數據同步整體技術實現中間環節很多,任意技術點都需要了解透徹,否則會出現很多致命事故,需要多人團隊協作完成。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。