一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

如何解決微服務(wù)的數(shù)據(jù)一致性分發(fā)問(wèn)題?

 黃爸爸好 2020-08-04

介紹

系統(tǒng)架構(gòu)微服務(wù)化以后,根據(jù)微服務(wù)獨(dú)立數(shù)據(jù)源的思想,每個(gè)微服務(wù)一般具有各自獨(dú)立的數(shù)據(jù)源,但是不同微服務(wù)之間難免需要通過(guò)數(shù)據(jù)分發(fā)來(lái)共享一些數(shù)據(jù),這個(gè)就是微服務(wù)的數(shù)據(jù)分發(fā)問(wèn)題。Netflix/Airbnb等一線互聯(lián)網(wǎng)公司的實(shí)踐[參考附錄1/2/3]表明,數(shù)據(jù)一致性分發(fā)能力,是構(gòu)建松散耦合、可擴(kuò)展和高性能的微服務(wù)架構(gòu)的基礎(chǔ)。

本文解釋分布式微服務(wù)中的數(shù)據(jù)一致性分發(fā)問(wèn)題,應(yīng)用場(chǎng)景,并給出常見(jiàn)的解決方法。本文主要面向互聯(lián)網(wǎng)分布式系統(tǒng)架構(gòu)師和研發(fā)經(jīng)理。

為啥要分發(fā)數(shù)據(jù)?場(chǎng)景?

我們還是要從具體業(yè)務(wù)場(chǎng)景出發(fā),為啥要分發(fā)數(shù)據(jù)?有哪些場(chǎng)景?在實(shí)際企業(yè)中,數(shù)據(jù)分發(fā)的場(chǎng)景其實(shí)是非常多的。假設(shè)某電商企業(yè)有這樣一個(gè)訂單服務(wù)Order Service,它有一個(gè)獨(dú)立的數(shù)據(jù)庫(kù)。同時(shí),周邊還有不少系統(tǒng)需要訂單的數(shù)據(jù),上圖給出了一些例子:

  1. 一個(gè)是緩存系統(tǒng),為了提升訂單數(shù)據(jù)的訪問(wèn)性能,我們可以把頻繁訪問(wèn)的訂單數(shù)據(jù),通過(guò)Redis緩存起來(lái);

  2. 第二個(gè)是Fulfillment Service,也就是訂單履行系統(tǒng),它也需要一份訂單數(shù)據(jù),借此實(shí)現(xiàn)訂單履行的功能;

  3. 第三個(gè)是ElasticSearch搜索引擎系統(tǒng),它也需要一份訂單數(shù)據(jù),可以支持前臺(tái)用戶(hù)、或者是后臺(tái)運(yùn)營(yíng)快速查詢(xún)訂單信息;

  4. 第四個(gè)是傳統(tǒng)數(shù)據(jù)倉(cāng)庫(kù)系統(tǒng),它也需要一份訂單數(shù)據(jù),支持對(duì)訂單數(shù)據(jù)的分析和挖掘。

當(dāng)然,為了獲得一份訂單數(shù)據(jù),這些系統(tǒng)可以定期去訂單服務(wù)查詢(xún)最新的數(shù)據(jù),也就是拉模式,但是拉模式有兩大問(wèn)題:

  1. 一個(gè)是拉數(shù)據(jù)通常會(huì)有延遲,也就是說(shuō)拉到的數(shù)據(jù)并不實(shí)時(shí);

  2. 如果頻繁拉的話,考慮到外圍系統(tǒng)眾多(而且可能還會(huì)增加),勢(shì)必會(huì)對(duì)訂單數(shù)據(jù)庫(kù)的性能造成影響,嚴(yán)重時(shí)還可能會(huì)把訂單數(shù)據(jù)庫(kù)給拉掛。

