?問題?
1. 同步實(shí)時(shí)性:數(shù)據(jù)在DB更新后需多久才更新到Elasticsearch,多久的時(shí)間是應(yīng)用系統(tǒng)可以接受范圍,一般需要控制在1s以內(nèi),如果是分鐘以上,屬于離線同步。
2.數(shù)據(jù)一致性,數(shù)據(jù)頻繁在DB變更修改,更新到ES后如何保證數(shù)據(jù)與DB一致,在容許的時(shí)間范圍內(nèi)應(yīng)用系統(tǒng)查詢的數(shù)據(jù)有效可接受的,如果變更出現(xiàn)覆蓋等,那數(shù)據(jù)是無效的,應(yīng)用系統(tǒng)是不可接受的,如何修復(fù)。
?同步模式
1.推送Push模式,數(shù)據(jù)源主動將變更數(shù)據(jù)推送到目標(biāo)源,如RabbitMQ,服務(wù)端會主動MQ發(fā)送到客戶端。
2. 拉取Pull模式,目標(biāo)源定時(shí)去數(shù)據(jù)源拉取變更數(shù)據(jù),如Mysql數(shù)據(jù)庫的數(shù)據(jù)主從同步,Slave會去Master拉取變更數(shù)據(jù)。
3. 推拉結(jié)合,數(shù)據(jù)源與目標(biāo)源之間,既有推送方式也有拉取方式,此種模式一般會借助于中間媒介實(shí)現(xiàn),如基于Kafka的游戲日志應(yīng)用,數(shù)據(jù)源(采集端)會將日志數(shù)據(jù)發(fā)送到Kafka集群,目標(biāo)源會定期的從Kafka拉取數(shù)據(jù)更新。
技術(shù)方案
1. 同步雙寫,更新DB時(shí)同步更新ES。此技術(shù)方案最簡單,附帶問題最多,數(shù)據(jù)沖突,數(shù)據(jù)覆蓋,數(shù)據(jù)丟失,處處是坑,謹(jǐn)慎選擇。
2. 異步雙寫,更新DB之后,記錄一條MQ,MQ通知消費(fèi)端,消費(fèi)端反向查詢DB數(shù)據(jù),最后更新到ES。此技術(shù)方案與業(yè)務(wù)系統(tǒng)耦合嚴(yán)重,需要每個(gè)業(yè)務(wù)專門編寫相關(guān)程序,不利于快速響應(yīng)需求。
3. CDC,全稱Change Data Capture,變更數(shù)據(jù)捕捉,從數(shù)據(jù)庫內(nèi)部捕捉變更數(shù)據(jù),將變更數(shù)據(jù)推送到中間程序中,中間程序邏輯實(shí)現(xiàn)同步推送到ES。CDC機(jī)制速度極快,數(shù)據(jù)精準(zhǔn),與應(yīng)用程序耦合少,可抽象脫離業(yè)務(wù)系統(tǒng),適合大規(guī)模使用。?

