成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

為什么說(shuō)傳統(tǒng)分布式事務(wù)不再適用于微服務(wù)架構(gòu)?

大數(shù)據(jù) 分布式
微服務(wù)架構(gòu)該如何保證數(shù)據(jù)一致性呢?本文就來(lái)談?wù)勥@個(gè)話題。

[[180941]]

傳統(tǒng)應(yīng)用使用本地事務(wù)和分布式事務(wù)保證數(shù)據(jù)一致性,但是在微服務(wù)架構(gòu)中數(shù)據(jù)都是服務(wù)私有的,需要通過(guò)服務(wù)提供的API來(lái)訪問(wèn),所以分布式事務(wù)不再適用微服務(wù)架構(gòu)。那么微服務(wù)架構(gòu)又該如何保證數(shù)據(jù)一致性呢?本文就來(lái)談?wù)勥@個(gè)話題。

  1. 傳統(tǒng)分布式事務(wù)不是微服務(wù)中數(shù)據(jù)一致性的***選擇
  2. 微服務(wù)架構(gòu)中應(yīng)滿足數(shù)據(jù)最終一致性原則
  3. 微服務(wù)架構(gòu)實(shí)現(xiàn)最終一致性的三種模式
  4. 對(duì)賬是***的***防線

傳統(tǒng)分布式事務(wù)

我們先來(lái)看下***部分,傳統(tǒng)使用本地事務(wù)和分布式事務(wù)保證一致性。

36大數(shù)據(jù)

傳統(tǒng)單機(jī)應(yīng)用一般都會(huì)使用一個(gè)關(guān)系型數(shù)據(jù)庫(kù),好處是應(yīng)用可以使用ACID。為保證一致性我們只需要:開(kāi)始一個(gè)事務(wù),改變(插入,刪除,更新)很多行,然后提交事務(wù)(如果有異常時(shí)回滾事務(wù))。更進(jìn)一步,借助開(kāi)發(fā)平臺(tái)中的數(shù)據(jù)訪問(wèn)技術(shù)和框架(如 Spring),我們需要做的事情更少,只需要關(guān)注數(shù)據(jù)本身的改變。

隨著組織規(guī)模不斷擴(kuò)大,業(yè)務(wù)量不斷增長(zhǎng),單機(jī)應(yīng)用和數(shù)據(jù)庫(kù)已經(jīng)不足以支持龐大的業(yè)務(wù)量和數(shù)據(jù)量,這個(gè)時(shí)候需要對(duì)應(yīng)用和數(shù)據(jù)庫(kù)進(jìn)行拆分,這就出現(xiàn)了一個(gè)應(yīng)用需要同時(shí)訪問(wèn)兩個(gè)或兩個(gè)以上的數(shù)據(jù)庫(kù)情況。開(kāi)始我們用分布式事務(wù)來(lái)保證一致性,也就是我們常說(shuō)的兩階段提交協(xié)議(2PC)。

36大數(shù)據(jù)

本地事務(wù)和分布式事務(wù)現(xiàn)在已經(jīng)非常成熟,相關(guān)介紹很豐富,此處不再討論。我們下面來(lái)談?wù)劄槭裁捶植际绞聞?wù)不適用于微服務(wù)架構(gòu)。

36大數(shù)據(jù)

首先,對(duì)于微服務(wù)架構(gòu)來(lái)說(shuō),數(shù)據(jù)訪問(wèn)變得更加復(fù)雜,這是因?yàn)閿?shù)據(jù)都是微服務(wù)私有的,唯一可訪問(wèn)的方式就是通過(guò) API。這種打包數(shù)據(jù)訪問(wèn)方式使得微服務(wù)之間松耦合,并且彼此之間獨(dú)立,更容易進(jìn)行性能擴(kuò)展。

其次,不同的微服務(wù)經(jīng)常使用不同的數(shù)據(jù)庫(kù)。應(yīng)用會(huì)產(chǎn)生各種不同類型的數(shù)據(jù),關(guān)系型數(shù)據(jù)庫(kù)并不一定是***選擇。

例如,某個(gè)產(chǎn)生和查詢字符串的應(yīng)用采用 Elasticsearch 的字符搜索引擎;某個(gè)產(chǎn)生社交圖片數(shù)據(jù)的應(yīng)用可以采用圖數(shù)據(jù)庫(kù),例如Neo4j。

基于微服務(wù)的應(yīng)用一般都使用 SQL 和 NoSQL 結(jié)合的模式。但是這些非關(guān)系型數(shù)據(jù)大多數(shù)并不支持 2PC。

可見(jiàn)在微服務(wù)架構(gòu)中已經(jīng)不能選擇分布式事務(wù)了。

最終一致性原則

依據(jù) CAP 理論,必須在可用性(availability)和一致性(consistency)之間做出選擇。如果選擇提供一致性需要付出在滿足一致性之前阻塞其他并發(fā)訪問(wèn)的代價(jià)。這可能持續(xù)一個(gè)不確定的時(shí)間,尤其是在系統(tǒng)已經(jīng)表現(xiàn)出高延遲時(shí)或者網(wǎng)絡(luò)故障導(dǎo)致失去連接時(shí)。

依據(jù)目前的成功經(jīng)驗(yàn),可用性一般是更好的選擇,但是在服務(wù)和數(shù)據(jù)庫(kù)之間維護(hù)數(shù)據(jù)一致性是非常根本的需求,微服務(wù)架構(gòu)中應(yīng)選擇滿足最終一致性。

