微服務:事務管理

ccbdbc78d1edb2276fad85b3294b8571.jpeg

幾乎所有的信息管理系統都會涉及到事務,事務的目的是為了保證數據的一致性,這里說的一致性是數據庫狀態的一致性。

說到數據庫狀態的一致性,相信大家都會想到 ACID :

  • 原子性(Atomic):在一個事件的多個數據庫操作中,要么同時成功,要么同時失敗,例如:轉賬業務;

  • 隔離性(Isolation):不同的業務之間處理數據相互獨立,互不影響;

  • 持久性(Durability):正常提交的數據能夠被持久化,不丟失數據,比如 mysql 天然就能持久化,redis 、 rabbitmq 也能通過設置進行持久化;

  • 一致性(Consistency):最終的數據正確,所以說是通過 AID 這些手段來保證了 C 。

在單體架構中,通常是一套程序對應一個數據庫,事務基于數據庫本身的能力,如果你在 .NET Core 中使用 dapper 或 sqlsugar ,可以很容易進行事務的處理,可以參考下面文檔:

https://dapper-tutorial.net/transaction?

https://www.donet5.com/Home/Doc?typeId=1183

但是,在微服務架構,分布式的場景中,事務的處理就會變得復雜,會存在多個節點,多個節點的同步、可用性等都是需要考慮的問題,在分布式中有一個著名的 CAP 理論:

  • C:數據一致性(Consisitency):分布式中存在多個節點,對某個指定的客戶端來說,從任一節點讀取的數據保證獲取到的是最新寫入的數據;

  • A:可用性(Acailability),非故障節點在合理的時間內返回合理的響應(不是錯誤和超時的響應);

  • P:分區容錯性(Partition Tolerance),節點之間的數據傳遞是基于網絡的,由于網絡本身不是 100% 可靠,極端情況下會出現網絡不可用的情況,進而將網絡兩端的節點分隔開來,這就是所謂的「網絡分區」現象。在出現網絡分區時,兩部分的數據是不一致的,如果要保證數據的一致性,就必須要讓沒有及時同步數據的節點變為不可用,這就犧牲了可用性,否則就會犧牲一致性,所以在 P 一定存在的情況下,需要在 C 和 A 中間做取舍。

我們在 CAP、ACID 中討論的一致性稱為「強一致性」(Strong Consistency),而把犧牲了 C 的 AP 系統,但又要保證最終的結果是一致的,稱為「弱一致性」,也叫最終一致性。最終一致性的概念由 eBay 的系統架構師丹 · 普利切特(Dan Pritchett)在 2008 年發表于 ACM 的論文「Base: An Acid Alternative」中提出的。

本文主要說下保證一致性的幾種方式:TCC、SAGA 和消息隊列。

TCC

TCC 是 Try-Confirm-Cancel 的縮寫,表示將整個過程分為了三個階段:

  • Try:一個請求涉及到多個服務,多個服務會同時進行 Try,這個階段為嘗試執行階段,在這個階段中會進行數據的校驗、檢查,保障一致性,并準備資源,都成功會進入到 Confirm 階段;

  • Confirm:確認執行階段,不進行任何業務檢查,多個服務的 Try 都執行成功了,多個服務都進入到 Confirm 階段,在這個階段直接使用 Try 階段準備的資源來完成業務處理。注意,Confirm 階段可能會重復執行,因此需要滿足冪等性。

  • Cancel:如果在 Try 階段有一個服務沒有成功,那么所有的服務都進入到 Cancel 階段,在該階段,釋放 Try 階段預留的業務資源。注意,Cancel 階段也可能會重復執行,因此也需要滿足冪等性。

在 .NET Core 中可以參考:

https://github.com/simpleway2016/JMS

在 Java 中可以使用 seata:

https://github.com/seata/seata https://seata.io/zh-cn/

因為在 TCC 中的第一步 Try 需要預留資源,進行檢查和校驗,但在某些場景下,資源不是我們所能控制的,比如支付中,余額是銀行管理的,我們通常沒有權限。所以這時就不太適合 TCC ,可以考慮用 SAGA 來代替 TCC。

SAGA

SAGA 起源于 1987 年普林斯頓大學的赫克托 · 加西亞 · 莫利納(Hector Garcia Molina)和肯尼斯 · 麥克米倫(Kenneth Salem)在 ACM 發表的一篇論文《SAGAS》。

SAGA 和 TCC 最大的區別是基于數據補償機制來代替回滾。一個 SAGA 表示處理多個服務中數據的一系列操作,由一連串的本地事務組成,每個獨立的本地事務中還是能夠使用 ACID 。

SATA 由兩部分組成:

  • 將一個大的事務拆分成的若干個小的事務,比如一個大的事務 T ,拆分成 T1、T2、T3;

  • 每一個子事務有對應的補償動作,例如對應上面的 T1、T2、T3 有 C1、C2、C3 的補償動作。

在 ACID 中如果出現異常,可以很容易進行回滾,但 SAGA 沒辦法自己回滾,必須依賴補償動作來進行回滾。

