溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何使用Seata Saga設(shè)計(jì)更有彈性的金融應(yīng)用

發(fā)布時(shí)間:2021-10-09 11:50:56 來源:億速云 閱讀:134 作者:柒染 欄目:大數(shù)據(jù)

如何使用Seata Saga設(shè)計(jì)更有彈性的金融應(yīng)用,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

Seata 意為:Simple Extensible Autonomous Transaction Architecture,是一套一站式分布式事務(wù)解決方案,提供了 AT、TCC、Saga 和 XA 事務(wù)模式,下面一起來了解Seata中的 Saga 模式。

  金融分布式應(yīng)用開發(fā)的痛點(diǎn)

分布式系統(tǒng)有一個(gè)比較明顯的問題就是,一個(gè)業(yè)務(wù)流程需要組合一組服務(wù)。這樣的事情在微服務(wù)下就更為明顯了,因?yàn)檫@需要業(yè)務(wù)上的一致性的保證。也就是說,如果一個(gè)步驟失敗了,那么要么回滾到以前的服務(wù)調(diào)用,要么不斷重試保證所有的步驟都成功。

而在金融領(lǐng)域微服務(wù)架構(gòu)下的業(yè)務(wù)流程往往會(huì)更復(fù)雜,流程很長(zhǎng),比如一個(gè)互聯(lián)網(wǎng)微貸業(yè)務(wù)流程調(diào)十幾個(gè)服務(wù)很正常,再加上異常處理的流程那就更復(fù)雜了,做過金融業(yè)務(wù)開發(fā)的同學(xué)會(huì)很有體感。

所以在金融分布式應(yīng)用開發(fā)過程中我們面臨一些痛點(diǎn):

  • 業(yè)務(wù)一致性難以保障

我們接觸到的大多數(shù)業(yè)務(wù)(比如在渠道層、產(chǎn)品層、集成層的系統(tǒng)),為了保障業(yè)務(wù)最終一致性,往往會(huì)采用“補(bǔ)償”的方式來做,如果沒有一個(gè)協(xié)調(diào)器來支持,開發(fā)難度是比較大的,每一步都要在 catch 里去處理前面所有的“回滾”操作,這將會(huì)形成“箭頭形”的代碼,可讀性及維護(hù)性差。或者重試異常的操作,如果重試不成功可能要轉(zhuǎn)異步重試,甚至最后轉(zhuǎn)人工處理。這些都給開發(fā)人員帶來極大的負(fù)擔(dān),開發(fā)效率低,且容易出錯(cuò)。

  • 業(yè)務(wù)狀態(tài)難以管理

業(yè)務(wù)實(shí)體很多、實(shí)體的狀態(tài)也很多,往往做完一個(gè)業(yè)務(wù)活動(dòng)后就將實(shí)體的狀態(tài)更新到了數(shù)據(jù)庫里,沒有一個(gè)狀態(tài)機(jī)來管理整個(gè)狀態(tài)的變遷過程,不直觀,容易出錯(cuò),造成業(yè)務(wù)進(jìn)入一個(gè)不正確的狀態(tài)。

  • 冪等性難以保障

服務(wù)的冪等性是分布式環(huán)境下的基本要求,為了保證服務(wù)的冪等性往往需要服務(wù)開發(fā)者逐個(gè)去設(shè)計(jì),有用數(shù)據(jù)庫唯一鍵實(shí)現(xiàn)的,有用分布式緩存實(shí)現(xiàn)的,沒有一個(gè)統(tǒng)一的方案,開發(fā)人員負(fù)擔(dān)大,也容易遺漏,從而造成資損。

  • 業(yè)務(wù)監(jiān)控運(yùn)維難,缺乏統(tǒng)一的差錯(cuò)守護(hù)能力

業(yè)務(wù)的執(zhí)行情況監(jiān)控一般通過打印日志,再基于日志監(jiān)控平臺(tái)查看,大多數(shù)情況是沒有問題的,但是如果業(yè)務(wù)出錯(cuò),這些監(jiān)控缺乏當(dāng)時(shí)的業(yè)務(wù)上下文,對(duì)排查問題不友好,往往需要再去數(shù)據(jù)庫里查。同時(shí)日志的打印也依賴于開發(fā),容易遺漏。對(duì)于補(bǔ)償事務(wù)往往需要有“差錯(cuò)守護(hù)觸發(fā)補(bǔ)償”、“工人觸發(fā)補(bǔ)償”操作,沒有統(tǒng)一的差錯(cuò)守護(hù)和處理規(guī)范,這些都要開發(fā)者逐個(gè)開發(fā),負(fù)擔(dān)沉重。