最終一致性是指系統(tǒng)中的所有數(shù)據(jù)副本經(jīng)過(guò)一定時(shí)間后,最終能夠達(dá)到一致的狀態(tài)。

當(dāng)然選擇了最終一致性,就要保證到最終的這段時(shí)間要在用戶可接受的范圍之內(nèi)。那么我們?cè)趺磳?shí)現(xiàn)最終一致性呢?

從一致性的本質(zhì)來(lái)看,是要保證在一個(gè)業(yè)務(wù)邏輯中包含的服務(wù)要么都成功,要么都失敗。那我們?cè)趺催x擇方向呢?保證成功還是保證失敗呢?

36大數(shù)據(jù)

我們說(shuō)業(yè)務(wù)模式?jīng)Q定了我們的選擇。實(shí)現(xiàn)最終一致性有三種模式:可靠事件模式、業(yè)務(wù)補(bǔ)償模式、TCC 模式。

可靠事件模式

可靠事件模式屬于事件驅(qū)動(dòng)架構(gòu),當(dāng)某件重要事情發(fā)生時(shí),例如更新一個(gè)業(yè)務(wù)實(shí)體,微服務(wù)會(huì)向消息代理發(fā)布一個(gè)事件。消息代理會(huì)向訂閱事件的微服務(wù)推送事件,當(dāng)訂閱這些事件的微服務(wù)接收此事件時(shí),就可以完成自己的業(yè)務(wù),也可能會(huì)引發(fā)更多的事件發(fā)布。

1. 如訂單服務(wù)創(chuàng)建一個(gè)待支付的訂單,發(fā)布一個(gè)“創(chuàng)建訂單”的事件。

36大數(shù)據(jù)

2. 支付服務(wù)消費(fèi)“創(chuàng)建訂單”事件,支付完成后發(fā)布一個(gè)“支付完成”事件。

36大數(shù)據(jù)

3. 訂單服務(wù)消費(fèi)“支付完成”事件,訂單狀態(tài)更新為待出庫(kù)。

36大數(shù)據(jù)

從而就實(shí)現(xiàn)了完成的業(yè)務(wù)流程。但是這并不是一個(gè)***的流程。

36大數(shù)據(jù)

這個(gè)過(guò)程可能導(dǎo)致出現(xiàn)不一致的地方在于:某個(gè)微服務(wù)在更新了業(yè)務(wù)實(shí)體后發(fā)布事件卻失敗;雖然微服務(wù)發(fā)布事件成功,但是消息代理未能正確推送事件到訂閱的微服務(wù);接受事件的微服務(wù)重復(fù)消費(fèi)了事件。

可靠事件模式在于保證可靠事件投遞和避免重復(fù)消費(fèi),可靠事件投遞定義為:

  • 每個(gè)服務(wù)原子性的業(yè)務(wù)操作和發(fā)布事件。
  • 消息代理確保事件傳遞至少一次。

避免重復(fù)消費(fèi)要求服務(wù)實(shí)現(xiàn)冪等性,如支付服務(wù)不能因?yàn)橹貜?fù)收到事件而多次支付。

因?yàn)楝F(xiàn)在流行的消息隊(duì)列都實(shí)現(xiàn)了事件的持久化和 at least once 的投遞模式,『消息代理確保事件投遞至少一次』已經(jīng)滿足,今天不做展開(kāi)。

下面分享的內(nèi)容主要從可靠事件投遞和實(shí)現(xiàn)冪等性兩方面來(lái)討論,我們先來(lái)看可靠事件投遞。

首先我們來(lái)看一個(gè)實(shí)現(xiàn)的代碼片段,這是從某生產(chǎn)系統(tǒng)上截取下來(lái)的。

36大數(shù)據(jù)

根據(jù)上述代碼及注釋,初看可能出現(xiàn) 3 種情況:

  1. 操作數(shù)據(jù)庫(kù)成功,向消息代理投遞事件也成功。
  2. 操作數(shù)據(jù)庫(kù)失敗,不會(huì)向消息代理中投遞事件了。
  3. 操作數(shù)據(jù)庫(kù)成功,但是向消息代理中投遞事件時(shí)失敗,向外拋出了異常,剛剛執(zhí)行的更新數(shù)據(jù)庫(kù)的操作將被回滾。

從上面分析的幾種情況來(lái)看,貌似沒(méi)有問(wèn)題。但是仔細(xì)分析不難發(fā)現(xiàn)缺陷所在,在上面的處理過(guò)程中存在一段隱患時(shí)間窗口。

36大數(shù)據(jù)

微服務(wù) A 投遞事件的時(shí)候可能消息代理已經(jīng)處理成功,但是返回響應(yīng)的時(shí)候網(wǎng)絡(luò)異常,導(dǎo)致 append 操作拋出異常。最終結(jié)果是事件被投遞,數(shù)據(jù)庫(kù)卻被回滾。

36大數(shù)據(jù)

在投遞完成后到數(shù)據(jù)庫(kù) commit 操作之間如果微服務(wù) A 宕機(jī)也將造成數(shù)據(jù)庫(kù)操作因?yàn)檫B接異常關(guān)閉而被回滾。最終結(jié)果還是事件被投遞,數(shù)據(jù)庫(kù)卻被回滾。這個(gè)實(shí)現(xiàn)往往運(yùn)行很長(zhǎng)時(shí)間都沒(méi)有出過(guò)問(wèn)題,但是一旦出現(xiàn)了將會(huì)讓人感覺(jué)莫名,很難發(fā)現(xiàn)問(wèn)題所在。

