<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>

          SpringCloud Alibaba之Seata分布式事務(wù)

          共 6133字,需瀏覽 13分鐘

           ·

          2021-02-09 23:51

          點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”

          優(yōu)質(zhì)文章,第一時間送達(dá)

          76套java從入門到精通實(shí)戰(zhàn)課程分享

          分布式事務(wù)基礎(chǔ)

          事務(wù)

          事務(wù)指的就是一個操作單元,在這個操作單元中的所有操作最終要保持一致的行為,要么所有操作都成功,要么所有的操作都被撤銷。簡單地說,事務(wù)提供一種“要么什么都不做,要么做全套”機(jī)制。

          本地事務(wù)

          本地事物其實(shí)可以認(rèn)為是數(shù)據(jù)庫提供的事務(wù)機(jī)制。說到數(shù)據(jù)庫事務(wù)就不得不說,數(shù)據(jù)庫事務(wù)中的四大特性:

          • A:原子性(Atomicity),一個事務(wù)中的所有操作,要么全部完成,要么全部不完成

          • C:一致性(Consistency),在一個事務(wù)執(zhí)行之前和執(zhí)行之后數(shù)據(jù)庫都必須處于一致性狀態(tài)

          • I:隔離性(Isolation),在并發(fā)環(huán)境中,當(dāng)不同的事務(wù)同時操作相同的數(shù)據(jù)時,事務(wù)之間互不影響

          • D:持久性(Durability),指的是只要事務(wù)成功結(jié)束,它對數(shù)據(jù)庫所做的更新就必須永久地保存下來

          數(shù)據(jù)庫事務(wù)在實(shí)現(xiàn)時會將一次事務(wù)涉及的所有操作全部納入到一個不可分割的執(zhí)行單元,該執(zhí)行單元中的所有操作要么都成功,要么都失敗,只要其中任一操作執(zhí)行失敗,都將導(dǎo)致整個事務(wù)的回滾

          分布式事務(wù)

          分布式事務(wù)指事務(wù)的參與者、支持事務(wù)的服務(wù)器、資源服務(wù)器以及事務(wù)管理器分別位于不同的分布式系統(tǒng)的不同節(jié)點(diǎn)之上。

          簡單地說,就是一次大的操作由不同的小操作組成,這些小的操作分布在不同的服務(wù)器上,且屬于不同的應(yīng)用,分布式事務(wù)需要保證這些小操作要么全部成功,要么全部失敗。

          本質(zhì)上來說,分布式事務(wù)就是為了保證不同數(shù)據(jù)庫的數(shù)據(jù)一致性。

          分布式事務(wù)的場景

          單體系統(tǒng)訪問多個數(shù)據(jù)庫

          一個服務(wù)需要調(diào)用多個數(shù)據(jù)庫實(shí)例完成數(shù)據(jù)的增刪改操作

          ?

          多個微服務(wù)訪問同一個數(shù)據(jù)庫

          多個服務(wù)需要調(diào)用一個數(shù)據(jù)庫實(shí)例完成數(shù)據(jù)的增刪改操作

          ?

          多個微服務(wù)訪問多個數(shù)據(jù)庫

          多個服務(wù)需要調(diào)用一個數(shù)據(jù)庫實(shí)例完成數(shù)據(jù)的增刪改操作

          ?

          分布式事務(wù)解決方案

          全局事務(wù)

          全局事務(wù)基于DTP模型實(shí)現(xiàn)。DTP是由X/Open組織提出的一種分布式事務(wù)模型——X/Open Distributed Transaction Processing Reference Model。它規(guī)定了要實(shí)現(xiàn)分布式事務(wù),需要三種角色:

          • AP: Application 應(yīng)用系統(tǒng) (微服務(wù))

          • TM: Transaction Manager 事務(wù)管理器 (全局事務(wù)管理)

          • RM: Resource Manager 資源管理器 (數(shù)據(jù)庫)

          整個事務(wù)分成兩個階段:

          • 階段一: 表決階段,所有參與者都將本事務(wù)執(zhí)行預(yù)提交,并將能否成功的信息反饋發(fā)給協(xié)調(diào)者。

          • 階段二: 執(zhí)行階段,協(xié)調(diào)者根據(jù)所有參與者的反饋,通知所有參與者,步調(diào)一致地執(zhí)行提交或者回滾。

          優(yōu)點(diǎn)

          • 提高了數(shù)據(jù)一致性的概率,實(shí)現(xiàn)成本較低

          缺點(diǎn)

          • 單點(diǎn)問題: 事務(wù)協(xié)調(diào)者宕機(jī)

          • 同步阻塞: 延遲了提交時間,加長了資源阻塞時間

          • 數(shù)據(jù)不一致: 提交第二階段,依然存在commit結(jié)果未知的情況,有可能導(dǎo)致數(shù)據(jù)不一致

          可靠消息服務(wù)

          基于可靠消息服務(wù)的方案是通過消息中間件保證上、下游應(yīng)用數(shù)據(jù)操作的一致性。假設(shè)有A和B兩個系統(tǒng),分別可以處理任務(wù)A和任務(wù)B。此時存在一個業(yè)務(wù)流程,需要將任務(wù)A和任務(wù)B在同一個事務(wù)中處理。就可以使用消息中間件來實(shí)現(xiàn)這種分布式事務(wù)。

          ?

          第一步:消息由系統(tǒng)A投遞到中間件

          1. 在系統(tǒng)A處理任務(wù)A前,首先向消息中間件發(fā)送一條消息

          2. 消息中間件收到后將該條消息持久化,但并不投遞。持久化成功后,向A回復(fù)一個確認(rèn)應(yīng)答

          3. 系統(tǒng)A收到確認(rèn)應(yīng)答后,則可以開始處理任務(wù)A

          4. 任務(wù)A處理完成后,向消息中間件發(fā)送Commit或者Rollback請求。該請求發(fā)送完成后,對系統(tǒng)A而言,該事務(wù)的處理過程就結(jié)束了

          5. 如果消息中間件收到Commit,則向B系統(tǒng)投遞消息;如果收到Rollback,則直接丟棄消息。但是如果消息中間件收不到Commit和Rollback指令,那么就要依靠"超時詢問機(jī)制"。

          超時詢問機(jī)制

          系統(tǒng)A除了實(shí)現(xiàn)正常的業(yè)務(wù)流程外,還需提供一個事務(wù)詢問的接口,供消息中間件調(diào)用。當(dāng)消息中間件收到發(fā)布消息便開始計時,如果到了超時沒收到確認(rèn)指令,就會主動調(diào)用系統(tǒng)A提供的事務(wù)詢問接口詢問該系統(tǒng)目前的狀態(tài)。該接口會返回三種結(jié)果,中間件根據(jù)三種結(jié)果做出不同反應(yīng):

          提交:將該消息投遞給系統(tǒng)B

          回滾:直接將條消息丟棄

          處理中:繼續(xù)等待

          第二步:消息由中間件投遞到系統(tǒng)B

          消息中間件向下游系統(tǒng)投遞完消息后便進(jìn)入阻塞等待狀態(tài),下游系統(tǒng)便立即進(jìn)行任務(wù)的處理,任務(wù)處理完成后便向消息中間件返回應(yīng)答。

          • 如果消息中間件收到確認(rèn)應(yīng)答后便認(rèn)為該事務(wù)處理完畢

          • 如果消息中間件在等待確認(rèn)應(yīng)答超時之后就會重新投遞,直到下游消費(fèi)者返回消費(fèi)成功響應(yīng)為止。

          一般消息中間件可以設(shè)置消息重試的次數(shù)和時間間隔,如果最終還是不能成功投遞,則需要手工干預(yù)。這里之所以使用人工干預(yù),而不是使用讓A系統(tǒng)回滾,主要是考慮到整個系統(tǒng)設(shè)計的復(fù)雜度問題。

          基于可靠消息服務(wù)的分布式事務(wù),前半部分使用異步,注重性能;后半部分使用同步,注重開發(fā)成本。

          最大努力通知

          最大努力通知也被稱為定期校對,其實(shí)是對第二種解決方案的進(jìn)一步優(yōu)化。它引入了本地消息表來記錄錯誤消息,然后加入失敗消息的定期校對功能,來進(jìn)一步保證消息會被下游系統(tǒng)消費(fèi)。

          ?

          第一步:消息由系統(tǒng)A投遞到中間件

          1. 處理業(yè)務(wù)的同一事務(wù)中,向本地消息表中寫入一條記錄

          2. 準(zhǔn)備專門的消息發(fā)送者不斷地發(fā)送本地消息表中的消息到消息中間件,如果發(fā)送失敗則重試

          第二步:消息由中間件投遞到系統(tǒng)B

          1. 消息中間件收到消息后負(fù)責(zé)將該消息同步投遞給相應(yīng)的下游系統(tǒng),并觸發(fā)下游系統(tǒng)的任務(wù)執(zhí)行

          2. 當(dāng)下游系統(tǒng)處理成功后,向消息中間件反饋確認(rèn)應(yīng)答,消息中間件便可以將該條消息刪除,從而該事務(wù)完成

          3. 對于投遞失敗的消息,利用重試機(jī)制進(jìn)行重試,對于重試失敗的,寫入錯誤消息表

          4. 消息中間件需要提供失敗消息的查詢接口,下游系統(tǒng)會定期查詢失敗消息,并將其消費(fèi)

          這種方式的優(yōu)缺點(diǎn):

          • 優(yōu)點(diǎn):?一種非常經(jīng)典的實(shí)現(xiàn),實(shí)現(xiàn)了最終一致性。

          • 缺點(diǎn):?消息表會耦合到業(yè)務(wù)系統(tǒng)中,如果沒有封裝好的解決方案,會有很多雜活需要處理。

          TCC事務(wù)

          TCC即為Try Confifirm Cancel,它屬于補(bǔ)償型分布式事務(wù)。TCC實(shí)現(xiàn)分布式事務(wù)一共有三個步驟:

          • Try:?嘗試待執(zhí)行的業(yè)務(wù):這個過程并未執(zhí)行業(yè)務(wù),只是完成所有業(yè)務(wù)的一致性檢查,并預(yù)留好執(zhí)行所需的全部資源

          • Confifirm:?確認(rèn)執(zhí)行業(yè)務(wù):確認(rèn)執(zhí)行業(yè)務(wù)操作,不做任何業(yè)務(wù)檢查, 只使用Try階段預(yù)留的業(yè)務(wù)資源。通常情況下,采用TCC則認(rèn)為 Confifirm階段是不會出錯的。即:只要Try成功,Confifirm一定成功。若Confifirm階段真的出錯了,需引入重試機(jī)制或人工處理。

          • Cancel:?取消待執(zhí)行的業(yè)務(wù):取消Try階段預(yù)留的業(yè)務(wù)資源。通常情況下,采用TCC則認(rèn)為Cancel階段也是一定成功的。若Cancel階段真的出錯了,需引入重試機(jī)制或人工處理

          ?

          ?

          TCC兩階段提交與XA兩階段提交的區(qū)別是:

          • XA是資源層面的分布式事務(wù),強(qiáng)一致性,在兩階段提交的整個過程中,一直會持有資源的鎖。

          • TCC是業(yè)務(wù)層面的分布式事務(wù),最終一致性,不會一直持有資源的鎖。

          TCC事務(wù)的優(yōu)缺點(diǎn):

          • 優(yōu)點(diǎn):把數(shù)據(jù)庫層的二階段提交上提到了應(yīng)用層來實(shí)現(xiàn),規(guī)避了數(shù)據(jù)庫層的2PC性能低下問題。

          • 缺點(diǎn):TCC的Try、Confifirm和Cancel操作功能需業(yè)務(wù)提供,開發(fā)成本高。

          Seata介紹

          2019 年 1 月,阿里巴巴中間件團(tuán)隊發(fā)起了開源項目?Fescar(Fast & EaSy Commit AndRollback),其愿景是讓分布式事務(wù)的使用像本地事務(wù)的使用一樣,簡單和高效,并逐步解決開發(fā)者們遇到的分布式事務(wù)方面的所有難題。后來更名為?Seata,意為:Simple Extensible Autonomous Transaction Architecture,是一套分布式事務(wù)解決方案。

          Seata的設(shè)計目標(biāo)是對業(yè)務(wù)無侵入,因此從業(yè)務(wù)無侵入的2PC方案著手,在傳統(tǒng)2PC的基礎(chǔ)上演進(jìn)。它把一個分布式事務(wù)理解成一個包含了若干分支事務(wù)的全局事務(wù)。全局事務(wù)的職責(zé)是協(xié)調(diào)其下管轄的分支事務(wù)達(dá)成一致,要么一起成功提交,要么一起失敗回滾。此外,通常分支事務(wù)本身就是一個關(guān)系數(shù)據(jù)庫的本地事務(wù)。

          ?

          Seata主要由三個重要組件組成:

          • TC:Transaction Coordinator 事務(wù)協(xié)調(diào)器,管理全局的分支事務(wù)的狀態(tài),用于全局性事務(wù)的提交和回滾。

          • TM:Transaction Manager 事務(wù)管理器,用于開啟、提交或者回滾全局事務(wù)。

          • RM:Resource Manager 資源管理器,用于分支事務(wù)上的資源管理,向TC注冊分支事務(wù),上報分支事務(wù)的狀態(tài),接受TC的命令來提交或者回滾分支事務(wù)。

          ?

          Seata的執(zhí)行流程如下:

          1. A服務(wù)的TM向TC申請開啟一個全局事務(wù),TC就會創(chuàng)建一個全局事務(wù)并返回一個唯一的XID

          2. A服務(wù)的RM向TC注冊分支事務(wù),并及其納入XID對應(yīng)全局事務(wù)的管轄

          3. A服務(wù)執(zhí)行分支事務(wù),向數(shù)據(jù)庫做操作

          4. A服務(wù)開始遠(yuǎn)程調(diào)用B服務(wù),此時XID會在微服務(wù)的調(diào)用鏈上傳播

          5. B服務(wù)的RM向TC注冊分支事務(wù),并將其納入XID對應(yīng)的全局事務(wù)的管轄

          6. B服務(wù)執(zhí)行分支事務(wù),向數(shù)據(jù)庫做操作

          7. 全局事務(wù)調(diào)用鏈處理完畢,TM根據(jù)有無異常向TC發(fā)起全局事務(wù)的提交或者回滾

          8. TC協(xié)調(diào)其管轄之下的所有分支事務(wù), 決定是否回滾

          Seata實(shí)現(xiàn)2PC與傳統(tǒng)2PC的差別

          1. 架構(gòu)層次方面,傳統(tǒng)2PC方案的 RM 實(shí)際上是在數(shù)據(jù)庫層,RM本質(zhì)上就是數(shù)據(jù)庫自身,通過XA協(xié)議實(shí)現(xiàn),而 Seata的RM是以jar包的形式作為中間件層部署在應(yīng)用程序這一側(cè)的。

          2. 兩階段提交方面,傳統(tǒng)2PC無論第二階段的決議是commit還是rollback,事務(wù)性資源的鎖都要保持到Phase2完成才釋放。而Seata的做法是在Phase1 就將本地事務(wù)提交,這樣就可以省去Phase2持鎖的時間,整體提高效率

          Seata實(shí)現(xiàn)分布式事務(wù)控制

          本示例通過Seata中間件實(shí)現(xiàn)分布式事務(wù),模擬電商中的下單和扣庫存的過程

          我們通過訂單微服務(wù)執(zhí)行下單操作,然后由訂單微服務(wù)調(diào)用商品微服務(wù)扣除庫存

          ?

          案例基本代碼

          修改order微服務(wù)

          controller

          @RestController?
          @Slf4j?
          public?class?OrderController5?{
          ?@Autowired?
          ?private?OrderServiceImpl5?orderService;
          ?//下單?
          ?@RequestMapping("/order/prod/{pid}")?
          ?public?Order?order(@PathVariable("pid")?Integer?pid)?{
          ??log.info("接收到{}號商品的下單請求,接下來調(diào)用商品微服務(wù)查詢此商品信息",?pid);
          ??return?orderService.createOrder(pid);
          ?}
          }


          OrderService

          @Service?
          @Slf4j?
          public?class?OrderServiceImpl5{
          ?@Autowired?
          ?private?OrderDao?orderDao;
          ?@Autowired?
          ?private?ProductService?productService;
          ?@Autowired?
          ?private?RocketMQTemplate?rocketMQTemplate;
          ?@GlobalTransactional?
          ?public?Order?createOrder(Integer?pid)?{
          ??//1?調(diào)用商品微服務(wù),查詢商品信息?
          ??Product?product?=?productService.findByPid(pid);
          ??log.info("查詢到{}號商品的信息,內(nèi)容是:{}",?pid,?JSON.toJSONString(product));
          ??//2?下單(創(chuàng)建訂單)?
          ??Order?order?=?new?Order();
          ??order.setUid(1);
          ??order.setUsername("測試用戶");
          ??order.setPid(pid);
          ??order.setPname(product.getPname());
          ??order.setPprice(product.getPprice());
          ??order.setNumber(1);
          ??orderDao.save(order);
          ??log.info("創(chuàng)建訂單成功,訂單信息為{}",?JSON.toJSONString(order));
          ??//3?扣庫存?
          ??productService.reduceInventory(pid,?order.getNumber());
          ??//4?向mq中投遞一個下單成功的消息?
          ??rocketMQTemplate.convertAndSend("order-topic",?order);
          ??return?order;
          ?}
          }


          ProductService

          @FeignClient(value?=?"service-product")?
          public?interface?ProductService?{
          ?//減庫存?
          ?@RequestMapping("/product/reduceInventory")?
          ??void?reduceInventory(@RequestParam("pid")?Integer?pid,?@RequestParam("num")?
          ??int?num);
          }


          修改Product微服務(wù)

          controller

          //減少庫存?
          @RequestMapping("/product/reduceInventory")?
          public?void?reduceInventory(Integer?pid,?int?num)?{
          ?productService.reduceInventory(pid,?num);
          }


          service

          @Override?
          public?void?reduceInventory(Integer?pid,?int?num)?{
          ?Product?product?=?productDao.findById(pid).get();
          ?product.setStock(product.getStock()?-?num);
          ?//減庫存?
          ?productDao.save(product);
          }


          異常模擬

          在ProductServiceImpl的代碼中模擬一個異常, 然后調(diào)用下單接口

          @Override?
          public?void?reduceInventory(Integer?pid,?Integer?number)?{
          ?Product?product?=?productDao.findById(pid).get();
          ?if?(product.getStock()???throw?new?RuntimeException("庫存不足");
          ?}
          ?int?i?=?1?/?0;
          ?product.setStock(product.getStock()?-?number);
          ?productDao.save(product);
          }


          啟動Seata

          修改配置文件

          將下載得到的壓縮包進(jìn)行解壓,進(jìn)入conf目錄,調(diào)整下面的配置文件:

          registry.conf

          registry?{
          ?type?=?"nacos"?
          ?nacos?{?
          ?serverAddr?=?"localhost"?
          ?namespace?=?"public"?
          ?cluster?=?"default"?
          ?}?
          ?}
          ?config?{?
          ?type?=?"nacos"?
          ?nacos?{?
          ?serverAddr?=?"localhost"?
          ?namespace?=?"public"?
          ?cluster?=?"default"?
          ?}?
          ?}


          nacos-confifig.txt

          service.vgroup_mapping.service-product=default?
          service.vgroup_mapping.service-order=default


          這里的語法為:service.vgroup_mapping.${your-service-gruop}=default,中間的${your-service-gruop}為自己定義的服務(wù)組名稱, 這里需要我們在程序的配置文件中配置

          初始化seata在nacos的配置

          \#?初始化seata?的nacos配置?
          ?
          \#?注意:?這里要保證nacos是已經(jīng)正常運(yùn)行的?
          ?
          cd?conf?
          ?
          nacos-config.sh?127.0.0.1


          執(zhí)行成功后可以打開Nacos的控制臺,在配置列表中,可以看到初始化了很多Group為SEATA_GROUP的配置。

          啟動seata服務(wù)

          cd?bin?
          ?
          seata-server.bat?-p?9000?-m?file


          啟動后在 Nacos 的服務(wù)列表下面可以看到一個名為 serverAddr 的服務(wù)。

          使用Seata實(shí)現(xiàn)事務(wù)控制

          初始化數(shù)據(jù)表

          在我們的數(shù)據(jù)庫中加入一張undo_log表,這是Seata記錄事務(wù)日志要用到的表

          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,?
          `ext`?VARcHAR(100)?DEFAULT?NULL,?
          PRIMARY?KEY?(`id`),?
          UNIQUE?KEY?`ux_undo_log`?(`xid`,?`branch_id`)?
          )?ENGINE?=?INNODB?
          AUTO_INCREMENT?=?1?
          DEFAULT?CHARSET?=?utf8;


          添加配置

          在需要進(jìn)行分布式控制的微服務(wù)中進(jìn)行下面幾項配置:

          添加依賴

          ?
          ?
          com.alibaba.cloud?
          ?
          spring-cloud-starter-alibaba-seata?
          ?
          ?
          ?
          ?
          ?
          com.alibaba.cloud?
          ?
          spring-cloud-starter-alibaba-nacos-config?
          ?


          DataSourceProxyConfifig

          Seata 是通過代理數(shù)據(jù)源實(shí)現(xiàn)事務(wù)分支的,所以需要配置 io.seata.rm.datasource.DataSourceProxy 的Bean,且是 @Primary默認(rèn)的數(shù)據(jù)源,否則事務(wù)不會回滾,無法實(shí)現(xiàn)分布式事務(wù)

          @Configuration?
          public?class?DataSourceProxyConfig?{
          ?@Bean?
          ?@ConfigurationProperties(prefix?=?"spring.datasource")?
          ?public?DruidDataSource?druidDataSource()?{
          ??return?new?DruidDataSource();
          ?}
          ?@Primary?
          ?@Bean?
          ?public?DataSourceProxy?dataSource(DruidDataSource?druidDataSource)?{
          ??return?new?DataSourceProxy(druidDataSource);
          ?}
          }


          registry.conf

          在resources下添加Seata的配置文件 registry.conf

          registry?{
          ?type?=?"nacos"?
          ?nacos?{?
          ?serverAddr?=?"localhost"?
          ?namespace?=?"public"?
          ?cluster?=?"default"?
          ?}?
          ?}
          ?config?{?
          ?type?=?"nacos"?
          ?nacos?{?
          ?serverAddr?=?"localhost"?
          ?namespace?=?"public"?
          ?cluster?=?"default"
          ?}?
          ?}


          bootstrap.yaml

          spring:?
          application:?
          name:?service-product?
          cloud:?
          nacos:?
          config:?
          server-addr:?localhost:8848?#?nacos的服務(wù)端地址?
          namespace:?public?
          group:?SEATA_GROUP?
          alibaba:?
          seata:?
          tx-service-group:?${
          ?spring.application.name
          }


          在order微服務(wù)開啟全局事務(wù)

          @GlobalTransactional//全局事務(wù)控制?
          ?
          public?Order?createOrder(Integer?pid)?{}


          測試

          再次下單測試

          seata運(yùn)行流程分析

          ?

          要點(diǎn)說明:

          1. 每個RM使用DataSourceProxy連接數(shù)據(jù)庫,其目的是使用ConnectionProxy,使用數(shù)據(jù)源和數(shù)據(jù)連接代理的目的就是在第一階段將undo_log和業(yè)務(wù)數(shù)據(jù)放在一個本地事務(wù)提交,這樣就保存了只要有業(yè)務(wù)操作就一定有undo_log。

          2. 在第一階段undo_log中存放了數(shù)據(jù)修改前和修改后的值,為事務(wù)回滾作好準(zhǔn)備,所以第一階段完成就已經(jīng)將分支事務(wù)提交,也就釋放了鎖資源。

          3. TM開啟全局事務(wù)開始,將XID全局事務(wù)id放在事務(wù)上下文中,通過feign調(diào)用也將XID傳入下游分支事務(wù),每個分支事務(wù)將自己的Branch ID分支事務(wù)ID與XID關(guān)聯(lián)。

          4. 第二階段全局事務(wù)提交,TC會通知各各分支參與者提交分支事務(wù),在第一階段就已經(jīng)提交了分支事務(wù),這里各各參與者只需要刪除undo_log即可,并且可以異步執(zhí)行,第二階段很快可以完成。

          5. 第二階段全局事務(wù)回滾,TC會通知各各分支參與者回滾分支事務(wù),通過 XID 和 Branch ID 找到相應(yīng)的回滾日志,通過回滾日志生成反向的 SQL 并執(zhí)行,以完成分支事務(wù)回滾到之前的狀態(tài),如果回滾失敗則會重試回滾操作


          版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。

          本文鏈接:

          https://blog.csdn.net/python8989/article/details/113666402




          鋒哥最新SpringCloud分布式電商秒殺課程發(fā)布

          ??????

          ??長按上方微信二維碼?2 秒






          感謝點(diǎn)贊支持下哈?

          瀏覽 82
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  国产视频激情 | 日日干,夜夜操 | 一级a免一级a做免费线看内裤的 | 亚洲天堂2013 | 男人的天堂高清无码 |