所以,當(dāng)企業(yè)規(guī)模到了一定階段,還是需要考慮數(shù)據(jù)分發(fā)技術(shù),將業(yè)務(wù)數(shù)據(jù)同步分發(fā)到對(duì)數(shù)據(jù)感興趣的其它服務(wù)。除了上面提到的一些數(shù)據(jù)分發(fā)場(chǎng)景,其實(shí)還有很多其它場(chǎng)景,例如:

  1. 第一個(gè)是數(shù)據(jù)復(fù)制(replication)。為了實(shí)現(xiàn)高可用,一般要將數(shù)據(jù)復(fù)制多分存儲(chǔ),這個(gè)時(shí)候需要采用數(shù)據(jù)分發(fā)。

  2. 第二個(gè)是支持?jǐn)?shù)據(jù)庫(kù)的解耦拆分。在單體數(shù)據(jù)庫(kù)解耦拆分的過(guò)程中,為了實(shí)現(xiàn)不停機(jī)拆分,在一段時(shí)間內(nèi),需要將遺留老數(shù)據(jù)同步復(fù)制到新的數(shù)據(jù)存儲(chǔ),這個(gè)時(shí)候也需要數(shù)據(jù)分發(fā)技術(shù)。

  3. 第三個(gè)是實(shí)現(xiàn)CQRS,還有去數(shù)據(jù)庫(kù)Join。這兩個(gè)場(chǎng)景我后面有單獨(dú)文章解釋?zhuān)@邊先說(shuō)明一下,實(shí)現(xiàn)CQRS和數(shù)據(jù)庫(kù)去Join的底層技術(shù),其實(shí)也是數(shù)據(jù)分發(fā)。

  4. 第四個(gè)是實(shí)現(xiàn)分布式事務(wù)。這個(gè)場(chǎng)景我后面也有單獨(dú)文章講解,這邊先說(shuō)明一下,解決分布式事務(wù)問(wèn)題的一些方案,底層也是依賴(lài)于數(shù)據(jù)分發(fā)技術(shù)的。

  5. 其它還有流式計(jì)算、大數(shù)據(jù)BI/AI,還有審計(jì)日志和歷史數(shù)據(jù)歸檔等場(chǎng)景,一般都離不開(kāi)數(shù)據(jù)分發(fā)技術(shù)。

總之,波波認(rèn)為,數(shù)據(jù)分發(fā),是構(gòu)建現(xiàn)代大規(guī)模分布式系統(tǒng)、微服務(wù)架構(gòu)和異步事件驅(qū)動(dòng)架構(gòu)的底層基礎(chǔ)技術(shù)。

雙寫(xiě)?

對(duì)于數(shù)據(jù)分發(fā)這個(gè)問(wèn)題,乍一看,好像并不復(fù)雜,稍有開(kāi)發(fā)經(jīng)驗(yàn)的同學(xué)會(huì)說(shuō),我在應(yīng)用層做一個(gè)雙寫(xiě)不就可以了嗎?比方說(shuō),請(qǐng)看上圖右邊,這里有一個(gè)微服務(wù)A,它需要把數(shù)據(jù)寫(xiě)入DB,同時(shí)還要把數(shù)據(jù)寫(xiě)到MQ,對(duì)于這個(gè)需求,我在A服務(wù)中弄一個(gè)雙寫(xiě),不就搞定了嗎?其實(shí)這個(gè)問(wèn)題并沒(méi)有那么簡(jiǎn)單,關(guān)鍵是你如何才能保證雙寫(xiě)的事務(wù)性?

請(qǐng)看上圖左邊的代碼,這里有一個(gè)方法updateDbThenSendMsgInTransaction,這個(gè)方法上加了事務(wù)性標(biāo)注,也就是說(shuō),如果拋異常的話,數(shù)據(jù)庫(kù)操作會(huì)回滾。我們來(lái)看這個(gè)方法的執(zhí)行步驟:

第一步先更新數(shù)據(jù)庫(kù),如果更新成功,那么result設(shè)為true,如果更新失敗,那么result設(shè)為false;

第二步,如果result為true,也就是說(shuō)DB更新成功,那么我們就繼續(xù)做第三步,向mq發(fā)送消息

如果發(fā)消息也成功,那么我們的流程就走到第四步,整個(gè)雙寫(xiě)事務(wù)就成功了。

如果發(fā)消息拋異常,也就是發(fā)消息失敗,那么容器會(huì)執(zhí)行該方法的事務(wù)性回滾,上面的數(shù)據(jù)庫(kù)更新操作也會(huì)回滾。

初看這個(gè)雙寫(xiě)流程沒(méi)有問(wèn)題,可以保證事務(wù)性。但是深入研究會(huì)發(fā)現(xiàn)它其實(shí)是有問(wèn)題的。比方說(shuō)在第三步,如果發(fā)消息拋異常了,并不保證說(shuō)發(fā)消息失敗了,可能只是由于網(wǎng)絡(luò)異常抖動(dòng)而造成的拋異常,實(shí)際消息可能是已經(jīng)發(fā)到MQ中,但是拋異常會(huì)造成上面數(shù)據(jù)庫(kù)更新操作的回滾,結(jié)果造成兩邊數(shù)據(jù)不一致。

模式一:事務(wù)性發(fā)件箱(Transactional Outbox)

對(duì)于事務(wù)性雙寫(xiě)這個(gè)問(wèn)題,業(yè)界沉淀下來(lái)比較實(shí)踐的做法,其中一種,就是采用所謂事務(wù)性發(fā)件箱模式,英文叫Transactional Outbox。據(jù)說(shuō)這個(gè)模式是eBay最早發(fā)明和使用的。事務(wù)性發(fā)件箱模式不難理解,請(qǐng)看上圖。