下面給出兩種可靠事件投遞的實(shí)現(xiàn)方式。

1. 本地事件表

本地事件表方法將事件和業(yè)務(wù)數(shù)據(jù)保存在同一個(gè)數(shù)據(jù)庫(kù)中,使用一個(gè)額外的“事件恢復(fù)”服務(wù)來(lái)恢復(fù)事件,由本地事務(wù)保證更新業(yè)務(wù)和發(fā)布事件的原子性。考慮到事件恢復(fù)可能會(huì)有一定的延時(shí),服務(wù)在完成本地事務(wù)后可立即向消息代理發(fā)布一個(gè)事件。

本地事件表

  1. 微服務(wù)在同一個(gè)本地事務(wù)中記錄業(yè)務(wù)數(shù)據(jù)和事件。
  2. 微服務(wù)實(shí)時(shí)發(fā)布一個(gè)事件立即通知關(guān)聯(lián)的業(yè)務(wù)服務(wù),如果事件發(fā)布成功立即刪除記錄的事件。
  3. 事件恢復(fù)服務(wù)定時(shí)從事件表中恢復(fù)未發(fā)布成功的事件,重新發(fā)布,重新發(fā)布成功才刪除記錄的事件。

其中第Ⅱ條的操作主要是為了增加發(fā)布事件的實(shí)時(shí)性,由第三條保證事件一定被發(fā)布。

本地事件表方式業(yè)務(wù)系統(tǒng)和事件系統(tǒng)耦合比較緊密,額外的事件數(shù)據(jù)庫(kù)操作也會(huì)給數(shù)據(jù)庫(kù)帶來(lái)額外的壓力,可能成為瓶頸。

2. 外部事件表

外部事件表方法將事件持久化到外部的事件系統(tǒng),事件系統(tǒng)需提供實(shí)時(shí)事件服務(wù)以接受微服務(wù)發(fā)布事件,同時(shí)事件系統(tǒng)還需要提供事件恢復(fù)服務(wù)來(lái)確認(rèn)和恢復(fù)事件。

外部事件表

  1. 業(yè)務(wù)服務(wù)在事務(wù)提交前,通過(guò)實(shí)時(shí)事件服務(wù)向事件系統(tǒng)請(qǐng)求發(fā)送事件,事件系統(tǒng)只記錄事件并不真正發(fā)送。
  2. 業(yè)務(wù)服務(wù)在提交后,通過(guò)實(shí)時(shí)事件服務(wù)向事件系統(tǒng)確認(rèn)發(fā)送,事件得到確認(rèn)后事件系統(tǒng)才真正發(fā)布事件到消息代理。
  3. 業(yè)務(wù)服務(wù)在業(yè)務(wù)回滾時(shí),通過(guò)實(shí)時(shí)事件向事件系統(tǒng)取消事件。
  4. 如果業(yè)務(wù)服務(wù)在發(fā)送確認(rèn)或取消之前停止服務(wù)了怎么辦呢?事件系統(tǒng)的事件恢復(fù)服務(wù)會(huì)定期找到未確認(rèn)發(fā)送的事件向業(yè)務(wù)服務(wù)查詢狀態(tài),根據(jù)業(yè)務(wù)服務(wù)返回的狀態(tài)決定事件是要發(fā)布還是取消。

該方式將業(yè)務(wù)系統(tǒng)和事件系統(tǒng)獨(dú)立解耦,都可以獨(dú)立伸縮。但是這種方式需要一次額外的發(fā)送操作,并且需要發(fā)布者提供額外的查詢接口。

介紹完了可靠事件投遞再來(lái)說(shuō)一說(shuō)冪等性的實(shí)現(xiàn),有些事件本身是冪等的,有些事件卻不是。

本身具有冪等性的事件需要考慮執(zhí)行順序

如果事件本身描述的是某個(gè)時(shí)間點(diǎn)的固定值(如賬戶余額為 100),而不是描述一條轉(zhuǎn)換指令(如余額增加 10),那么這個(gè)事件是冪等的。

我們要意識(shí)到事件可能出現(xiàn)的次數(shù)和順序是不可預(yù)測(cè)的,需要保證冪等事件的順序執(zhí)行,否則結(jié)果往往不是我們想要的。

如果我們先后收到兩條事件,(1)賬戶余額更新為100,(2)賬戶余額更新為120。

1. 微服務(wù)收到事件(1)

微服務(wù)收到事件(1)

2. 微服務(wù)收到事件(2)

微服務(wù)收到事件(2)

3. 微服務(wù)再次收到事件(1)

微服務(wù)再次收到事件(1)

顯然結(jié)果是錯(cuò)誤的,所以我們需要保證事件(2)一旦執(zhí)行事件(1)就不能再處理,否則賬戶余額仍不是我們想要的結(jié)果。

為保證事件的順序一個(gè)簡(jiǎn)單的做法是在事件中添加時(shí)間戳,微服務(wù)記錄每類型的事件***處理的時(shí)間戳,如果收到的事件的時(shí)間戳早于我們記錄的,丟棄該事件。如果事件不是在同一個(gè)服務(wù)器上發(fā)出的,那么服務(wù)器之間的時(shí)間同步是個(gè)難題,更穩(wěn)妥的做法是使用一個(gè)全局遞增序列號(hào)替換時(shí)間戳。