理論基礎(chǔ)

一些場(chǎng)景下,我們對(duì)數(shù)據(jù)有強(qiáng)一致性的需求時(shí),會(huì)采用在業(yè)務(wù)層上需要使用“兩階段提交”這樣的分布式事務(wù)方案。而在另外一些場(chǎng)景下,我們并不需要這么強(qiáng)的一致性,那就只需要保證最終一致性就可以了。

例如螞蟻金服目前在金融核心系統(tǒng)使用的就是 TCC 模式,金融核心系統(tǒng)的特點(diǎn)是一致性要求高(業(yè)務(wù)上的隔離性)、短流程、并發(fā)高。

而在很多金融核心以上的業(yè)務(wù)(比如在渠道層、產(chǎn)品層、集成層的系統(tǒng)),這些系統(tǒng)的特點(diǎn)是最終一致即可、流程多、流程長(zhǎng)、還可能要調(diào)用其它公司的服務(wù)(如金融網(wǎng)絡(luò))。這是如果每個(gè)服務(wù)都開發(fā) Try、Confirm、Cancel 三個(gè)方法成本高。如果事務(wù)中有其它公司的服務(wù),也無法要求其它公司的服務(wù)也遵循 TCC 這種開發(fā)模式。同時(shí)流程長(zhǎng),事務(wù)邊界太長(zhǎng)會(huì)影響性能。

對(duì)于事務(wù)我們都知道 ACID,也很熟悉 CAP 理論最多只能滿足其中兩個(gè),所以,為了提高性能,出現(xiàn)了 ACID 的一個(gè)變種 BASE。ACID 強(qiáng)調(diào)的是一致性(CAP 中的 C),而 BASE 強(qiáng)調(diào)的是可用性(CAP 中的 A)。我們知道,在很多情況下,我們是無法做到強(qiáng)一致性的 ACID 的。特別是我們需要跨多個(gè)系統(tǒng)的時(shí)候,而且這些系統(tǒng)還不是由一個(gè)公司所提供的。BASE 的系統(tǒng)傾向于設(shè)計(jì)出更加有彈力的系統(tǒng),在短時(shí)間內(nèi),就算是有數(shù)據(jù)不同步的風(fēng)險(xiǎn),我們也應(yīng)該允許新的交易可以發(fā)生,而后面我們?cè)跇I(yè)務(wù)上將可能出現(xiàn)問題的事務(wù)通過補(bǔ)償?shù)姆绞教幚淼?,以保證最終的一致性。

所以我們?cè)趯?shí)際開發(fā)中會(huì)進(jìn)行取舍,對(duì)于更多的金融核心以上的業(yè)務(wù)系統(tǒng)可以采用補(bǔ)償事務(wù),補(bǔ)償事務(wù)處理方面在30年前就提出了 Saga 理論,隨著微服務(wù)的發(fā)展,近些年才逐步受到大家的關(guān)注。目前業(yè)界比較也公認(rèn) Saga 是作為長(zhǎng)事務(wù)的解決方案。

https://github.com/aphyr/dist-sagas/blob/master/sagas.pdf

http://microservices.io/patterns/data/saga.html

社區(qū)和業(yè)界的方案

Apache Camel Saga

Camel 是實(shí)現(xiàn) EIP(Enterprise Integration Patterns)企業(yè)集成模式的一款開源產(chǎn)品,它基于事件驅(qū)動(dòng)的架構(gòu),有著良好的性能和吞吐量,它在2.21版本新增加了 Saga EIP。

Saga EIP 提供了一種方式可以通過 camel route 定義一系列有關(guān)聯(lián)關(guān)系的 Action,這些 Action 要么都執(zhí)行成功,要么都回滾,Saga 可以協(xié)調(diào)任何通訊協(xié)議的分布式服務(wù)或本地服務(wù),并達(dá)到全局的最終一致性。Saga 不要求整個(gè)處理在短時(shí)間內(nèi)完成,因?yàn)樗徽加萌魏螖?shù)據(jù)庫鎖,它可以支持需要長(zhǎng)時(shí)間處理的請(qǐng)求,從幾秒到幾天,Camel 的 Saga EIP 是基于 Microprofile 的 LRA(Long Running Action),同樣也是支持協(xié)調(diào)任何通訊協(xié)議任何語言實(shí)現(xiàn)的分布式服務(wù)。