我們?nèi)匀灰杂唵蜲rder服務(wù)為例。在數(shù)據(jù)庫(kù)中,除了訂單Order表,為了實(shí)現(xiàn)事務(wù)性雙寫(xiě),我們還需增加了一個(gè)發(fā)件箱Outbox表。Order表和Outbox表都在同一個(gè)數(shù)據(jù)庫(kù)中,對(duì)它們進(jìn)行同時(shí)更新的話,通過(guò)數(shù)據(jù)庫(kù)的事務(wù)機(jī)制,是可以實(shí)現(xiàn)事務(wù)性更新的。

下面我們通過(guò)例子來(lái)展示這個(gè)流程,我們這里假定Order Service要添加一個(gè)新訂單。

首先第一步,Order Service先將新訂單數(shù)據(jù)寫(xiě)入Order表,然后它再向Outbox表中寫(xiě)入一條訂單新增記錄,這兩個(gè)DB操作可以包在一個(gè)DB事務(wù)里頭,也就是可以實(shí)現(xiàn)事務(wù)性寫(xiě)入。

然后第二步,我們?cè)僖胍粋€(gè)稱(chēng)為消息中繼Message Relay的角色,它負(fù)責(zé)定期Poll拉取Outbox中的新數(shù)據(jù),然后第三步再Publish發(fā)送到MQ。如果寫(xiě)入MQ確認(rèn)成功,Message Relay就可以將Outbox中的對(duì)應(yīng)記錄標(biāo)記為已消費(fèi)。這里可能會(huì)出現(xiàn)一種異常情況,就是Message Relay在將消息發(fā)送到MQ時(shí),發(fā)生了網(wǎng)絡(luò)抖動(dòng),實(shí)際消息可能已經(jīng)寫(xiě)入MQ,但是Message Relay并沒(méi)有得到確認(rèn),這時(shí)候它會(huì)重發(fā),直到明確成功為止。所以,這里也是一個(gè)At Least Once,也就是至少交付一次的消費(fèi)語(yǔ)義,消息可能被重復(fù)投遞。因此,MQ之后的消費(fèi)方要做消息去重或冪等處理。

總之,事務(wù)性發(fā)件箱模式可以保證,對(duì)Order表的修改,然后將對(duì)應(yīng)事件發(fā)送到MQ,這兩個(gè)動(dòng)作可以實(shí)現(xiàn)事務(wù)性,也就是實(shí)現(xiàn)數(shù)據(jù)分發(fā)的事務(wù)性。

注意,這里的Message Relay角色既可以是一個(gè)獨(dú)立部署的服務(wù),也可以和Order Service住在一起。生產(chǎn)實(shí)踐中,需要考慮Message Relay的高可用部署,還有監(jiān)控和告警,否則如果Message Relay掛了,消息就發(fā)不出來(lái),然后,依賴(lài)于消息的各種消費(fèi)方也將無(wú)法正常工作。

Transactional Outbox參考實(shí)現(xiàn) ~ Killbill Common Queue

事務(wù)性發(fā)件箱的原理簡(jiǎn)單,實(shí)現(xiàn)起來(lái)也不復(fù)雜,波波這邊推薦一個(gè)生產(chǎn)級(jí)的參考實(shí)現(xiàn)。這個(gè)實(shí)現(xiàn)源于一個(gè)叫killbill的項(xiàng)目,killbill是美國(guó)高朋(GroupOn)公司開(kāi)源的訂閱計(jì)費(fèi)和支付平臺(tái),這個(gè)項(xiàng)目已經(jīng)有超過(guò)8~9年的歷史,在高朋等公司已經(jīng)有不少落地案例,是一個(gè)比較成熟的產(chǎn)品。killbill項(xiàng)目里頭有一些公共庫(kù),單獨(dú)放在一個(gè)叫killbill-commons的子項(xiàng)目里頭,其中有一個(gè)叫killbill common queue,它其實(shí)是事務(wù)性發(fā)件箱的一個(gè)生產(chǎn)級(jí)實(shí)現(xiàn)。上圖有給出這個(gè)queue的github鏈接。

Killbill common queue也是一個(gè)基于DB實(shí)現(xiàn)的分布式的隊(duì)列,它上層還包裝了EventBus事件總線機(jī)制。killbill common queue的總體設(shè)計(jì)思路不難理解,請(qǐng)看上圖:

在上圖的左邊,killbill common queue提供發(fā)送消息API,并且是支持事務(wù)的。比方說(shuō)圖上的postFromTransaction方法,它可以發(fā)送一個(gè)BusEvent事件到DB Queue當(dāng)中,這個(gè)方法還接受一個(gè)數(shù)據(jù)庫(kù)連接Connection參數(shù),killbill common queue可以保證對(duì)事件event的數(shù)據(jù)庫(kù)寫(xiě)入,和使用同一個(gè)Connection的其它數(shù)據(jù)庫(kù)寫(xiě)入操作,發(fā)生在同一個(gè)事務(wù)中。這個(gè)做法其實(shí)就是一種事務(wù)性發(fā)件箱的實(shí)現(xiàn),這里的發(fā)件箱存的就是事件event。