CDC機(jī)制原有設(shè)計(jì)是為了同類型數(shù)據(jù)庫之間數(shù)據(jù)同步,應(yīng)用在主從同步高可用方面,所以同類型數(shù)據(jù)庫之間數(shù)據(jù)同步非常容易實(shí)現(xiàn),數(shù)據(jù)庫廠商本身天然支持,經(jīng)過多年實(shí)戰(zhàn)驗(yàn)證高效可靠。幾乎所有數(shù)據(jù)庫產(chǎn)品都支持:Postgresql 有 Logical Decoding,Sqlserver 有 Change data capture 和 Change Tracking,Oralce 有 Redo log和 Oralce Golden Gate,Mongodb 有 Replicate sets,Elasticsearch 有 Translog。
相反,在異構(gòu)數(shù)據(jù)庫之間實(shí)現(xiàn)數(shù)據(jù)同步是比較復(fù)雜的,數(shù)據(jù)鏈路長,中間涉及到的技術(shù)點(diǎn)特別多,且每一步都非常關(guān)鍵。
Mysql同步到ES
數(shù)據(jù)從Mysql同步到ES主要涉及到幾個(gè)技術(shù)關(guān)鍵點(diǎn)
1.Binlog機(jī)制
2.Canal中間件
3.Kakfa中間件
4.同步應(yīng)用程序(業(yè)務(wù)型開發(fā)中間件)
Binlog機(jī)制
Binlog是Mysql自帶功能機(jī)制,設(shè)計(jì)之初是為了數(shù)據(jù)庫之間主從同步;
1.Master主庫,啟動Binlog機(jī)制,將變更數(shù)據(jù)寫入Binlog文件
2.Slave從庫,從Master主庫拉取binlon數(shù)據(jù),回放Binlog,更新從庫數(shù)據(jù)啟用Binlog注意:
? ? ?Master主庫一般會有多臺Slave訂閱,且Master主庫要支持業(yè)務(wù)系統(tǒng)實(shí)時(shí)變更操作,服務(wù)器資源會有瓶頸
? ? ? 需要同步的數(shù)據(jù)表一定要有主鍵
Canal中間件
Canal是Mysql的中間件產(chǎn)品,專門應(yīng)用在數(shù)據(jù)同步
1.偽裝Slave從庫,
2.訂閱Mysql同步
3.拉取Binlog變更數(shù)據(jù),
4.回放Binlog變更數(shù)據(jù),
5.解析Binlog數(shù)據(jù)為Json,報(bào)文記錄了新舊數(shù)據(jù),數(shù)據(jù)庫數(shù)據(jù)表,更新方式;
6.輸出變更數(shù)據(jù),并保證變更順序,輸出目的源支持很多,常規(guī)的一般輸出到kafka

????配置cannal注意點(diǎn)
1.Canal基于Jvm運(yùn)行,數(shù)據(jù)處理能力不如Mysql,Canal需要配置集群模式。一組Canal集群不能支持太多的數(shù)據(jù)庫實(shí)例。
2.若是數(shù)據(jù)庫做了水平的分庫分表,原有Canal是不能識別為一類數(shù)據(jù)源,需要稍微修改部分代碼
3.建議Canal訂閱Slave從機(jī),因?yàn)镸aster是業(yè)務(wù)主庫,主庫承擔(dān)的業(yè)務(wù)系統(tǒng)職責(zé)太多
4. Binlog日志模式建議啟動Gtid,Canal訂閱的數(shù)據(jù)庫如果出現(xiàn)故障,需要基于此切換到其他數(shù)據(jù)庫。
5.數(shù)據(jù)輸出到Kafka,若數(shù)據(jù)庫是做了分庫分表的,需要修改Canal部分代碼。
6.設(shè)置Kafka分區(qū)鍵相同,保障相同數(shù)據(jù)變更順序。
Kafka中間件
使用Kafka作為中間緩存,主要基于以下方面考慮
1.分區(qū)特性,Kafka支持分區(qū),并發(fā)性能好,數(shù)據(jù)吞吐能力超過mysql,性能不會成為瓶頸
2.分區(qū)順序存儲,Kafka數(shù)據(jù)存儲是有順序的,設(shè)置好主鍵,保障Binlog變更順序
3.消費(fèi)順序,客戶端消費(fèi)Kafk數(shù)據(jù),會基于Offset,按順序消費(fèi),保障Binlog變更順序
4.消費(fèi)組:嚴(yán)格意義上講,Kafka并非消息隊(duì)列,應(yīng)算消息流,一個(gè)數(shù)據(jù)表可能會映射到多個(gè)索引,這就需要設(shè)置不同的消費(fèi)組,保障多個(gè)消費(fèi)組之間不沖突覆蓋,同樣的變更數(shù)據(jù)有多次重復(fù)消費(fèi)

