<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          開源的分布式事務(wù)解決方案-Seata

          共 4882字,需瀏覽 10分鐘

           ·

          2020-11-29 05:45

          Seata 是什么?

          (1)Seata 是一款開源的分布式事務(wù)解決方案,致力于在微服務(wù)架構(gòu)下提供高性能和簡單易用的分布式事務(wù)服務(wù)。

          (2)在 Seata 開源之前,Seata 對應(yīng)的內(nèi)部版本在阿里經(jīng)濟體內(nèi)部一直扮演著分布式一致性中間件的角色,幫助經(jīng)濟體平穩(wěn)的度過歷年的雙11,對各BU業(yè)務(wù)進行了有力的支撐。經(jīng)過多年沉淀與積累,商業(yè)化產(chǎn)品先后在阿里云、金融云進行售賣。

          (3)2019.1 為了打造更加完善的技術(shù)生態(tài)和普惠技術(shù)成果,Seata 正式宣布對外開源,未來 Seata 將以社區(qū)共建的形式幫助其技術(shù)更加可靠與完備。

          (4)Seata 將為用戶提供了 AT、TCC、SAGA 和 XA 事務(wù)模式,為用戶打造一站式的分布式解決方案。

          AT 模式

          前提

          • 基于支持本地 ACID 事務(wù)的關(guān)系型數(shù)據(jù)庫。
          • Java 應(yīng)用,通過 JDBC 訪問數(shù)據(jù)庫。

          整體機制

          兩階段提交協(xié)議的演變:

          • 一階段:業(yè)務(wù)數(shù)據(jù)和回滾日志記錄在同一個本地事務(wù)中提交,釋放本地鎖和連接資源。
          • 二階段:
            • 提交異步化,非常快速地完成。
            • 回滾通過一階段的回滾日志進行反向補償。

          寫隔離

          • 一階段本地事務(wù)提交前,需要確保先拿到 全局鎖
          • 拿不到 全局鎖 ,不能提交本地事務(wù)。
          • 全局鎖 的嘗試被限制在一定范圍內(nèi),超出范圍將放棄,并回滾本地事務(wù),釋放本地鎖。

          以一個示例來說明:

          兩個全局事務(wù) tx1 和 tx2,分別對 a 表的 m 字段進行更新操作,m 的初始值 1000。

          tx1 先開始,開啟本地事務(wù),拿到本地鎖,更新操作 m = 1000 - 100 = 900。本地事務(wù)提交前,先拿到該記錄的 全局鎖 ,本地提交釋放本地鎖。tx2 后開始,開啟本地事務(wù),拿到本地鎖,更新操作 m = 900 - 100 = 800。本地事務(wù)提交前,嘗試拿該記錄的 全局鎖 ,tx1 全局提交前,該記錄的全局鎖被 tx1 持有,tx2 需要重試等待 全局鎖

          Write-Isolation: Commit

          tx1 二階段全局提交,釋放 全局鎖 。tx2 拿到 全局鎖 提交本地事務(wù)。

          Write-Isolation: Rollback

          如果 tx1 的二階段全局回滾,則 tx1 需要重新獲取該數(shù)據(jù)的本地鎖,進行反向補償?shù)母虏僮鳎瑢崿F(xiàn)分支的回滾。

          此時,如果 tx2 仍在等待該數(shù)據(jù)的 全局鎖,同時持有本地鎖,則 tx1 的分支回滾會失敗。分支的回滾會一直重試,直到 tx2 的 全局鎖 等鎖超時,放棄 全局鎖 并回滾本地事務(wù)釋放本地鎖,tx1 的分支回滾最終成功。

          因為整個過程 全局鎖 在 tx1 結(jié)束前一直是被 tx1 持有的,所以不會發(fā)生 臟寫 的問題。

          讀隔離

          在數(shù)據(jù)庫本地事務(wù)隔離級別 讀已提交(Read Committed) 或以上的基礎(chǔ)上,Seata(AT 模式)的默認全局隔離級別是 讀未提交(Read Uncommitted)

          如果應(yīng)用在特定場景下,必需要求全局的 讀已提交 ,目前 Seata 的方式是通過 SELECT FOR UPDATE 語句的代理。

          Read Isolation: SELECT FOR UPDATE

          SELECT FOR UPDATE 語句的執(zhí)行會申請 全局鎖 ,如果 全局鎖 被其他事務(wù)持有,則釋放本地鎖(回滾 SELECT FOR UPDATE 語句的本地執(zhí)行)并重試。這個過程中,查詢是被 block 住的,直到 全局鎖 拿到,即讀取的相關(guān)數(shù)據(jù)是 已提交 的,才返回。

          出于總體性能上的考慮,Seata 目前的方案并沒有對所有 SELECT 語句都進行代理,僅針對 FOR UPDATE 的 SELECT 語句。

          工作機制

          以一個示例來說明整個 AT 分支的工作過程。

          業(yè)務(wù)表:product

          FieldTypeKey
          idbigint(20)PRI
          namevarchar(100)
          sincevarchar(100)

          AT 分支事務(wù)的業(yè)務(wù)邏輯:

          update?product?set?name?=?'GTS'?where?name?=?'TXC';

          一階段

          過程:

          1. 解析 SQL:得到 SQL 的類型(UPDATE),表(product),條件(where name = 'TXC')等相關(guān)的信息。
          2. 查詢前鏡像:根據(jù)解析得到的條件信息,生成查詢語句,定位數(shù)據(jù)。
          select?id,?name,?since?from?product?where?name?=?'TXC';

          得到前鏡像:

          idnamesince
          1TXC2014
          1. 執(zhí)行業(yè)務(wù) SQL:更新這條記錄的 name 為 'GTS'。
          2. 查詢后鏡像:根據(jù)前鏡像的結(jié)果,通過 主鍵 定位數(shù)據(jù)。
          select?id,?name,?since?from?product?where?id?=?1;

          得到后鏡像:

          idnamesince
          1GTS2014
          1. 插入回滾日志:把前后鏡像數(shù)據(jù)以及業(yè)務(wù) SQL 相關(guān)的信息組成一條回滾日志記錄,插入到 UNDO_LOG 表中。
          {
          ?"branchId":?641789253,
          ?"undoItems":?[{
          ??"afterImage":?{
          ???"rows":?[{
          ????"fields":?[{
          ?????"name":?"id",
          ?????"type":?4,
          ?????"value":?1
          ????},?{
          ?????"name":?"name",
          ?????"type":?12,
          ?????"value":?"GTS"
          ????},?{
          ?????"name":?"since",
          ?????"type":?12,
          ?????"value":?"2014"
          ????}]
          ???}],
          ???"tableName":?"product"
          ??},
          ??"beforeImage":?{
          ???"rows":?[{
          ????"fields":?[{
          ?????"name":?"id",
          ?????"type":?4,
          ?????"value":?1
          ????},?{
          ?????"name":?"name",
          ?????"type":?12,
          ?????"value":?"TXC"
          ????},?{
          ?????"name":?"since",
          ?????"type":?12,
          ?????"value":?"2014"
          ????}]
          ???}],
          ???"tableName":?"product"
          ??},
          ??"sqlType":?"UPDATE"
          ?}],
          ?"xid":?"xid:xxx"
          }
          1. 提交前,向 TC 注冊分支:申請 product 表中,主鍵值等于 1 的記錄的 全局鎖
          2. 本地事務(wù)提交:業(yè)務(wù)數(shù)據(jù)的更新和前面步驟中生成的 UNDO LOG 一并提交。
          3. 將本地事務(wù)提交的結(jié)果上報給 TC。

          二階段-回滾

          1. 收到 TC 的分支回滾請求,開啟一個本地事務(wù),執(zhí)行如下操作。
          2. 通過 XID 和 Branch ID 查找到相應(yīng)的 UNDO LOG 記錄。
          3. 數(shù)據(jù)校驗:拿 UNDO LOG 中的后鏡與當前數(shù)據(jù)進行比較,如果有不同,說明數(shù)據(jù)被當前全局事務(wù)之外的動作做了修改。這種情況,需要根據(jù)配置策略來做處理,詳細的說明在另外的文檔中介紹。
          4. 根據(jù) UNDO LOG 中的前鏡像和業(yè)務(wù) SQL 的相關(guān)信息生成并執(zhí)行回滾的語句:
          update?product?set?name?=?'TXC'?where?id?=?1;
          1. 提交本地事務(wù)。并把本地事務(wù)的執(zhí)行結(jié)果(即分支事務(wù)回滾的結(jié)果)上報給 TC。

          二階段-提交

          1. 收到 TC 的分支提交請求,把請求放入一個異步任務(wù)的隊列中,馬上返回提交成功的結(jié)果給 TC。
          2. 異步任務(wù)階段的分支提交請求將異步和批量地刪除相應(yīng) UNDO LOG 記錄。

          附錄

          回滾日志表

          UNDO_LOG Table:不同數(shù)據(jù)庫在類型上會略有差別。

          以 MySQL 為例:

          FieldType
          branch_idbigint PK
          xidvarchar(100)
          contextvarchar(128)
          rollback_infolongblob
          log_statustinyint
          log_createddatetime
          log_modifieddatetime
          --?注意此處0.7.0+?增加字段?context
          CREATE?TABLE?`undo_log`?(
          ??`id`?bigint(20)?NOT?NULL?AUTO_INCREMENT,
          ??`branch_id`?bigint(20)?NOT?NULL,
          ??`xid`?varchar(100)?NOT?NULL,
          ??`context`?varchar(128)?NOT?NULL,
          ??`rollback_info`?longblob?NOT?NULL,
          ??`log_status`?int(11)?NOT?NULL,
          ??`log_created`?datetime?NOT?NULL,
          ??`log_modified`?datetime?NOT?NULL,
          ??PRIMARY?KEY?(`id`),
          ??UNIQUE?KEY?`ux_undo_log`?(`xid`,`branch_id`)
          )?ENGINE=InnoDB?AUTO_INCREMENT=1?DEFAULT?CHARSET=utf8;

          TCC 模式

          回顧總覽中的描述:一個分布式的全局事務(wù),整體是 兩階段提交 的模型。全局事務(wù)是由若干分支事務(wù)組成的,分支事務(wù)要滿足 兩階段提交 的模型要求,即需要每個分支事務(wù)都具備自己的:

          • 一階段 prepare 行為
          • 二階段 commit 或 rollback 行為
          Overview of a global transaction

          根據(jù)兩階段行為模式的不同,我們將分支事務(wù)劃分為 Automatic (Branch) Transaction ModeManual (Branch) Transaction Mode.

          AT 模式(參考鏈接 TBD)基于 支持本地 ACID 事務(wù)關(guān)系型數(shù)據(jù)庫

          • 一階段 prepare 行為:在本地事務(wù)中,一并提交業(yè)務(wù)數(shù)據(jù)更新和相應(yīng)回滾日志記錄。
          • 二階段 commit 行為:馬上成功結(jié)束,自動 異步批量清理回滾日志。
          • 二階段 rollback 行為:通過回滾日志,自動 生成補償操作,完成數(shù)據(jù)回滾。

          相應(yīng)的,TCC 模式,不依賴于底層數(shù)據(jù)資源的事務(wù)支持:

          • 一階段 prepare 行為:調(diào)用 自定義 的 prepare 邏輯。
          • 二階段 commit 行為:調(diào)用 自定義 的 commit 邏輯。
          • 二階段 rollback 行為:調(diào)用 自定義 的 rollback 邏輯。

          所謂 TCC 模式,是指支持把 自定義 的分支事務(wù)納入到全局事務(wù)的管理中。

          Saga 模式

          Saga模式是SEATA提供的長事務(wù)解決方案,在Saga模式中,業(yè)務(wù)流程中每個參與者都提交本地事務(wù),當出現(xiàn)某一個參與者失敗則補償前面已經(jīng)成功的參與者,一階段正向服務(wù)和二階段補償服務(wù)都由業(yè)務(wù)開發(fā)實現(xiàn)。

          Saga模式示意圖

          理論基礎(chǔ):Hector & Kenneth 發(fā)表論? Sagas (1987)

          適用場景:

          • 業(yè)務(wù)流程長、業(yè)務(wù)流程多
          • 參與者包含其它公司或遺留系統(tǒng)服務(wù),無法提供 TCC 模式要求的三個接口

          優(yōu)勢:

          • 一階段提交本地事務(wù),無鎖,高性能
          • 事件驅(qū)動架構(gòu),參與者可異步執(zhí)行,高吞吐
          • 補償服務(wù)易于實現(xiàn)

          缺點:

          • 不保證隔離性(應(yīng)對方案見用戶文檔)
          原文鏈接:http://seata.io/zh-cn/docs/overview/what-is-seata.html
          END/往期推薦:




          1.微服務(wù)實戰(zhàn)系列

          2.springboot從入門到精通

          3.java入門到精通

          4.中間件等

          5.程序人生

          更多信息請關(guān)注公眾號:「軟件老王」,關(guān)注不迷路,軟件老王和他的IT朋友們,分享一些他們的技術(shù)見解和生活故事。

          瀏覽 70
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲日韩中文字幕视频在线 | 狠狠爱伊人 | 日韩AV免费在线 | 一级 黄 色情 片 | 开心激情站中文字幕 |