除了POST寫(xiě)入API,killbill common queue還支持類(lèi)似前面提到的Message Relay的功能,并且是包裝成EeventBus + Handler方式來(lái)實(shí)現(xiàn)的。開(kāi)發(fā)者只需要實(shí)現(xiàn)事件處理器,并且注冊(cè)訂閱在EventBus上,就可以接收到DB Queue,也就是發(fā)件箱當(dāng)中的新事件,并進(jìn)行消費(fèi)處理。如果事件處理成功,那么EvenbBus會(huì)將對(duì)應(yīng)的事件從發(fā)件箱中移走;如果事件處理不成功,那么EventBus會(huì)負(fù)責(zé)重試,直到處理成功,或者超過(guò)最大重試次數(shù),那么它會(huì)將該事件標(biāo)記為處理失敗,并移到歷史歸檔表中,等待后續(xù)人工檢查和干預(yù)。這個(gè)EventBus的底層,其實(shí)有一個(gè)Dispatcher派遣線程,它負(fù)責(zé)定期掃描DB Queue(也就是發(fā)件箱)中的新事件,有的話就批量拉取出來(lái),并發(fā)送到內(nèi)部EventBus的隊(duì)列中,如果內(nèi)部隊(duì)列滿了,那么Dispather Thread也會(huì)暫停拉取新事件。

在killbill common queue的設(shè)計(jì)中,每個(gè)節(jié)點(diǎn)上的Dispather線程只負(fù)責(zé)通過(guò)自己這個(gè)節(jié)點(diǎn)寫(xiě)入的事件,并且在一個(gè)節(jié)點(diǎn)上,Dispather線程也只有一個(gè),這樣才能保證消息消費(fèi)的順序性,并且也不會(huì)重復(fù)消費(fèi)。

Reaper機(jī)制

killbill common queue,其實(shí)是一個(gè)基于集中式數(shù)據(jù)庫(kù)實(shí)現(xiàn)的分布式隊(duì)列,為什么說(shuō)它是分布式隊(duì)列呢?請(qǐng)看上圖,killbill common queue的設(shè)計(jì)是這樣的,它的每個(gè)節(jié)點(diǎn),只負(fù)責(zé)消費(fèi)處理從自己這個(gè)節(jié)點(diǎn)寫(xiě)入的事件。比方說(shuō)上圖中有藍(lán)色/黃色和綠色3個(gè)節(jié)點(diǎn),那么藍(lán)色節(jié)點(diǎn),只負(fù)責(zé)從藍(lán)色節(jié)點(diǎn)寫(xiě)入,在數(shù)據(jù)庫(kù)中標(biāo)記為藍(lán)色的事件。同樣,黃色節(jié)點(diǎn),只負(fù)責(zé)從黃色節(jié)點(diǎn)寫(xiě)入,在數(shù)據(jù)庫(kù)中標(biāo)記為黃色的事件。綠色節(jié)點(diǎn)也是類(lèi)似。這是一種分布式的設(shè)計(jì),如果處理容量不夠,只需按需添加更多節(jié)點(diǎn),就可以實(shí)現(xiàn)負(fù)載分?jǐn)偂?/span>

這里有個(gè)問(wèn)題,如果其中某個(gè)節(jié)點(diǎn)掛了,比方說(shuō)上圖的藍(lán)色節(jié)點(diǎn)掛了,那么誰(shuí)來(lái)繼續(xù)消費(fèi)數(shù)據(jù)庫(kù)中藍(lán)色的,還沒(méi)有來(lái)得及處理的事件呢?為了解決這個(gè)問(wèn)題,killbill common queue設(shè)計(jì)了一種稱(chēng)為reaper收割機(jī)的機(jī)制。每個(gè)節(jié)點(diǎn)上都還住了一個(gè)收割機(jī)線程,它們會(huì)定期檢查數(shù)據(jù)庫(kù),看有沒(méi)有長(zhǎng)時(shí)間無(wú)人處理的事件,如果有,就搶占標(biāo)記為由自己負(fù)責(zé)。比方說(shuō)上圖的右邊,最終黃色節(jié)點(diǎn)上的收割機(jī)線程搶到了原來(lái)由藍(lán)色節(jié)點(diǎn)負(fù)責(zé)的事件,那么它會(huì)把這些事件標(biāo)記為黃色,也就是由自己來(lái)負(fù)責(zé)。

收割機(jī)機(jī)制,保證了killbill common queue的高可用性,相當(dāng)于保證了事務(wù)性發(fā)件箱中的Message Relay的高可用性。

Killbill PersistentBus表結(jié)構(gòu)