Saga 的實(shí)現(xiàn)不會(huì)對(duì)數(shù)據(jù)進(jìn)行加鎖,而是在給操作定義它的“補(bǔ)償操作”,當(dāng)正常流程執(zhí)行出錯(cuò)的時(shí)候觸發(fā)那些已經(jīng)執(zhí)行過的操作的“補(bǔ)償操作”,將流程回滾掉。“補(bǔ)償操作”可以在 Camel route 上用 Java 或 XML DSL(Definition Specific Language)來定義。

下面是一個(gè) Java DSL 示例:

如何使用Seata Saga設(shè)計(jì)更有彈性的金融應(yīng)用cdn.nlark.com/yuque/0/2019/png/226702/1572853428625-e17b7e50-9353-40ee-a1e5-c276618a9214.png">

XML DSL 示例:

如何使用Seata Saga設(shè)計(jì)更有彈性的金融應(yīng)用

Eventuate Tram Saga

Eventuate Tram Saga 框架是使用 JDBC / JPA 的 Java 微服務(wù)的一個(gè) Saga 框架。它也和 Camel Saga 一樣采用了 Java DSL 來定義補(bǔ)償操作:

如何使用Seata Saga設(shè)計(jì)更有彈性的金融應(yīng)用

Apache ServiceComb Saga

ServiceComb Saga 也是一個(gè)微服務(wù)應(yīng)用的數(shù)據(jù)最終一致性解決方案。相對(duì)于 TCC 而言,在 try 階段,Saga 會(huì)直接提交事務(wù),后續(xù) rollback 階段則通過反向的補(bǔ)償操作來完成。與前面兩種不同是它是采用 Java 注解+攔截器的方式來進(jìn)行“補(bǔ)償”服務(wù)的定義。

架構(gòu)

Saga 是由 alpha 和 **omega **組成,其中:

  • alpha 充當(dāng)協(xié)調(diào)者的角色,主要負(fù)責(zé)對(duì)事務(wù)進(jìn)行管理和協(xié)調(diào);

  • omega 是微服務(wù)中內(nèi)嵌的一個(gè) agent,負(fù)責(zé)對(duì)網(wǎng)絡(luò)請(qǐng)求進(jìn)行攔截并向 alpha 上報(bào)事務(wù)事件;

下圖展示了 alpha,omega 以及微服務(wù)三者的關(guān)系: 如何使用Seata Saga設(shè)計(jì)更有彈性的金融應(yīng)用

使用示例

如何使用Seata Saga設(shè)計(jì)更有彈性的金融應(yīng)用

螞蟻金服的實(shí)踐

螞蟻金服內(nèi)部大規(guī)模在使用 TCC 模式分布式事務(wù),主要用于金融核心等對(duì)一致性要求高、性能要求高的場(chǎng)景。在更上層的業(yè)務(wù)系統(tǒng)因?yàn)榱鞒潭嗔鞒涕L(zhǎng),開發(fā) TCC 成本比較高,大都會(huì)權(quán)衡采用 Saga 模式來到達(dá)業(yè)務(wù)最終一致性,由于歷史的原因不同的 BU 有自己的一套“補(bǔ)償”事務(wù)的方案,基本上是兩種:

  • 一種是當(dāng)一個(gè)服務(wù)在失敗時(shí)需要“重試”或“補(bǔ)償”時(shí),在執(zhí)行服務(wù)前在數(shù)據(jù)庫插入一條記錄,記錄狀態(tài),當(dāng)異常時(shí)通過定時(shí)任務(wù)去查詢數(shù)據(jù)庫記錄并進(jìn)行“重試”或“補(bǔ)償”,當(dāng)業(yè)務(wù)流程執(zhí)行成功則刪除記錄;

  • 另一種是設(shè)計(jì)一個(gè)狀態(tài)機(jī)引擎和簡(jiǎn)單的 DSL,編排業(yè)務(wù)流程和記錄業(yè)務(wù)狀態(tài),狀態(tài)機(jī)引擎可以定義“補(bǔ)償服務(wù)”,當(dāng)異常時(shí)由狀態(tài)機(jī)引擎反向調(diào)用“補(bǔ)償服務(wù)”進(jìn)行回滾,同時(shí)還會(huì)有一個(gè)“差錯(cuò)守護(hù)”平臺(tái),監(jiān)控那些執(zhí)行失敗或補(bǔ)償失敗的業(yè)務(wù)流水,并不斷進(jìn)行“補(bǔ)償”或“重試”;