同步程序
同步程序當(dāng)前基于Java自主開發(fā),當(dāng)前的主流同步工具不能很好支持自定義需求,主要包括兩大程序
1. 同步任務(wù)調(diào)度程序
同步調(diào)度配置,配置同步任務(wù),配置同步映射關(guān)系,DB到ES的映射,Kafka到ES的映射
同步調(diào)度分配,同步任務(wù)操作,啟動、停止、重新設(shè)置;同步任務(wù)分配,指定并行度等。
2.同步任務(wù)執(zhí)行程序
執(zhí)行任務(wù),將數(shù)據(jù)從Kafka經(jīng)過映射寫入到ES中,主要由四大模塊組成
(1)Kafka模塊,拉取消費(fèi)數(shù)據(jù),記錄消費(fèi)位置
(2)Mapper模塊,執(zhí)行映射過程,數(shù)據(jù)表與索引映射,表字段與索引字段映射,生成指定的Json格式數(shù)據(jù)
(3)Elastic模塊,將Mapper生成好的Json數(shù)據(jù)提交到ES中,Bulk局部更新,設(shè)置doc_as_upsert為true,成功則提交消費(fèi)記錄位置,失敗則走異常邏輯
(4)Schedule模塊,基于線程級別執(zhí)行同步任務(wù),支持同步任務(wù)啟動暫停等狀態(tài)操作,實(shí)時(shí)匯總同步任務(wù)的狀態(tài)指標(biāo)數(shù)據(jù)
數(shù)據(jù)同步全過程
1. 數(shù)據(jù)從DB更新到ES,中間經(jīng)過多個(gè)環(huán)節(jié),同步模式既有推送,也拉取,且多次結(jié)合完成。
2. Mysql寫入到本地binlog,推送模式
3. Canal讀取binlog寫入Kafka,先是拉取模式,后是推送模式
4. Worker同步程序從Kafka讀寫數(shù)據(jù),經(jīng)過處理寫入到ES,先是拉取模式,后是推送模式

注意事項(xiàng)
DB到ES實(shí)時(shí)同步整體項(xiàng)目鏈路很長,且涉及技術(shù)點(diǎn)較多,任意環(huán)節(jié)都會導(dǎo)致一些問題,特別注意:
1. DB刷數(shù)據(jù)問題,由于DB是批量更新,會出現(xiàn)部分性能瓶頸
2. DB多表關(guān)聯(lián)深度問題,DB多表直接關(guān)聯(lián)最好的關(guān)系是1對1,主要ES映射也可以基于主鍵關(guān)聯(lián)更新,無需反向查詢
3. ES高級類型限制問題,ES本身支持很多高級數(shù)據(jù)類型,但這些在同步程序中最好不要使用

有待探索問題
1.數(shù)據(jù)校驗(yàn),DB數(shù)據(jù)雖然同步到ES中,但目前是沒有有效的方法去校驗(yàn)正確性的,傳統(tǒng)的方式校驗(yàn)方式是隨機(jī)兩邊查詢對比,非常的低效,需要探討更好的數(shù)據(jù)比對方法;
2. 數(shù)據(jù)修復(fù),當(dāng)數(shù)據(jù)發(fā)現(xiàn)不正確時(shí)需要自動能夠修復(fù),但由于數(shù)據(jù)校驗(yàn)的低效,數(shù)據(jù)修復(fù)的準(zhǔn)確性有待考量
3. 技術(shù)演進(jìn),數(shù)據(jù)同步程序基于Java開發(fā),但做了很多非業(yè)務(wù)時(shí)間工作,程序大量的工作在調(diào)度,考慮引入Flink平臺,由平臺負(fù)責(zé)底層資源調(diào)度,上層只需配置同步映射。

? ?采取CDC這種方案也是基于馬蜂窩已有的經(jīng)驗(yàn)分享,設(shè)計(jì)思路一樣,技術(shù)實(shí)現(xiàn)不一樣。數(shù)據(jù)同步整體技術(shù)實(shí)現(xiàn)中間環(huán)節(jié)很多,任意技術(shù)點(diǎn)都需要了解透徹,否則會出現(xiàn)很多致命事故,需要多人團(tuán)隊(duì)協(xié)作完成。