基于killbill common queue的EventBus,也被稱(chēng)為killbill PersistentBus。上圖給出了它的數(shù)據(jù)庫(kù)表結(jié)構(gòu),其中bus_events就是用來(lái)存放待處理事件的,相當(dāng)于發(fā)件箱,主要的字段包括:

  1. event_json,存放json格式的原始數(shù)據(jù)。

  2. creating_owner,記錄創(chuàng)建節(jié)點(diǎn),也就是事件是由哪個(gè)節(jié)點(diǎn)寫(xiě)入的。

  3. processingowner,記錄處理節(jié)點(diǎn),也就是事件最終是由哪個(gè)節(jié)點(diǎn)處理的;通常由creatingowner自己處理,但也可能被收割,由其它節(jié)點(diǎn)處理。

  4. processing_state,當(dāng)前的處理狀態(tài)。

  5. error_count,處理錯(cuò)誤計(jì)數(shù),超過(guò)一定計(jì)數(shù)會(huì)被標(biāo)記為處理失敗。

當(dāng)前處理狀態(tài)主要包括6種:

  1. AVAILABLE,表示待處理

  2. IN_PROCESSING,表示已經(jīng)被dispatcher線程取走,正在處理中

  3. PROCESSED,表示已經(jīng)處理

  4. REMOVED,表示已經(jīng)被刪除

  5. FAILED,表示處理失敗

  6. REPEATED,表示被其它節(jié)點(diǎn)收割了

除了bus_events待處理事件表,還有一個(gè)對(duì)應(yīng)的bus-events-history事件歷史記錄表。不管成功還是失敗,最終,事件會(huì)被寫(xiě)入歷史記錄表進(jìn)行歸檔,作為事后審計(jì)或者人工干預(yù)的依據(jù)。

上圖下方給出了數(shù)據(jù)庫(kù)表的github鏈接,你可以進(jìn)一步參考學(xué)習(xí)。

Killbill PersistentBus處理狀態(tài)遷移

上圖給出了killbill PersistentBus的事件處理狀態(tài)遷移圖。

  1. 剛開(kāi)始事件處于AVAILABLE待處理狀態(tài);

  2. 之后事件被dispatcher線程拉取,進(jìn)入IN_PROCESSING處理中狀態(tài);

  3. 之后,如果事件處理器成功處理了事件,那么事件就進(jìn)入PROCESSED已經(jīng)處理狀態(tài);

  4. 如果事件處理器處理事件失敗,那么事件的錯(cuò)誤計(jì)數(shù)會(huì)被增加1,如果錯(cuò)誤計(jì)數(shù)還沒(méi)有超過(guò)最大失敗重試閥值,那么事件就會(huì)重新進(jìn)入AVAILABLE狀態(tài);

  5. 如果事件的錯(cuò)誤數(shù)量超過(guò)了最大失敗重試閥值,那么事件就會(huì)進(jìn)入FAILED失敗狀態(tài);

  6. 如果負(fù)責(zé)待處理事件的節(jié)點(diǎn)掛了,那么到達(dá)一定的時(shí)間間隔,對(duì)應(yīng)的事件會(huì)被收割進(jìn)入REAPED被收割狀態(tài)。

上圖有一個(gè)通過(guò)API觸發(fā)進(jìn)入的REMOVED移除狀態(tài),這個(gè)是給通知隊(duì)列用的,用戶(hù)可以通過(guò)API移除對(duì)應(yīng)的通知消息。順便提一下,除了事件/消息隊(duì)列,Killbill queue也是支持通知隊(duì)列(或者說(shuō)延遲消息隊(duì)列)的。

模式二:變更數(shù)據(jù)捕獲(Change Data Capture, CDC)

對(duì)于事務(wù)性雙寫(xiě)這個(gè)問(wèn)題,業(yè)界沉淀下來(lái)比較實(shí)踐的做法,其中第二種,就是所謂的變更數(shù)據(jù)捕獲,英文稱(chēng)為Change Data Capture,簡(jiǎn)稱(chēng)CDC。

變更數(shù)據(jù)捕獲的原理也不復(fù)雜,它利用了數(shù)據(jù)庫(kù)的事務(wù)日志記錄。一般數(shù)據(jù)庫(kù),對(duì)于變更提交操作,都記錄所謂事務(wù)日志Transaction Log,也稱(chēng)為提交日志Commit Log,比方說(shuō)MySQL支持binlog,Postgres支持Write Ahead log。事務(wù)日志可以簡(jiǎn)單理解為數(shù)據(jù)庫(kù)本地的一個(gè)文件隊(duì)列,它記錄了按時(shí)間順序發(fā)生的對(duì)數(shù)據(jù)庫(kù)表的變更提交記錄。