如果 T1、T2、T3 都提交成功了,整個事務 T 就提交成功,如果執行 T2 時出現異常,這時有兩種方式進行處理:

正向(不斷重試):不斷對 T2 進行重試操作,直到成功(不排除人工干預),等 T2 重試成功后,繼續執行后面的 T3;

反向(補償):T2 出現異常時,執行對應的補償 C2,C2 必須執行成功(不排除人工),然后執行 T1 對應的補償動作 C1 。

在上面提到的 seata 中也同樣可以支持 SAGA 模式。

除了 seata ,還有一個用 go 語言寫的 DTM 分布式事務框架也不錯:

https://dtm.pub/ https://github.com/dtm-labs/dtm

重要的是,DTM 支持 C# 客戶端:

https://github.com/dtm-labs/dtmcli-csharp

消息隊列

消息隊列相信大家都不陌生,我們零代碼產品中調用外部接口的組件,會被用在一些復雜的業務邏輯編排中,對外部接口的調用就是使用消息隊列,RabbitMQ 的延時隊列加上死信隊列可以來進行重試的操作,來保證數據的最終一致。

還有另一種方式就是使用事務消息表,比如有這樣一個場景,在系統列表中刪除一條流程數據,這時需要做:

1、列表服務中對數據進行刪除;

2、文件服務對這條數據相關的附件進行刪除;

3、流程服務對該業務數據的所有流程信息進行刪除。

具體的步驟如下:

1、列表服務刪除數據成功后,在數據庫中創建一張事務消息表,該表中記錄事務 ID、數據刪除成功的狀態、業務數據 ID、附件待刪除的狀態、流程信息待刪除的狀態等;

2、列表服務刪除數據成功后,發送消息分別進行附件刪除處理和流程信息刪除處理;

3、消息被正確處理后,修改事務消息表的狀態;

4、創建一個單獨的消息服務程序,輪詢掃描事務消息表,如果發現狀態沒有變成已完成,就重新發送一個新的消息,這樣附件刪除和流程信息刪除就會進行多次執行,這也要求這些操作必須是冪等的。

RabbitMQ 本身不支持分布式事務,不過有一些消息中間件是支持的,例如:RocketMQ,原生就支持分布式事務操作,可以更方便進行事務處理。

本文是一些理論的梳理,要想更徹底地掌握,可以選擇一個框架,找幾個場景,寫寫代碼演練一下。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/283955.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/283955.shtml
英文地址,請注明出處:http://en.pswp.cn/news/283955.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

js - flex布局測試案例:完美居中