方案對(duì)比

社區(qū)和業(yè)界的解決方案一般是兩種,一種基本狀態(tài)機(jī)或流程引擎通過 DSL 方式編排流程程和補(bǔ)償定義,一種是基于 Java 注解+攔截器實(shí)現(xiàn)補(bǔ)償,那么這兩種方案有什么優(yōu)缺點(diǎn)呢?

方式優(yōu)點(diǎn)缺點(diǎn)
狀態(tài)機(jī)+DSL1.可以用可視化工具來定義業(yè)務(wù)流程,標(biāo)準(zhǔn)化,可讀性高,可實(shí)現(xiàn)服務(wù)編排的功能 2.提高業(yè)務(wù)分析人員與程序開發(fā)人員的溝通效率 3. 業(yè)務(wù)狀態(tài)管理:流程本質(zhì)就是一個(gè)狀態(tài)機(jī),可以很好的反映業(yè)務(wù)狀態(tài)的流轉(zhuǎn) 4.提高異常處理靈活性:可以實(shí)現(xiàn)宕機(jī)恢復(fù)后的“向前重試”或“向后補(bǔ)償” 5.天然可以使用 Actor 模型或 SEDA 架構(gòu)等異步處理引擎來執(zhí)行,提高整體吞吐量1.業(yè)務(wù)流程實(shí)際是由 JAVA 程序與 DSL 配置組成,程序與配置分離,開發(fā)起來比較繁瑣 2.如果是改造現(xiàn)有業(yè)務(wù),對(duì)業(yè)務(wù)侵入性高 3.引擎實(shí)現(xiàn)成本高
攔截器+java 注解1.程序與注解是在一起的,開發(fā)簡(jiǎn)單,學(xué)習(xí)成本低 2.方便接入現(xiàn)有業(yè)務(wù) 3.基于動(dòng)態(tài)代理攔截器,框架實(shí)現(xiàn)成本低1.框架無法提供 Actor 模型或 SEDA 架構(gòu)等異步處理模式來提高系統(tǒng)吞吐量 2.框架無法提供業(yè)務(wù)狀態(tài)管理 3.難以實(shí)現(xiàn)宕機(jī)恢復(fù)后的“向前重試”,因?yàn)闊o法恢復(fù)線程上下文

Seata Saga 的方案

Seata Saga 的簡(jiǎn)介可以看一下《Seata Saga 官網(wǎng)文檔》。

Seata Saga 采用了狀態(tài)機(jī)+DSL 方案來實(shí)現(xiàn),原因有以下幾個(gè):

  • 狀態(tài)機(jī)+DSL 方案在實(shí)際生產(chǎn)中應(yīng)用更廣泛;

  • 可以使用 Actor 模型或 SEDA 架構(gòu)等異步處理引擎來執(zhí)行,提高整體吞吐量;

  • 通常在核心系統(tǒng)以上層的業(yè)務(wù)系統(tǒng)會(huì)伴隨有“服務(wù)編排”的需求,而服務(wù)編排又有事務(wù)最終一致性要求,兩者很難分割開,狀態(tài)機(jī)+DSL 方案可以同時(shí)滿足這兩個(gè)需求;

  • 由于 Saga 模式在理論上是不保證隔離性的,在極端情況下可能由于臟寫無法完成回滾操作,比如舉一個(gè)極端的例子, 分布式事務(wù)內(nèi)先給用戶 A 充值,然后給用戶 B 扣減余額,如果在給A用戶充值成功,在事務(wù)提交以前,A 用戶把線消費(fèi)掉了,如果事務(wù)發(fā)生回滾,這時(shí)則沒有辦法進(jìn)行補(bǔ)償了,有些業(yè)務(wù)場(chǎng)景可以允許讓業(yè)務(wù)最終成功,在回滾不了的情況下可以繼續(xù)重試完成后面的流程,狀態(tài)機(jī)+DSL的方案可以實(shí)現(xiàn)“向前”恢復(fù)上下文繼續(xù)執(zhí)行的能力, 讓業(yè)務(wù)最終執(zhí)行成功,達(dá)到最終一致性的目的。