對(duì)于本身不具有冪等性的操作,主要思想是為每條事件存儲(chǔ)執(zhí)行結(jié)果,當(dāng)收到一條事件時(shí)我們需要根據(jù)事件的 ID 查詢?cè)撌录欠褚呀?jīng)執(zhí)行過(guò),如果執(zhí)行過(guò)直接返回上一次的執(zhí)行結(jié)果,否則調(diào)度執(zhí)行事件。

36大數(shù)據(jù)

在這個(gè)思想下我們需要考慮重復(fù)執(zhí)行一條事件和查詢存儲(chǔ)結(jié)果的開(kāi)銷。

重復(fù)處理開(kāi)銷小的事件

如果重復(fù)處理一條事件開(kāi)銷很小,或者可預(yù)見(jiàn)只有非常少的事件會(huì)被重復(fù)接收,可以選擇重復(fù)處理一次事件,在將事件數(shù)據(jù)持久化時(shí)由數(shù)據(jù)庫(kù)拋出唯一性約束異常。

重復(fù)處理開(kāi)銷大事件使用事件存儲(chǔ)過(guò)濾重復(fù)事件

如果重復(fù)處理一條事件的開(kāi)銷相比額外一次查詢的開(kāi)銷要高很多,使用一個(gè)過(guò)濾服務(wù)來(lái)過(guò)濾重復(fù)的事件,過(guò)濾服務(wù)使用事件存儲(chǔ)存儲(chǔ)已經(jīng)處理過(guò)的事件和結(jié)果。

當(dāng)收到一條事件時(shí),過(guò)濾服務(wù)首先查詢事件存儲(chǔ),確定該條事件是否已經(jīng)被處理過(guò),如果事件已經(jīng)被處理過(guò),直接返回存儲(chǔ)的結(jié)果;否則調(diào)度業(yè)務(wù)服務(wù)執(zhí)行處理,并將處理完的結(jié)果存儲(chǔ)到事件存儲(chǔ)中。

一般情況下上面的方法能夠運(yùn)行得很好,如果我們的微服務(wù)是 RPC 類的服務(wù)我們需要更加小心,可能出現(xiàn)的問(wèn)題在于,(1)過(guò)濾服務(wù)在業(yè)務(wù)處理完成后才將事件結(jié)果存儲(chǔ)到事件存儲(chǔ)中,但是在業(yè)務(wù)處理完成前有可能就已經(jīng)收到重復(fù)事件,由于是 RPC 服務(wù)也不能依賴數(shù)據(jù)庫(kù)的唯一性約束;(2)業(yè)務(wù)服務(wù)的處理結(jié)果可能出現(xiàn)位置狀態(tài),一般出現(xiàn)在正常提交請(qǐng)求但是沒(méi)有收到響應(yīng)的時(shí)候。

對(duì)于問(wèn)題(1)可以按步驟記錄事件處理過(guò)程,比如事件的記錄事件的處理過(guò)程為“接收”、“發(fā)送請(qǐng)求”、“收到應(yīng)答”、“處理完成”。好處是過(guò)濾服務(wù)能及時(shí)的發(fā)現(xiàn)重復(fù)事件,進(jìn)一步還能根據(jù)事件狀態(tài)作不同的處理。

對(duì)于問(wèn)題(2)可以通過(guò)一次額外的查詢請(qǐng)求來(lái)確定事件的實(shí)際處理狀態(tài),要注意額外的查詢會(huì)帶來(lái)更長(zhǎng)時(shí)間的延時(shí),更進(jìn)一步可能某些 RPC 服務(wù)根本不提供查詢接口。此時(shí)只能選擇接收暫時(shí)的不一致,時(shí)候采用對(duì)賬和人工接入的方式來(lái)保證一致性。

補(bǔ)償模式

為了描述方便,這里先定義兩個(gè)概念:

  1. 業(yè)務(wù)異常:業(yè)務(wù)邏輯產(chǎn)生錯(cuò)誤的情況,比如賬戶余額不足、商品庫(kù)存不足等。
  2. 技術(shù)異常:非業(yè)務(wù)邏輯產(chǎn)生的異常,如網(wǎng)絡(luò)連接異常、網(wǎng)絡(luò)超時(shí)等。

補(bǔ)償模式使用一個(gè)額外的協(xié)調(diào)服務(wù)來(lái)協(xié)調(diào)各個(gè)需要保證一致性的微服務(wù),協(xié)調(diào)服務(wù)按順序調(diào)用各個(gè)微服務(wù),如果某個(gè)微服務(wù)調(diào)用異常(包括業(yè)務(wù)異常和技術(shù)異常)就取消之前所有已經(jīng)調(diào)用成功的微服務(wù)。

補(bǔ)償模式建議僅用于不能避免出現(xiàn)業(yè)務(wù)異常的情況,如果有可能應(yīng)該優(yōu)化業(yè)務(wù)模式,以避免要求補(bǔ)償事務(wù)。如賬戶余額不足的業(yè)務(wù)異常可通過(guò)預(yù)先凍結(jié)金額的方式避免,商品庫(kù)存不足可要求商家準(zhǔn)備額外的庫(kù)存等。