<span>I love flex layout!</span><style>body{display:flex;justify-content:center;align-items:center;font-size:3em;color:#00ffff;}</style>![enter image description here][1]<p>與自己為敵&#xff0c;</p><p>與自己為友&a…

操作數據庫(對戰小游戲)

創建數據庫 1 create database duizhan2 go3 use duizhan4 go5 create table duizhan6 (7 Code varchar(20) not null primary key,8 Name varchar(20) not null,9 Sex varchar(20) not null, 10 Blood int, 11 Attack int, 12 Defence int, 13 Mingzhong…

8-Python3從入門到實戰—基礎之數據類型(集合-Sets)

Python從入門到實戰系列——目錄 集合的定義 集合&#xff08;set&#xff09;和字典類似&#xff0c;也是一組key的集合&#xff0c;但不存儲value&#xff1b;由于key不能重復&#xff0c;所以&#xff0c;在set中&#xff0c;沒有重復的key。創建一個set&#xff0c;需要提供…

Redis的那些事:一文入門Redis的基礎操作

Redis是什么Redis&#xff0c;全稱是Remote Dictionary Service,翻譯過來就是&#xff0c;遠程字典服務。redis屬于nosql非關系型數據庫。Nosql常見的數據關系&#xff0c;基本上是以key-value鍵值對形式存在的。Key-value: 就像翻閱中文字典或者單詞字典&#xff0c;通過指定的…

10種提問型爆文標題句式 直接套用

如果你用1天的時間來寫篇好文章&#xff0c;那你花掉半天時間想一個好標題都不過分&#xff01; 你是不是覺得我有點言過其實了&#xff1f;沒關系&#xff0c;先來問你2個問題&#xff1a; 1、花了很長時間&#xff0c;寫了一篇很牛的賣貨推文&#xff0c;定稿后&#xff0c…

同域和不同域長啥樣

相同域http://www.jiangdou.com/http://www.jiangdou.com/maidou 不同域http://www.jiangdou.comhttp://bbs.jiangdou.comhttps://www.jiangdou.comhttp://www.jiangdou.com:8080轉載于:https://www.cnblogs.com/MaiJiangDou/p/6689133.html

2016 China Joy搶先看,文末有彩蛋!

這里只有你想不到的&#xff0c;沒有你看不到的。 2016 China Joy開幕在即&#xff0c;天氣成了最折磨各種媒體、展商和觀眾的小妖精&#xff0c;一會艷陽天&#xff0c;一會大暴雨&#xff0c;軒軒現在是這樣的&#xff01; 七月底的魔都&#xff0c;熱的那叫一個銷魂&#x…

JdbcTemplate+PageImpl實現多表分頁查詢

一、基礎實體  MappedSuperclass public abstract class AbsIdEntity implements Serializable {private static final long serialVersionUID 7988377299341530426L;public final static int IS_DELETE_YES 1;// 標記刪除public final static int IS_DELETE_NO 0;// 未刪除…

消息隊列選型手冊

前言 消息隊列中間件重要嗎&#xff1f;面試必問問題之一&#xff0c;你說重不重要。我有時會問同事&#xff0c;為啥你用 RabbitMQ&#xff0c;不用 Kafka&#xff0c;或者 RocketMQ 呢&#xff1f; 他給我的回答&#xff1a;“因為公司用的就是這個&#xff0c;大家都這么用…

Jenkins 持續集成國產嵌入式操作系統 RT-Thread 的CI

我們直接在Jenkins的鏡像基礎上進行集成RT-Thread 的編譯環境&#xff0c; 這樣直接使用Shell 命令 最直接了當&#xff0c; 通過 第三方docker等插件&#xff0c; 嘗試了計重方案&#xff0c; 沒有找到理想中的感覺&#xff0c; 如果其他人有想法可以告知一二。 我們有現成的鏡…

codevs原創抄襲題 5960 信使

題目描述 Description?戰爭時期&#xff0c;前線有n個哨所&#xff0c;每個哨所可能會與其他若干個哨所之間有通信聯系。信使負責在哨所之間傳遞信息&#xff0c;當然&#xff0c;這是要花費一定時間的&#xff08;以天為單位&#xff09;。指揮部設在第一個哨所。當指揮部下達…

VC解析XML--使用CMarkup類解析XML

經過今天嘗試MFC解析XML串&#xff0c;也算有了不少收獲&#xff0c;總結一下。 我是使用的CMarkup類對XML進行操作。 CMarkup好象都是先從一個xml文件里面把內容讀出來&#xff0c;再進行解析&#xff0c;搞得我恨不得要把我的CString寫到xml文件里面…

MongoDB精華總結

概述 MongoDB是屬于文檔型的NoSQL數據庫&#xff0c;也就是文檔數據庫。文檔數據庫區別于傳統的其它數據庫&#xff0c;它是用來管理文檔。在傳統的數據庫中&#xff0c;信息被分割成離散的數據段&#xff0c;而在文檔數據庫中&#xff0c;文檔是處理信息的基本單位&#xff0c…

認清性能問題

本文翻譯自 Thinking Clearly About Performance 這是我三年前讀到的一篇關于性能問題的好文&#xff0c;讀完后還覺不過癮&#xff0c;怕理解的不夠遂又翻譯了一遍&#xff0c;這也是當年我的第一次翻譯。 這幾年來每次碰到性能問題&#xff0c;我都會想起這篇文章&#xff0c…

字節也開始縮招了...

閱讀本文大概需要6分鐘。最近和一個字節技術總監聊天&#xff0c;得知他們公司居然也開始縮招了。這真讓人感到意外&#xff0c;畢竟頭條這些年是以極速擴張而聞名。搜了搜新聞還真是&#xff0c;這也意味著互聯網行業最后一個堅挺的大戶也在開源節流了。最近互聯網行業的情況真…

實現打字效果

摘自一個表白網站的效果。 方法&#xff1a; substr() 可在字符串中抽取從 第一個參數表示從指定的下標&#xff0c;第二個參數表示抽取指定數目的字符。 indexOf() 方法可返回某個指定的字符串值在字符串中首次出現的位置&#xff0c;兩個參數&#xff0c;第一位指定的字符串&…

php優化-》常用到的部分優化

1.循環內部盡可能不要聲明變量&#xff1b; 2.在可以用PHP內部字符串操作函數的情況下&#xff0c;盡量不要用正則表達式&#xff1b; 3.foreach效率更高&#xff0c;盡量用foreach代替while和for循環&#xff1b; 4.用單引號替代雙引號引用字符串&#xff1b; 5.盡量的少進行文…

簡述:分布式CAP理論和BASE理論

目錄 一、什么是CAP&#xff1f; Consistency (一致性)&#xff1a; Availability (可用性): Partition Tolerance (分區容錯性): 二、取舍策略 三、Base理論 1、基本可用 2、軟狀態 3、最終一致性 四、常見產品 Ereka Zookeeper 五、總結 一、什么是CAP&#xf…

WinForm(四)一種實現登錄的方式

首先聲明&#xff0c;這只是一種登錄方式&#xff0c;并不是最好的方式&#xff0c;用這個例子為了說明登錄窗體和Application的關系。在登錄前&#xff0c;定義了用戶實體&#xff0c;然后是一個通用的類&#xff0c;存放進程中當前登錄的用戶&#xff0c;所以CurrentUser是靜…

Java多線程4:synchronized鎖機制

臟讀 一個常見的概念。在多線程中&#xff0c;難免會出現在多個線程中對同一個對象的實例變量進行并發訪問的情況&#xff0c;如果不做正確的同步處理&#xff0c;那么產生的后果就是"臟讀"&#xff0c;也就是取到的數據其實是被更改過的。 按照正常來看應該打印&quo…