下面我們通過(guò)例子來(lái)展示這個(gè)變更數(shù)據(jù)捕獲的流程,我們這里假定Order Service要添加一個(gè)新訂單。

第一步,Order Service將新訂單記錄寫(xiě)入Order表,并且提交。因?yàn)檫@是一次表變更操作,所以這次變更會(huì)被記錄到數(shù)據(jù)庫(kù)的事務(wù)日志當(dāng)中,其中內(nèi)容包括發(fā)生的變更數(shù)據(jù)。

第二步,我們還需要引入一個(gè)稱(chēng)為T(mén)ransaction Log Miner這樣的角色,這個(gè)Miner負(fù)責(zé)訂閱在事務(wù)日志隊(duì)列上,如果有新的變更記錄,Miner就會(huì)捕獲到變更記錄。

然后第三步,Miner會(huì)將變更記錄發(fā)送到MQ消息隊(duì)列。同之前的Message Relay一樣,這里的發(fā)送到MQ也是At Least Once語(yǔ)義,消息可能會(huì)被重復(fù)發(fā)送,所以MQ之后的消費(fèi)者需要做去重或者冪等處理。

總之,CDC技術(shù)同樣可以保證,對(duì)Order表的修改,然后將對(duì)應(yīng)事件發(fā)送到MQ,這兩個(gè)動(dòng)作可以實(shí)現(xiàn)事務(wù)性,也就是實(shí)現(xiàn)數(shù)據(jù)分發(fā)的事務(wù)性。

注意,這里的CDC一般是一個(gè)獨(dú)立部署的服務(wù),生產(chǎn)中需要做好高可用部署,并且做好監(jiān)控告警。否則如果CDC掛了,消息也就發(fā)不出來(lái),然后,依賴(lài)于消息的各種消費(fèi)方也將無(wú)法正常工作。

CDC開(kāi)源項(xiàng)目(企業(yè)級(jí))

當(dāng)前,有幾個(gè)比較成熟的企業(yè)級(jí)的CDC開(kāi)源項(xiàng)目,我這邊收集了一些,供大家學(xué)習(xí)參考:

  1. 第一個(gè)是阿里開(kāi)源的Canal,目前在github上有超過(guò)1.4萬(wàn)顆星,這個(gè)項(xiàng)目在國(guó)內(nèi)用得比較多,之前在拍拍貸的實(shí)時(shí)數(shù)據(jù)場(chǎng)景,Canal也有不少成功的應(yīng)用。Canal主要支持MySQL binlog的增量訂閱和消費(fèi)。它是基于MySQL的Master/Slave機(jī)制,它的Miner角色是通過(guò)偽裝成Slave來(lái)實(shí)現(xiàn)的。這個(gè)項(xiàng)目的使用文檔相對(duì)比較完善,建議大家一步參考學(xué)習(xí)。

  2. 第二個(gè)是Redhat開(kāi)源的Debezium,目前在github上有超過(guò)3.2k星,這個(gè)項(xiàng)目在國(guó)外用得較多。Debezium主要是在Kafka Connect的基礎(chǔ)上開(kāi)發(fā)的,它不僅支持mysql數(shù)據(jù)庫(kù),還支持postgres/sqlserver/mongodb等數(shù)據(jù)庫(kù)。

  3. 第三個(gè)是Zendesk開(kāi)源的Maxwell,目前在github上有超過(guò)2.1k星。Maxwell是一個(gè)輕量級(jí)的CDC Deamon,主要支持MySQL binlog的變更數(shù)據(jù)捕獲和處理。

  4. 第四個(gè)是Airbnb開(kāi)源的SpinalTap,目前在github上有兩百多顆星。SpinalTap主要支持MySQL binlog的變更捕獲和處理。這個(gè)項(xiàng)目的星雖然不多,但是它是在Airbnb SOA服務(wù)化過(guò)程中,通過(guò)實(shí)踐落地出來(lái)的一個(gè)項(xiàng)目,值得參考。

對(duì)于上面的這些項(xiàng)目,如果你想生產(chǎn)使用的話,波波推薦的是阿里的Canal,因?yàn)檫@個(gè)項(xiàng)目畢竟是國(guó)內(nèi)大廠阿里落地出來(lái),而且在國(guó)內(nèi)已經(jīng)有不少企業(yè)落地案例。其它幾個(gè)項(xiàng)目,你也可以參考研究。

學(xué)習(xí)參考 ~ Eventuate-Tram

既然談到這個(gè)CDC,這里有必要提到一個(gè)人和一本書(shū),這個(gè)人叫Chris Chardson,他是美國(guó)的老一輩的技術(shù)大牛,曾今是第一代的Cloud Foundry項(xiàng)目的創(chuàng)始人(后來(lái)Cloud Foundry被Pivotal所收購(gòu))。近幾年,Chris Chardson開(kāi)始轉(zhuǎn)戰(zhàn)微服務(wù)領(lǐng)域,這兩年,他還專(zhuān)門(mén)寫(xiě)了一本書(shū),叫《微服務(wù)設(shè)計(jì)模式》,英文名是《Microservices Patterns》。這本書(shū)主要是講微服務(wù)架構(gòu)和設(shè)計(jì)模式的,內(nèi)容還不錯(cuò),是我推薦大家閱讀的。