我們通過(guò)一個(gè)實(shí)例來(lái)說(shuō)明補(bǔ)償模式,一家旅行公司提供預(yù)訂行程的業(yè)務(wù),可以通過(guò)公司的網(wǎng)站提前預(yù)訂飛機(jī)票、火車(chē)票、酒店等。

假設(shè)一位客戶規(guī)劃的行程是:

上海-北京6月19日9點(diǎn)的某某航班。

某某酒店住宿3晚。

北京-上海6月22日17點(diǎn)火車(chē)。

在客戶提交行程后,旅行公司的預(yù)訂行程業(yè)務(wù)按順序串行的調(diào)用航班預(yù)訂服務(wù)、酒店預(yù)訂服務(wù)、火車(chē)預(yù)訂服務(wù)。***的火車(chē)預(yù)訂服務(wù)成功后整個(gè)預(yù)訂業(yè)務(wù)才算完成。

一位客戶規(guī)劃的行程

如果火車(chē)票預(yù)訂服務(wù)沒(méi)有調(diào)用成功,那么之前預(yù)訂的航班、酒店都得取消。取消之前預(yù)訂的酒店、航班即為補(bǔ)償過(guò)程。

火車(chē)票預(yù)訂服務(wù)沒(méi)有調(diào)用成功

為了降低開(kāi)發(fā)的復(fù)雜性和提高效率,協(xié)調(diào)服務(wù)實(shí)現(xiàn)為一個(gè)通用的補(bǔ)償框架。補(bǔ)償框架提供服務(wù)編排和自動(dòng)完成補(bǔ)償?shù)哪芰Α?/p>

要實(shí)現(xiàn)補(bǔ)償過(guò)程,我們需要做到兩點(diǎn):

首先要確定失敗的步驟和狀態(tài),從而確定需要補(bǔ)償?shù)姆秶?/p>

火車(chē)票預(yù)訂服務(wù)沒(méi)有調(diào)用成功

在上面的例子中我們不僅要知道第 3 個(gè)步驟(預(yù)訂火車(chē))失敗,還要知道失敗的原因。如果是因?yàn)轭A(yù)訂火車(chē)服務(wù)返回?zé)o票,那么補(bǔ)償過(guò)程只需要取消前兩個(gè)步驟就可以了;但是如果失敗的原因是因?yàn)榫W(wǎng)絡(luò)超時(shí),那么補(bǔ)償過(guò)程除前兩個(gè)步驟之外還需要包括第 3 個(gè)步驟。

其次要能提供補(bǔ)償操作使用到的業(yè)務(wù)數(shù)據(jù)。

比如一個(gè)支付微服務(wù)的補(bǔ)償操作要求參數(shù)包括支付時(shí)的業(yè)務(wù)流水 id、賬號(hào)和金額。理論上說(shuō)實(shí)際完成補(bǔ)償操作可以根據(jù)唯一的業(yè)務(wù)流水 id 就可以,但是提供更多的要素有益于微服務(wù)的健壯性,微服務(wù)在收到補(bǔ)償操作的時(shí)候可以做業(yè)務(wù)的檢查,比如檢查賬戶是否相等,金額是否一致等等。

實(shí)現(xiàn)補(bǔ)償模式的關(guān)鍵在于業(yè)務(wù)流水的記錄

做到上面兩點(diǎn)的辦法是記錄完整的業(yè)務(wù)流水,可以通過(guò)業(yè)務(wù)流水的狀態(tài)來(lái)確定需要補(bǔ)償?shù)牟襟E,同時(shí)業(yè)務(wù)流水為補(bǔ)償操作提供需要的業(yè)務(wù)數(shù)據(jù)。

業(yè)務(wù)流水為補(bǔ)償操作提供需要的業(yè)務(wù)數(shù)據(jù)

當(dāng)客戶的一個(gè)預(yù)訂請(qǐng)求達(dá)到時(shí),協(xié)調(diào)服務(wù)(補(bǔ)償框架)為請(qǐng)求生成一個(gè)全局唯一的業(yè)務(wù)流水號(hào),并在調(diào)用各個(gè)工作服務(wù)的同時(shí)記錄完整的狀態(tài)。

  1. 記錄調(diào)用 bookFlight 的業(yè)務(wù)流水,調(diào)用 bookFlight 服務(wù),更新業(yè)務(wù)流水狀態(tài)。
  2. 記錄調(diào)用 bookHotel 的業(yè)務(wù)流水,調(diào)用 bookHotel 服務(wù),更新業(yè)務(wù)流水狀態(tài)。
  3. 記錄調(diào)用 bookTrain 的業(yè)務(wù)流水,調(diào)用 bookTrain 服務(wù),更新業(yè)務(wù)流水狀態(tài)。

當(dāng)調(diào)用某個(gè)服務(wù)出現(xiàn)異常時(shí),比如第 3 步驟(預(yù)訂火車(chē))異常。

當(dāng)調(diào)用某個(gè)服務(wù)出現(xiàn)異常時(shí),比如第 3 步驟(預(yù)訂火車(chē))異常

協(xié)調(diào)服務(wù)(補(bǔ)償框架)同樣會(huì)記錄第 3 步的狀態(tài),同時(shí)會(huì)另外記錄一條事件,說(shuō)明業(yè)務(wù)出現(xiàn)了異常。然后就是執(zhí)行補(bǔ)償過(guò)程了,可以從業(yè)務(wù)流水的狀態(tài)中知道補(bǔ)償?shù)姆秶a(bǔ)償過(guò)程中需要的業(yè)務(wù)數(shù)據(jù)從記錄的業(yè)務(wù)流水中獲取。

