日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

饿了么多活利器:实时双向复制工具(DRC)

發(fā)布時(shí)間:2025/4/5 编程问答 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 饿了么多活利器:实时双向复制工具(DRC) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

DRC介紹

餓了么的 Data Replicate Center(DRC)項(xiàng)目用于數(shù)據(jù)雙向復(fù)制和數(shù)據(jù)訂閱,使用場景如下圖:

要點(diǎn)說明:

  • 跨機(jī)房的 Mysql 數(shù)據(jù)復(fù)制完全通過 DRC 來完成

  • 還有很多業(yè)務(wù)團(tuán)隊(duì)通過 DRC 來實(shí)現(xiàn)數(shù)據(jù)訂閱

目前餓了么100%的跨機(jī)房數(shù)據(jù)復(fù)制,90%的數(shù)據(jù)訂閱都通過DRC完成,每天有大量的數(shù)據(jù)流經(jīng)DRC。復(fù)制延遲保持在1s以下,從來沒有發(fā)生過數(shù)據(jù)丟失和錯亂的情況。

?

DRC的設(shè)計(jì)目標(biāo)包括:

  • 實(shí)時(shí)雙向數(shù)據(jù)復(fù)制,延時(shí) < 1s ,并能夠解決雙向修改時(shí)的數(shù)據(jù)沖突

  • 數(shù)據(jù)變更訂閱,能夠在DB數(shù)據(jù)發(fā)生變化時(shí)通知到相關(guān)訂閱方

  • 高度可靠和保持順序,不能丟失數(shù)據(jù),也不能因?yàn)殄e亂執(zhí)行順序?qū)е聰?shù)據(jù)錯誤

  • 我們最終達(dá)到了這3個目標(biāo),下面圍繞著如何設(shè)計(jì)以滿足以上目標(biāo)介紹一下。

    ?

    DRC的總體設(shè)計(jì)

    DRC采用了多組件的集群化設(shè)計(jì),整體結(jié)構(gòu)如下圖:

    要點(diǎn)說明:

    • DRC有兩個核心服務(wù),Replicator 和 Apply,他們以集群化的方式部署,一個負(fù)責(zé)從源頭數(shù)據(jù)庫拉取變更,一個負(fù)責(zé)應(yīng)用變更到目標(biāo)數(shù)據(jù)庫。

    • Master Replicator目前實(shí)現(xiàn)了 Mysql Binary Log Dump 協(xié)議,從Source Mysql 中取得 DataChangeEvent。

    • 對于任何唯一的數(shù)據(jù)源,數(shù)據(jù)修改事件(DataChangeEvent)需要能夠映射為唯一的單調(diào)遞增的SCN(System Change Number),如果不能執(zhí)行這樣的映射,則DRC的一致性就不能得到保證。

    • Replicator接收到 DataChangeEvent 數(shù)據(jù)后使用一個Heap外的環(huán)狀內(nèi)存結(jié)構(gòu)(MMAP)保存,減少GC負(fù)荷,為了保證低延遲的復(fù)制,不寫入本地文件。

    • Replicator Slave是一種稍微特殊的 Replicator,從 Master Replicator 拉取 DataChangeEvent,并保存到本地EventBuffer中。

    • Replicator中保存當(dāng)前 SCN Number,有一個 Master 和任意多個 Slave ,當(dāng) Masters失效后,Slave Replicator 可以選舉新的 Master

    • Client SDK 從 Replicator 中拉取 DataChange Event序列,拉取時(shí)需要提供當(dāng)前位置(SCN)和過濾條件,過濾條件支持基于庫名,或者表名的過濾。

    • Replicator 中不保存任何 Client SDK 相關(guān)的狀態(tài)信息(SCN),該信息由 Client SDK 調(diào)用方維護(hù)。

    • Data Apply負(fù)責(zé)把ChangeEvent按照需要的格式應(yīng)用到數(shù)據(jù)庫中,需要保持事務(wù)一致性,按照SCN的順序執(zhí)行。

    其中 SCN 和 DataChangeEvent 是整個DRC的兩個核心概念,需要詳細(xì)說明一下:

    SCN是一個結(jié)構(gòu)體,能夠單調(diào)有續(xù),并全局唯一,綁定到唯一的事件上,每當(dāng) DRC 從 Mysql 拿到一個新的 Data Change Event,就會分配一個新的 SCN 與之對應(yīng)。

    每種數(shù)據(jù)源對應(yīng)于一種 SCN 的結(jié)構(gòu),對于 Mysql 數(shù)據(jù)源的SCN結(jié)構(gòu)體代碼如下:

    SCN要求單調(diào)有續(xù),并全局唯一,所以SCN 的產(chǎn)生邏輯大部分情況下需要綁定到數(shù)據(jù)源的唯一邏輯上,例如 Mysql 的 SCN 實(shí)現(xiàn)就嵌入了 mysql 的 serverid,logIndex,logPostion,這樣能保證對于一個唯一的 mysql server 來說,scn 是單調(diào)有序并唯一的,我們還加上了一個 changeId 字段,這樣,如果數(shù)據(jù)抽取切換到另外一個 mysql 上了,changeId 只需要 +1,就可以保證產(chǎn)生的SCN依然有序,關(guān)于 Mysql Bin Log 結(jié)構(gòu)的詳細(xì)信息

    整個SCN的產(chǎn)生邏輯如下圖:

    有了唯一的 SCN 之后,整個系統(tǒng)就有了保證一致性的最基礎(chǔ)保障。SCN是在 Replicator 端生成的,并貫穿了整個 DRC 系統(tǒng)的各個組件,所有的組件都用相同的SCN來標(biāo)志event,也用SCN來記錄當(dāng)前復(fù)制的位點(diǎn)。

    ?

    下面簡單介紹一下各個組件的要點(diǎn),以方便之后的介紹。

    Replicator:?replicator 負(fù)責(zé)變更事件的抽取,SCN的生成,以及維護(hù)了一個Event Buffer 來存儲取到的 event,結(jié)構(gòu)如下圖:

    要點(diǎn)說明:

    • replicator 有一個 master 多個 slave,只有 master 會連接 DB,其他的 slave 只連接 master replicator。

    • SCN在各個Replicator中是一致的,當(dāng) master 失效后會選舉出新的 master(zk),并從該 master 的當(dāng)前位置開始復(fù)制,這樣就避免了非常復(fù)雜的在多個 replicator 間保持一致的問題。

    • Replicator 中不保存客戶端狀態(tài),Client SDK Pull 數(shù)據(jù)的時(shí)候需要指定開始 SCN 位置,所以可以隨時(shí)切換到任何一個Replicator拉取數(shù)據(jù)。

    • 如果客戶端提交的SCN超過當(dāng)前Replicator的最老數(shù)據(jù),Replicator 會回源到源頭的數(shù)據(jù)庫拉取。

    • Replicator 在維護(hù)了一個 RingBuffer,用于保存 ChangeEvent,這個buffer我們叫做 EventBuffer,EventBuffer 是 DRC 提高性能的一個非常關(guān)鍵的環(huán)節(jié),之后回詳細(xì)說明。

    ?

    Apply :Apply 部署在目標(biāo)端,負(fù)責(zé)把讀取到的數(shù)據(jù)寫入目標(biāo)數(shù)據(jù)庫,或者把變更消息發(fā)送到指定的消息隊(duì)列中,目前 DRC 支持 Kafka / RabbitMQ / MaxQ 等多種消息隊(duì)列。

    要點(diǎn)說明:

    • Apply 以 Channel 的形式在 DataApply Server 上組織復(fù)制單元

    • Channel 是一張表或者一組表

    • Channel 內(nèi)部邏輯通過串聯(lián)的 Filter 實(shí)現(xiàn)

    • Change 上實(shí)現(xiàn)了諸多的業(yè)務(wù)邏輯,例如冪等,沖突檢查,并行化性能優(yōu)化等等。

    • 以上就是 DRC 的一個整體介紹,下面說一下 DRC 的實(shí)現(xiàn)中一些具體的技術(shù)點(diǎn)。

    ?

    DRC 實(shí)現(xiàn)

    • 數(shù)據(jù)一致保證

    如何保證數(shù)據(jù)一致:一致性是 DRC 的最基本要求,DRC 通過一系列的方法保證雙向復(fù)制中兩邊的數(shù)據(jù)一致。這其中有三個問題要說一下:

    • 問題一:如何防止循環(huán)復(fù)制?

    雙向復(fù)制要解決的一個重要問題是循環(huán)復(fù)制,要能夠識別出一個改變動作是來自產(chǎn)研,還是來自DRC工具本身。來自產(chǎn)研的數(shù)據(jù)變更需要復(fù)制出去,而來自DRC的數(shù)據(jù)復(fù)制不需要復(fù)制。

    DRC防止沖突的方案是在由DRC產(chǎn)生的事務(wù)中加入DRC標(biāo)記。如下圖的事務(wù)2,Apply在寫入時(shí),會在事務(wù)的開頭處加上一個 insert 或者是 update 語句,其中包含了 DRC 的信息。當(dāng)Replicator 發(fā)現(xiàn)一個事物包涵該特殊標(biāo)記時(shí),就不會再復(fù)制出去。

    這種方式雖然避免了循環(huán)復(fù)制,帶給目標(biāo)端數(shù)據(jù)庫帶來了一些性能開銷,我們會在之后的版本中通過修改 Mysql Binlog 機(jī)制來更為高效的阻斷循環(huán)復(fù)制。

    • 問題二:萬一發(fā)生中斷或者是故障,如果保證數(shù)據(jù)正確?

    中斷恢復(fù):從中斷恢復(fù),主要靠的是SCN,因?yàn)镾CN有序,并保存在可靠存儲中,任何節(jié)點(diǎn)的失效,都可以通過SCN位點(diǎn)來恢復(fù),SCN可以被保存在本地文件,ZK和數(shù)據(jù)庫中,達(dá)到性能和可靠性的平衡。

    冪等:另外,大部分的DB操作在DRC下是冪等的,從任意一點(diǎn)開始,重復(fù)執(zhí)行一次,還是會得到相同的結(jié)果。DRC能夠處理各種重復(fù)執(zhí)行帶來的異常,并且保證最終數(shù)據(jù)始終一致。這里主要靠的是詳細(xì)分析各種重復(fù)執(zhí)行可能帶來的異常,對能夠跳過的異常就直接跳過,而不停止復(fù)制。

    • 問題三:萬一一筆數(shù)據(jù)在兩邊都修改了,如何解決沖突?

    避免沖突:首先我們通過全局定義的規(guī)則避免數(shù)據(jù)沖突,仔細(xì)設(shè)計(jì)的數(shù)據(jù)規(guī)則,讓每筆數(shù)據(jù)都有自己的歸屬機(jī)房,兩個機(jī)房同時(shí)修改一筆數(shù)據(jù)的情況很少出現(xiàn)。兩個機(jī)房產(chǎn)生的數(shù)據(jù)在 ID 上是錯開的,各種和業(yè)務(wù)相關(guān)的ID 也通過設(shè)計(jì)避免了重復(fù),這樣數(shù)據(jù)復(fù)制到一起后,不會發(fā)生沖突。對于有唯一鍵索引的數(shù)據(jù),我們也進(jìn)行了改造,加上了用于區(qū)別機(jī)房的數(shù)據(jù)字段。

    沖突解決:即使如此,有時(shí)候沖突還是不可避免的,比如發(fā)生機(jī)房切換,或者是業(yè)務(wù)方的代碼有Bug等,所以我們還提供2層沖突解決方案,萬一發(fā)生同一筆數(shù)據(jù),在兩個機(jī)房同時(shí)修改,則引入沖突處理:

    • 基本的沖突處理,通過時(shí)間戳完成,兩邊機(jī)房的都有實(shí)時(shí)同步的毫秒級別的NTP服務(wù),每筆數(shù)據(jù)上都打上了變更時(shí)間戳。在發(fā)生沖突的時(shí)候,最后發(fā)生的修改會勝出,最終兩個機(jī)房的數(shù)據(jù)都會被同步成最后的數(shù)據(jù)。

    • 如果時(shí)間戳不能滿足需要,還可以通過調(diào)用業(yè)務(wù)提供的沖突解決方案解決,沖突解決時(shí),為業(yè)務(wù)方提供了原始數(shù)據(jù)和最新數(shù)據(jù),由業(yè)務(wù)邏輯來決定哪個數(shù)據(jù)才是最終正確的數(shù)據(jù)。

    • 但是我們不會對數(shù)據(jù)進(jìn)行合并,因?yàn)楹喜淼膯栴}比較多,事實(shí)上看,基于時(shí)間戳已經(jīng)解決了99%的數(shù)據(jù)沖突問題。

    • 性能優(yōu)化

    DRC 具有非常高的吞吐量,主要?dú)w功于Replicator的本地EventBuffer,幾個月的Event數(shù)據(jù)都會被緩沖到 EventBuffer 中,EventBuffer 是一個跳表結(jié)構(gòu),如下圖:

    其中跳表的索引是SCN,通過SCN能夠快速的找到對應(yīng)Event,之后按照順序輸出其后的 Event,每次輸出一批Event,磁盤讀取和網(wǎng)絡(luò)傳輸都很高效。

    EventBuffer 落地在磁盤上,通過內(nèi)存映射Map到內(nèi)存中。Java Heap 中只保存比較少的索引數(shù)據(jù),大量的Event數(shù)據(jù)維持在堆外,避免大內(nèi)存帶來的GC開銷。大部分 EventBuffer 的大小維持在512G空間,能夠支持?jǐn)?shù)月到數(shù)個星期的事件。

    EventBuffer 中只保存了二進(jìn)制的數(shù)據(jù),數(shù)據(jù)的結(jié)構(gòu)被保存在另外一個獨(dú)立的存儲中,我們稱為MetaData Store。MetaData Store 保存了每個表的歷史數(shù)據(jù)格式的快照,每次發(fā)生表結(jié)構(gòu)變化,都會創(chuàng)建一個新的快照,結(jié)構(gòu)如下:

    要點(diǎn)說明:

    • Meta History 記錄了數(shù)據(jù)結(jié)構(gòu)以及對應(yīng)的 SCN

    • 通過 Meta History,可以回放任意時(shí)間點(diǎn)的數(shù)據(jù)

    • 通過 Meta Histroy 的翻譯,可以把數(shù)據(jù)翻譯成業(yè)務(wù)需要的格式,或者組裝成對應(yīng)的SQL

    以上主要介紹了DRC 的一些實(shí)現(xiàn)細(xì)節(jié),DRC 作為一個核心的中間件,還有很多其他的設(shè)計(jì),例如集群管理,高可用性設(shè)計(jì),性能優(yōu)化等,但考慮到篇幅,就不在這里全部寫出來了。有興趣的朋友可以可留言和我聯(lián)系,大家共同探討。

    轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/articles/9143327.html

    《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

    總結(jié)

    以上是生活随笔為你收集整理的饿了么多活利器:实时双向复制工具(DRC)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。