Charis Chardson還專(zhuān)門(mén)開(kāi)發(fā)了一個(gè)叫Eventuate-Tram的開(kāi)源項(xiàng)目(這個(gè)項(xiàng)目也有商業(yè)版),另外他的微服務(wù)書(shū)里頭也詳細(xì)介紹了這個(gè)項(xiàng)目。這個(gè)項(xiàng)目可以說(shuō)是一個(gè)大集成框架,它不僅實(shí)現(xiàn)了DDD領(lǐng)域驅(qū)動(dòng)開(kāi)發(fā)模式,CQRS命令查詢(xún)職責(zé)分離模式,事件溯源模式,還實(shí)現(xiàn)了Saga事務(wù)狀態(tài)機(jī)模式。當(dāng)然,這個(gè)項(xiàng)目的底層也實(shí)現(xiàn)了CDC變更數(shù)據(jù)捕獲模式。

波波認(rèn)為,Charis的項(xiàng)目,作為學(xué)習(xí)研究還是有價(jià)值的,但是暫不建議生產(chǎn)級(jí)使用,因?yàn)樗臇|西不是一線企業(yè)落地出來(lái)的,主要是他個(gè)人開(kāi)發(fā)的。至于說(shuō)Charis的項(xiàng)目能否在一線企業(yè)落地,還有待時(shí)間的進(jìn)一步檢驗(yàn)。

Transactional Outbox vs CDC

好的,前面我介紹了解決數(shù)據(jù)的事務(wù)性分發(fā)的兩種落地模式,一種是事務(wù)性發(fā)件箱模式,另外一種是變更數(shù)據(jù)捕獲模式,這兩種模式其實(shí)各有優(yōu)劣,為了幫助大家做選型決策,我這邊對(duì)這兩種模式進(jìn)行一個(gè)比較,請(qǐng)看上面的比較表格:

  1. 首先比較一下復(fù)雜性,事務(wù)性發(fā)件箱相對(duì)比較簡(jiǎn)單,簡(jiǎn)單做法只需要在數(shù)據(jù)庫(kù)中增加一個(gè)發(fā)件箱表,然后再啟一個(gè)Poller線程拉消息和發(fā)消息就可以了。CDC技術(shù)相對(duì)比較復(fù)雜,需要你深入理解數(shù)據(jù)庫(kù)的事務(wù)日志格式和協(xié)議。另外Miner的實(shí)現(xiàn)也不簡(jiǎn)單,要保證不丟消息,如果生產(chǎn)部署的話,還要考慮Miner的高可以部署,還有監(jiān)控告警等環(huán)節(jié)。

  2. 第二個(gè)比較的是Polling延遲和開(kāi)銷(xiāo)。事務(wù)性發(fā)件箱的Polling是近實(shí)時(shí)的,同時(shí)如果頻繁拉數(shù)據(jù)庫(kù)表,難免會(huì)有性能開(kāi)銷(xiāo)。CDC是比較實(shí)時(shí)的,同時(shí)它不侵入數(shù)據(jù)庫(kù)和表,所以它的性能開(kāi)銷(xiāo)相對(duì)小。

  3. 第三個(gè)比較的是應(yīng)用侵入性。事務(wù)性發(fā)件箱是有一定的應(yīng)用侵入性的,應(yīng)用在更新業(yè)務(wù)數(shù)據(jù)的同時(shí),還要單獨(dú)發(fā)送消息。CDC對(duì)應(yīng)用是無(wú)侵入的,因?yàn)樗〉氖菙?shù)據(jù)庫(kù)事務(wù)日志,這個(gè)和應(yīng)用是不直接耦合的。當(dāng)然,CDC和事務(wù)性發(fā)件箱模式并不排斥,你可以在應(yīng)用層采用事務(wù)性發(fā)件箱模式,同時(shí)仍然采用CDC到數(shù)據(jù)庫(kù)去捕獲和發(fā)件箱中的消息對(duì)應(yīng)的事務(wù)日志。這個(gè)方法對(duì)應(yīng)用有一定的侵入性,但是通過(guò)CDC可以獲得較好的數(shù)據(jù)同步性能。

  4. 第四點(diǎn)是適用場(chǎng)合。事務(wù)性發(fā)件箱主要適用于中小規(guī)模的企業(yè),因?yàn)樽龇ū容^簡(jiǎn)單,一個(gè)開(kāi)發(fā)人員也可以搞定。CDC則主要適用于中大規(guī)?;ヂ?lián)網(wǎng)企業(yè),最好有獨(dú)立框架團(tuán)隊(duì)負(fù)責(zé)CDC的治理和維護(hù)。像Netflix/Airbnb這樣的一線互聯(lián)網(wǎng)公司,也是在中后期才引入CDC技術(shù)的[參考附錄1/2/3]。