在不保證隔離性的情況下:業(yè)務(wù)流程設(shè)計(jì)時(shí)要遵循“寧可長(zhǎng)款, 不可短款”的原則,長(zhǎng)款意思是客戶少了線機(jī)構(gòu)多了錢,以機(jī)構(gòu)信譽(yù)可以給客戶退款,反之則是短款,少的線可能追不回來了。所以在業(yè)務(wù)流程設(shè)計(jì)上一定是先扣款。

狀態(tài)定義語言(Seata State Language)

  1. 通過狀態(tài)圖來定義服務(wù)調(diào)用的流程并生成 json 狀態(tài)語言定義文件;

  2. 狀態(tài)圖中一個(gè)節(jié)點(diǎn)可以是調(diào)用一個(gè)服務(wù),節(jié)點(diǎn)可以配置它的補(bǔ)償節(jié)點(diǎn);

  3. 狀態(tài)圖 json 由狀態(tài)機(jī)引擎驅(qū)動(dòng)執(zhí)行,當(dāng)出現(xiàn)異常時(shí)狀態(tài)引擎反向執(zhí)行已成功節(jié)點(diǎn)對(duì)應(yīng)的補(bǔ)償節(jié)點(diǎn)將事務(wù)回滾;

注意: 異常發(fā)生時(shí)是否進(jìn)行補(bǔ)償也可由用戶自定義決定

  1. 可以實(shí)現(xiàn)服務(wù)編排需求,支持單項(xiàng)選擇、并發(fā)、異步、子狀態(tài)機(jī)、參數(shù)轉(zhuǎn)換、參數(shù)映射、服務(wù)執(zhí)行狀態(tài)判斷、異常捕獲等功能;

假設(shè)有一個(gè)業(yè)務(wù)流程要調(diào)兩個(gè)服務(wù),先調(diào)庫存扣減(InventoryService),再調(diào)余額扣減(BalanceService),保證在一個(gè)分布式內(nèi)要么同時(shí)成功,要么同時(shí)回滾。兩個(gè)參與者服務(wù)都有一個(gè) reduce 方法,表示庫存扣減或余額扣減,還有一個(gè) compensateReduce 方法,表示補(bǔ)償扣減操作。以 InventoryService 為例看一下它的接口定義:

如何使用Seata Saga設(shè)計(jì)更有彈性的金融應(yīng)用

這個(gè)業(yè)務(wù)流程對(duì)應(yīng)的狀態(tài)圖:

如何使用Seata Saga設(shè)計(jì)更有彈性的金融應(yīng)用 對(duì)應(yīng)的 JSON:

如何使用Seata Saga設(shè)計(jì)更有彈性的金融應(yīng)用

狀態(tài)語言在一定程度上參考了 AWS Step Functions。

"狀態(tài)機(jī)" 屬性簡(jiǎn)介
  • Name: 表示狀態(tài)機(jī)的名稱,必須唯一;

  • Comment: 狀態(tài)機(jī)的描述;

  • Version: 狀態(tài)機(jī)定義版本;

  • StartState: 啟動(dòng)時(shí)運(yùn)行的第一個(gè)"狀態(tài)";

  • States: 狀態(tài)列表,是一個(gè) map 結(jié)構(gòu),key 是"狀態(tài)"的名稱,在狀態(tài)機(jī)內(nèi)必須唯一;