對(duì)于一個(gè)通用的補(bǔ)償框架來(lái)說(shuō),預(yù)先知道微服務(wù)需要記錄的業(yè)務(wù)要素是不可能的。那么就需要一種方法來(lái)保證業(yè)務(wù)流水的可擴(kuò)展性,這里介紹兩種方法:大表和關(guān)聯(lián)表。

大表和關(guān)聯(lián)表

大表顧明思議就是設(shè)計(jì)時(shí)除必須的字段外,還需要預(yù)留大量的備用字段,框架可以提供輔助工具來(lái)幫助將業(yè)務(wù)數(shù)據(jù)映射到備用字段中。

關(guān)聯(lián)表,分為框架表和業(yè)務(wù)表,技術(shù)表中保存為實(shí)現(xiàn)補(bǔ)償操作所需要的技術(shù)數(shù)據(jù),業(yè)務(wù)表保存業(yè)務(wù)數(shù)據(jù),通過(guò)在技術(shù)表中增加業(yè)務(wù)表名和業(yè)務(wù)表主鍵來(lái)建立和業(yè)務(wù)數(shù)據(jù)的關(guān)聯(lián)。

大表對(duì)于框架層實(shí)現(xiàn)起來(lái)簡(jiǎn)單,但是也有一些難點(diǎn),比如預(yù)留多少字段合適,每個(gè)字段又需要預(yù)留多少長(zhǎng)度。另外一個(gè)難點(diǎn)是如果向從數(shù)據(jù)層面來(lái)查詢數(shù)據(jù),很難看出備用字段的業(yè)務(wù)含義,維護(hù)過(guò)程不友好。

關(guān)聯(lián)表在業(yè)務(wù)要素上更靈活,能支持不同的業(yè)務(wù)類型記錄不同的業(yè)務(wù)要素;但是對(duì)于框架實(shí)現(xiàn)上難度更高,另外每次查詢都需要復(fù)雜的關(guān)聯(lián)動(dòng)作,性能方面會(huì)受影響。

有了上面的完整的流水記錄,協(xié)調(diào)服務(wù)就可以根據(jù)工作服務(wù)的狀態(tài)在異常時(shí)完成補(bǔ)償過(guò)程。但是補(bǔ)償由于網(wǎng)絡(luò)等原因,補(bǔ)償操作并不一定能保證 100%成功,這時(shí)候我們還要做更多一點(diǎn)。

通過(guò)重試保證補(bǔ)償過(guò)程的完整,從而滿足最終一致性

補(bǔ)償過(guò)程作為一個(gè)服務(wù)調(diào)用過(guò)程同樣存在調(diào)用不成功的情況,這個(gè)時(shí)候需要通過(guò)重試的機(jī)制來(lái)保證補(bǔ)償?shù)某晒β省.?dāng)然這也就要求補(bǔ)償操作本身具備冪等性。

關(guān)于冪等性的實(shí)現(xiàn)在前面做過(guò)討論。

如果只是一味的失敗就立即重試會(huì)給工作服務(wù)造成不必要的壓力,我們要根據(jù)服務(wù)執(zhí)行失敗的原因來(lái)選擇不同的重試策略。

通過(guò)重試保證補(bǔ)償過(guò)程的完整,從而滿足最終一致性

1) 如果失敗的原因不是暫時(shí)性的,由于業(yè)務(wù)因素導(dǎo)致(如業(yè)務(wù)要素檢查失敗)的業(yè)務(wù)錯(cuò)誤,這類錯(cuò)誤是不會(huì)重發(fā)就能自動(dòng)恢復(fù)的,那么應(yīng)該立即終止重試。

2) 如果錯(cuò)誤的原因是一些罕見(jiàn)的異常,比如因?yàn)榫W(wǎng)絡(luò)傳輸過(guò)程出現(xiàn)數(shù)據(jù)丟失或者錯(cuò)誤,應(yīng)該立即再次重試,因?yàn)轭愃频腻e(cuò)誤一般很少會(huì)再次發(fā)生。

3) 如果錯(cuò)誤的原因是系統(tǒng)繁忙(比如 HTTP 協(xié)議返回的 500 或者另外約定的返回碼)或者超時(shí),這個(gè)時(shí)候需要等待一些時(shí)間再重試。

重試操作一般會(huì)指定重試次數(shù)上線,如果重試次數(shù)達(dá)到了上限就不再進(jìn)行重試了。這個(gè)時(shí)候應(yīng)該通過(guò)一種手段通知相關(guān)人員進(jìn)行處理。

對(duì)于等待重試的策略如果重試時(shí)仍然錯(cuò)誤,可逐漸增加等待的時(shí)間,直到達(dá)到一個(gè)上限后,以上限作為等待時(shí)間。

如果某個(gè)時(shí)刻聚集了大量需要重試的操作,補(bǔ)償框架需要控制請(qǐng)求的流量,以防止對(duì)工作服務(wù)造成過(guò)大的壓力。

另外關(guān)于補(bǔ)償模式還有幾點(diǎn)補(bǔ)充說(shuō)明。

微服務(wù)實(shí)現(xiàn)補(bǔ)償操作不是簡(jiǎn)單的回退到業(yè)務(wù)發(fā)生時(shí)的狀態(tài),因?yàn)榭赡苓€有其他的并發(fā)的請(qǐng)求同時(shí)更改了狀態(tài)。一般都使用逆操作的方式完成補(bǔ)償。

補(bǔ)償過(guò)程不需要嚴(yán)格按照與業(yè)務(wù)發(fā)生的相反順序執(zhí)行,可以依據(jù)工作服務(wù)的重用程度優(yōu)先執(zhí)行,甚至是可以并發(fā)的執(zhí)行。

有些服務(wù)的補(bǔ)償過(guò)程是有依賴關(guān)系的,被依賴服務(wù)的補(bǔ)償操作沒(méi)有成功就要及時(shí)終止補(bǔ)償過(guò)程。

如果在一個(gè)業(yè)務(wù)中包含的工作服務(wù)不是都提供了補(bǔ)償操作,那我們編排服務(wù)時(shí)應(yīng)該把提供補(bǔ)償操作的服務(wù)放在前面,這樣當(dāng)后面的工作服務(wù)錯(cuò)誤時(shí)還有機(jī)會(huì)補(bǔ)償。

設(shè)計(jì)工作服務(wù)的補(bǔ)償接口時(shí)應(yīng)該以協(xié)調(diào)服務(wù)請(qǐng)求的業(yè)務(wù)要素作為條件,不要以工作服務(wù)的應(yīng)答要素作為條件。因?yàn)檫€存在超時(shí)需要補(bǔ)償?shù)那闆r,這時(shí)補(bǔ)償框架就沒(méi)法提供補(bǔ)償需要的業(yè)務(wù)要素。

TCC模式(Try-Confirm-Cancel)

一個(gè)完整的 TCC 業(yè)務(wù)由一個(gè)主業(yè)務(wù)服務(wù)和若干個(gè)從業(yè)務(wù)服務(wù)組成,主業(yè)務(wù)服務(wù)發(fā)起并完成整個(gè)業(yè)務(wù)活動(dòng),TCC 模式要求從服務(wù)提供三個(gè)接口:Try、Confirm、Cancel。

TCC模式(Try-Confirm-Cancel)

1. Try

完成所有業(yè)務(wù)檢查

預(yù)留必須業(yè)務(wù)資源

2. Confirm

真正執(zhí)行業(yè)務(wù)

不作任何業(yè)務(wù)檢查

只使用 Try 階段預(yù)留的業(yè)務(wù)資源

Confirm 操作滿足冪等性

3. Cancel:

釋放 Try 階段預(yù)留的業(yè)務(wù)資源

Cancel 操作滿足冪等性

整個(gè) TCC 業(yè)務(wù)分成兩個(gè)階段完成。

Cancel

***階段:主業(yè)務(wù)服務(wù)分別調(diào)用所有從業(yè)務(wù)的 try 操作,并在活動(dòng)管理器中登記所有從業(yè)務(wù)服務(wù)。當(dāng)所有從業(yè)務(wù)服務(wù)的 try 操作都調(diào)用成功或者某個(gè)從業(yè)務(wù)服務(wù)的 try 操作失敗,進(jìn)入第二階段。

第二階段:活動(dòng)管理器根據(jù)***階段的執(zhí)行結(jié)果來(lái)執(zhí)行 confirm 或 cancel 操作。

如果***階段所有 try 操作都成功,則活動(dòng)管理器調(diào)用所有從業(yè)務(wù)活動(dòng)的 confirm操作。否則調(diào)用所有從業(yè)務(wù)服務(wù)的 cancel 操作。

需要注意的是第二階段 confirm 或 cancel 操作本身也是滿足最終一致性的過(guò)程,在調(diào)用 confirm 或 cancel 的時(shí)候也可能因?yàn)槟撤N原因(比如網(wǎng)絡(luò))導(dǎo)致調(diào)用失敗,所以需要活動(dòng)管理支持重試的能力,同時(shí)這也就要求 confirm 和 cancel 操作具有冪等性。

在補(bǔ)償模式中一個(gè)比較明顯的缺陷是,沒(méi)有隔離性。從***個(gè)工作服務(wù)步驟開(kāi)始一直到所有工作服務(wù)完成(或者補(bǔ)償過(guò)程完成),不一致是對(duì)其他服務(wù)可見(jiàn)的。另外最終一致性的保證還充分的依賴了協(xié)調(diào)服務(wù)的健壯性,如果協(xié)調(diào)服務(wù)異常,就沒(méi)法達(dá)到一致性。

TCC模式在一定程度上彌補(bǔ)了上述的缺陷,在TCC模式中直到明確的confirm動(dòng)作,所有的業(yè)務(wù)操作都是隔離的(由業(yè)務(wù)層面保證)。另外工作服務(wù)可以通過(guò)指定 try 操作的超時(shí)時(shí)間,主動(dòng)的 cancel 預(yù)留的業(yè)務(wù)資源,從而實(shí)現(xiàn)自治的微服務(wù)。

TCC模式和補(bǔ)償模式一樣需要需要有協(xié)調(diào)服務(wù)和工作服務(wù),協(xié)調(diào)服務(wù)也可以作為通用服務(wù)一般實(shí)現(xiàn)為框架。與補(bǔ)償模式不同的是 TCC 服務(wù)框架不需要記錄詳細(xì)的業(yè)務(wù)流水,完成 confirm 和 cancel 操作的業(yè)務(wù)要素由業(yè)務(wù)服務(wù)提供。

TCC模式和補(bǔ)償模式

在第4步確認(rèn)預(yù)訂之前,訂單只是pending狀態(tài),只有等到明確的confirm之后訂單才生效。

pending狀態(tài)

如果3個(gè)服務(wù)中某個(gè)服務(wù)try操作失敗,那么可以向TCC服務(wù)框架提交cancel,或者什么也不做由工作服務(wù)自己超時(shí)處理。

向TCC服務(wù)框架提交cancel

TCC 模式也不能***保證一致性,如果業(yè)務(wù)服務(wù)向 TCC 服務(wù)框架提交 confirm后,TCC 服務(wù)框架向某個(gè)工作服務(wù)提交 confirm 失敗(比如網(wǎng)絡(luò)故障),那么就會(huì)出現(xiàn)不一致,一般稱為 heuristic exception。

需要說(shuō)明的是為保證業(yè)務(wù)成功率,業(yè)務(wù)服務(wù)向 TCC 服務(wù)框架提交 confirm 以及TCC 服務(wù)框架向工作服務(wù)提交 confirm/cancel 時(shí)都要支持重試,這也就要confirm/cancel 的實(shí)現(xiàn)必須具有冪等性。如果業(yè)務(wù)服務(wù)向 TCC 服務(wù)框架提交confirm/cancel 失敗,不會(huì)導(dǎo)致不一致,因?yàn)榉?wù)***都會(huì)超時(shí)而取消。

另外 heuristic exception 是不可杜絕的,但是可以通過(guò)設(shè)置合適的超時(shí)時(shí)間,以及重試頻率和監(jiān)控措施使得出現(xiàn)這個(gè)異常的可能性降低到很小。如果出現(xiàn)了heuristic exception 是可以通過(guò)人工的手段補(bǔ)救的。

對(duì)賬是***的***防線

如果有些業(yè)務(wù)由于瞬時(shí)的網(wǎng)絡(luò)故障或調(diào)用超時(shí)等問(wèn)題,通過(guò)上文所講的 3 種模式一般都能得到很好的解決。但是在當(dāng)今云計(jì)算環(huán)境下,很多服務(wù)是依賴于外部系統(tǒng)的可用性情況,在一些重要的業(yè)務(wù)場(chǎng)景下還需要周期性的對(duì)賬來(lái)保證真實(shí)的一致性。比如支付系統(tǒng)和銀行之間每天日終是都會(huì)有對(duì)賬過(guò)程。

對(duì)賬是***的***防線

責(zé)任編輯:趙寧寧 來(lái)源: 36大數(shù)據(jù)
相關(guān)推薦

2021-09-28 09:43:11

微服務(wù)架構(gòu)技術(shù)

2021-06-08 12:46:27

分布式阿里TCC

2024-05-17 13:48:19

2023-09-12 22:58:51

分布式架構(gòu)微服務(wù)

2021-11-05 07:18:15

分布式事務(wù)業(yè)務(wù)

2023-01-20 12:08:56

AIPythonTensorFlow

2020-12-14 14:24:07

CAP分布式數(shù)據(jù)一致性

2025-04-18 12:08:19

2012-06-13 09:23:46

虛擬化

2023-12-14 08:01:47

環(huán)境復(fù)制微服務(wù)

2019-10-10 09:16:34

Zookeeper架構(gòu)分布式

2022-05-23 10:26:26

數(shù)據(jù)庫(kù)分布式

2023-05-29 14:07:00

Zuul網(wǎng)關(guān)系統(tǒng)

2015-02-03 09:36:45

微服務(wù)2015元年

2023-12-29 08:14:41

BASE事務(wù)ServiceB

2022-10-26 17:28:41

分布式事務(wù)seata

2017-09-19 09:36:24

微服務(wù)架構(gòu)分布式

2021-03-17 10:51:16

架構(gòu)運(yùn)維技術(shù)

2022-06-27 08:21:05

Seata分布式事務(wù)微服務(wù)

2018-03-02 16:11:29

Spring Clou分布式服務(wù)跟蹤
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 91精品一区二区三区久久久久久 | 天堂久久网 | 日韩中文在线观看 | 日日夜夜精品免费视频 | 国产九一精品 | 日韩视频成人 | 久久精品国产99国产精品 | 久久久免费电影 | 亚洲欧美日韩系列 | 天堂在线网 | 四虎影视一区二区 | 国产精品日日夜夜 | 久久男人| 日韩中文字幕 | 九久久 | 91欧美| 欧美黄页 | 日韩精品在线一区 | 91在线第一页 | 日韩电影一区 | 欧美二三区 | 亚洲精品成人免费 | 日本国产高清 | 久久免费精品 | 97精品国产97久久久久久免费 | 91网视频 | 久久久久无码国产精品一区 | 91精品中文字幕一区二区三区 | 国产夜恋视频在线观看 | 玖玖国产 | 新超碰97| 99久久久无码国产精品 | 午夜视频网站 | 欧美国产一区二区 | 黄色片av | www.午夜| 国产伦精品一区二区 | 国内精品久久影院 | 国产91九色 | 欧美日韩电影一区二区 | 91欧美激情一区二区三区成人 |