Single Source of Truth

前面我解答了如何解決微服務(wù)的數(shù)據(jù)一致性分發(fā)問(wèn)題,也給出了可落地的方案。最后,我特別說(shuō)明在實(shí)踐中進(jìn)行數(shù)據(jù)分發(fā)的一個(gè)原則,叫Single Source of Truth,翻成中文就是單一真實(shí)數(shù)據(jù)源。它的意思是說(shuō),你要實(shí)現(xiàn)數(shù)據(jù)分發(fā),目標(biāo)服務(wù)可以有很多,但是一定要注意,數(shù)據(jù)的主人只能有一個(gè),它是數(shù)據(jù)的權(quán)威記錄系統(tǒng)(canonical system of record),其它的數(shù)據(jù)都是只讀的,非權(quán)威的拷貝(read-only, non-authoritative copy)。

換句話說(shuō),任何時(shí)候,對(duì)于某類(lèi)數(shù)據(jù),它主人應(yīng)該是唯一的,它是Single Source of Truth,只有它可以修改數(shù)據(jù),其它的服務(wù)可以獲得數(shù)據(jù)拷貝,做本地緩存也沒(méi)問(wèn)題,但是這些數(shù)據(jù)都是只讀的,不能修改。

只有遵循這條原則,數(shù)據(jù)分發(fā)才能正常工作,不會(huì)產(chǎn)生不一致的情況。

結(jié)論

  1. Netflix和Airbnb等一線互聯(lián)網(wǎng)公司的實(shí)踐證明,企業(yè)要真正實(shí)現(xiàn)松散耦合、可擴(kuò)展和高性能的微服務(wù)架構(gòu),那么底層的數(shù)據(jù)分發(fā)同步能力是非常關(guān)鍵的。

  2. 數(shù)據(jù)分發(fā)技術(shù),簡(jiǎn)單的可以采用事務(wù)性發(fā)件箱模式來(lái)實(shí)現(xiàn),重量級(jí)的可以考慮變更數(shù)據(jù)捕獲CDC技術(shù)來(lái)實(shí)現(xiàn)。事務(wù)性發(fā)件箱可以參考Killbill Queue的實(shí)現(xiàn),CDC可以參考阿里的Canal等開(kāi)源產(chǎn)品來(lái)實(shí)現(xiàn)。

  3. 最簡(jiǎn)單的雙寫(xiě)也是實(shí)現(xiàn)數(shù)據(jù)分發(fā)的一種方式,但是為了保證一致性,需要引入后臺(tái)校驗(yàn)補(bǔ)償程序。

  4. 最后,數(shù)據(jù)分發(fā)/同步的原則是:確保單一真實(shí)數(shù)據(jù)源(Single Source of Truth)。系統(tǒng)中數(shù)據(jù)的主人應(yīng)該只有一個(gè),只有主人可以寫(xiě)入數(shù)據(jù),其它都是只讀拷貝。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多

    亚洲精品偷拍一区二区三区| av一区二区三区天堂| 国产精品一区二区视频成人| 精品欧美国产一二三区| 欧美亚洲三级视频在线观看| 99热九九在线中文字幕| 欧美日韩国产午夜福利| 亚洲欧美中文字幕精品| 男女激情视频在线免费观看| 色婷婷日本视频在线观看| 扒开腿狂躁女人爽出白浆av | 亚洲中文字幕熟女丝袜久久| 内射精子视频欧美一区二区| 日本一品道在线免费观看| 在线观看免费无遮挡大尺度视频| 日本熟女中文字幕一区| 亚洲国产91精品视频| 国产成人一区二区三区久久| 在线中文字幕亚洲欧美一区| 国产熟女一区二区不卡| 好吊妞视频免费在线观看| 99视频精品免费视频| 东京热电东京热一区二区三区| 熟女少妇久久一区二区三区| 国产欧美日韩一级小黄片| 欧美日韩亚洲巨色人妻| 精品丝袜一区二区三区性色| 久久精品国产99国产免费| 亚洲精品国男人在线视频| 好吊视频一区二区在线| 国产性色精品福利在线观看| 国产精品内射视频免费| 日本精品理论在线观看| 狠狠干狠狠操亚洲综合| 草草草草在线观看视频| 成人免费高清在线一区二区| 91天堂素人精品系列全集| 日韩免费国产91在线| 日韩女优精品一区二区三区| 一区二区在线激情视频| 日韩亚洲精品国产第二页|