"狀態(tài)" 屬性簡(jiǎn)介
  • Type:"狀態(tài)" 的類型,比如有:

    • ServiceTask: 執(zhí)行調(diào)用服務(wù)任務(wù);

    • Choice: 單條件選擇路由;

    • CompensationTrigger: 觸發(fā)補(bǔ)償流程;

    • Succeed: 狀態(tài)機(jī)正常結(jié)束;

    • Fail: 狀態(tài)機(jī)異常結(jié)束;

    • SubStateMachine: 調(diào)用子狀態(tài)機(jī);

  • ServiceName: 服務(wù)名稱,通常是服務(wù)的beanId;

  • ServiceMethod: 服務(wù)方法名稱;

  • CompensateState: 該"狀態(tài)"的補(bǔ)償"狀態(tài)";

  • Input: 調(diào)用服務(wù)的輸入?yún)?shù)列表,是一個(gè)數(shù)組,對(duì)應(yīng)于服務(wù)方法的參數(shù)列表, $.表示使用表達(dá)式從狀態(tài)機(jī)上下文中取參數(shù),表達(dá)使用的 SpringEL, 如果是常量直接寫值即可;

  • Output: 將服務(wù)返回的參數(shù)賦值到狀態(tài)機(jī)上下文中,是一個(gè) map 結(jié)構(gòu),key 為放入到狀態(tài)機(jī)上文時(shí)的 key(狀態(tài)機(jī)上下文也是一個(gè) map),value 中 $. 是表示 SpringEL 表達(dá)式,表示從服務(wù)的返回參數(shù)中取值,#root 表示服務(wù)的整個(gè)返回參數(shù);

  • Status: 服務(wù)執(zhí)行狀態(tài)映射,框架定義了三個(gè)狀態(tài),SU 成功、FA 失敗、UN 未知,我們需要把服務(wù)執(zhí)行的狀態(tài)映射成這三個(gè)狀態(tài),幫助框架判斷整個(gè)事務(wù)的一致性,是一個(gè) map 結(jié)構(gòu),key 是條件表達(dá)式,一般是取服務(wù)的返回值或拋出的異常進(jìn)行判斷,默認(rèn)是 SpringEL 表達(dá)式判斷服務(wù)返回參數(shù),帶 $Exception{開頭表示判斷異常類型,value 是當(dāng)這個(gè)條件表達(dá)式成立時(shí)則將服務(wù)執(zhí)行狀態(tài)映射成這個(gè)值;

  • Catch: 捕獲到異常后的路由;

  • Next: 服務(wù)執(zhí)行完成后下一個(gè)執(zhí)行的"狀態(tài)";

  • Choices: Choice 類型的"狀態(tài)"里, 可選的分支列表, 分支中的 Expression 為 SpringEL 表達(dá)式,Next 為當(dāng)表達(dá)式成立時(shí)執(zhí)行的下一個(gè)"狀態(tài)";

  • ErrorCode: Fail 類型"狀態(tài)"的錯(cuò)誤碼;

  • Message: Fail 類型"狀態(tài)"的錯(cuò)誤信息;

更多詳細(xì)的狀態(tài)語言解釋請(qǐng)看《Seata Saga 官網(wǎng)文檔》。

狀態(tài)機(jī)引擎原理

如何使用Seata Saga設(shè)計(jì)更有彈性的金融應(yīng)用

  • 圖中的狀態(tài)圖是先執(zhí)行 stateA, 再執(zhí)行 stataB,然后執(zhí)行 stateC;

  • "狀態(tài)"的執(zhí)行是基于事件驅(qū)動(dòng)的模型,stataA 執(zhí)行完成后,會(huì)產(chǎn)生路由消息放入 EventQueue,事件消費(fèi)端從 EventQueue 取出消息,執(zhí)行 stateB;

  • 在整個(gè)狀態(tài)機(jī)啟動(dòng)時(shí)會(huì)調(diào)用 Seata Server 開啟分布式事務(wù),并生產(chǎn) xid, 然后記錄"狀態(tài)機(jī)實(shí)例"啟動(dòng)事件到本地?cái)?shù)據(jù)庫;

  • 當(dāng)執(zhí)行到一個(gè)"狀態(tài)"時(shí)會(huì)調(diào)用 Seata Server 注冊(cè)分支事務(wù),并生產(chǎn) branchId, 然后記錄"狀態(tài)實(shí)例"開始執(zhí)行事件到本地?cái)?shù)據(jù)庫;

  • 當(dāng)一個(gè)"狀態(tài)"執(zhí)行完成后會(huì)記錄"狀態(tài)實(shí)例"執(zhí)行結(jié)束事件到本地?cái)?shù)據(jù)庫, 然后調(diào)用 Seata Server 上報(bào)分支事務(wù)的狀態(tài);

  • 當(dāng)整個(gè)狀態(tài)機(jī)執(zhí)行完成,會(huì)記錄"狀態(tài)機(jī)實(shí)例"執(zhí)行完成事件到本地?cái)?shù)據(jù)庫, 然后調(diào)用 Seata Server 提交或回滾分布式事務(wù);

狀態(tài)機(jī)引擎設(shè)計(jì)

如何使用Seata Saga設(shè)計(jì)更有彈性的金融應(yīng)用

狀態(tài)機(jī)引擎的設(shè)計(jì)主要分成三層, 上層依賴下層,從下往上分別是:

  • Eventing 層:

    • 實(shí)現(xiàn)事件驅(qū)動(dòng)架構(gòu), 可以壓入事件, 并由消費(fèi)端消費(fèi)事件, 本層不關(guān)心事件是什么消費(fèi)端執(zhí)行什么,由上層實(shí)現(xiàn);

  • ProcessController 層:

    • 由于上層的 Eventing 驅(qū)動(dòng)一個(gè)“空”流程執(zhí)行的執(zhí)行,"state"的行為和路由都未實(shí)現(xiàn),由上層實(shí)現(xiàn);

基于以上兩層理論上可以自定義擴(kuò)展任何"流程"引擎。這兩層的設(shè)計(jì)是參考了內(nèi)部金融網(wǎng)絡(luò)平臺(tái)的設(shè)計(jì)。

  • StateMachineEngine 層:

    • 實(shí)現(xiàn)狀態(tài)機(jī)引擎每種 state 的行為和路由邏輯;

    • 提供 API、狀態(tài)機(jī)語言倉(cāng)庫;

Saga 模式下服務(wù)設(shè)計(jì)的實(shí)踐經(jīng)驗(yàn)

下面是實(shí)踐中總結(jié)的在 Saga 模式下微服務(wù)設(shè)計(jì)的一些經(jīng)驗(yàn),當(dāng)然這是推薦做法,并不是說一定要 100% 遵循,沒有遵循也有“繞過”方案。

好消息:Seata Saga 模式對(duì)微服務(wù)的接口參數(shù)沒有任務(wù)要求,這使得 Saga 模式可用于集成遺留系統(tǒng)或外部機(jī)構(gòu)的服務(wù)。

允許空補(bǔ)償
  • 空補(bǔ)償:原服務(wù)未執(zhí)行,補(bǔ)償服務(wù)執(zhí)行了;

  • 出現(xiàn)原因:

    • 原服務(wù) 超時(shí)(丟包);

    • Saga 事務(wù)觸發(fā) 回滾;

    • 未收到原服務(wù)請(qǐng)求,先收到補(bǔ)償請(qǐng)求;

所以服務(wù)設(shè)計(jì)時(shí)需要允許空補(bǔ)償,即沒有找到要補(bǔ)償?shù)臉I(yè)務(wù)主鍵時(shí)返回補(bǔ)償成功并將原業(yè)務(wù)主鍵記錄下來。

防懸掛控制
  • 懸掛:補(bǔ)償服務(wù) 比 原服務(wù) 先執(zhí)行;

  • 出現(xiàn)原因:

    • 原服務(wù) 超時(shí)(擁堵);

    • Saga 事務(wù)回滾,觸發(fā) 回滾;

    • 擁堵的原服務(wù)到達(dá);

所以要檢查當(dāng)前業(yè)務(wù)主鍵是否已經(jīng)在空補(bǔ)償記錄下來的業(yè)務(wù)主鍵中存在,如果存在則要拒絕服務(wù)的執(zhí)行。

冪等控制
  • 原服務(wù)與補(bǔ)償服務(wù)都需要保證冪等性, 由于網(wǎng)絡(luò)可能超時(shí),可以設(shè)置重試策略,重試發(fā)生時(shí)要通過冪等控制避免業(yè)務(wù)數(shù)據(jù)重復(fù)更新。

很多時(shí)候我們不需要強(qiáng)調(diào)強(qiáng)一性,我們基于 BASE 和 Saga 理論去設(shè)計(jì)更有彈性的系統(tǒng),在分布式架構(gòu)下獲得更好的性能和容錯(cuò)能力。分布式架構(gòu)沒有銀彈,只有適合特定場(chǎng)景的方案,事實(shí)上 Seata Saga 是一個(gè)具備“服務(wù)編排”和“Saga 分布式事務(wù)”能力的產(chǎn)品,總結(jié)下來它的適用場(chǎng)景是:

  • 適用于微服務(wù)架構(gòu)下的“長(zhǎng)事務(wù)”處理;

  • 適用于微服務(wù)架構(gòu)下的“服務(wù)編排”需求;

  • 適用于金融核心系統(tǒng)以上的有大量組合服務(wù)的業(yè)務(wù)系統(tǒng)(比如在渠道層、產(chǎn)品層、集成層的系統(tǒng));

  • 適用于業(yè)務(wù)流程中需要集成遺留系統(tǒng)或外部機(jī)構(gòu)提供的服務(wù)的場(chǎng)景(這些服務(wù)不可變不能對(duì)其提出改造要求)。

看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝您對(duì)億速云的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI