<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下基于Seata AT的分布式事務(wù)實(shí)踐

          共 11340字,需瀏覽 23分鐘

           ·

          2021-11-22 16:01

          Seata是Spring Cloud Alibaba中一款開源的分布式事務(wù)解決方案,本文具體就Seata的AT模式進(jìn)行介紹、實(shí)踐

          6c1896dd7eb0eaa959c2a6f3c21baeae.webp

          abstract.png基本原理

          在Seata的設(shè)計(jì)架構(gòu)中有三個(gè)角色,具體如下

          • TC(Transaction Coordinator): 事務(wù)協(xié)調(diào)者。維護(hù)全局和分支事務(wù)的狀態(tài),驅(qū)動(dòng)全局事務(wù)提交或回滾
          • TM(Transaction Manager): 事務(wù)管理器。定義全局事務(wù)的范圍,用于開始、提交、回滾全局事務(wù)
          • RM(Resource Manager): 資源管理器。管理分支事務(wù)處理的資源,與TC通訊以注冊分支事務(wù)和報(bào)告分支事務(wù)的狀態(tài),并驅(qū)動(dòng)分支事務(wù)進(jìn)行提交或回滾

          TC是Seata的服務(wù)端需獨(dú)立部署,而TM、RM則是作為Seata的客戶端與各微服務(wù)進(jìn)行集成。三者之間的流程關(guān)系如下圖所示。具體地,Seata的分布式事務(wù)模型是基于 2PC(兩階段提交,Tow-Phase Commit) 協(xié)議,基本執(zhí)行流程如下

          1. TM向TC申請開啟一個(gè)分布式事務(wù),事務(wù)創(chuàng)建成功后會生成一個(gè)全局唯一的事務(wù)ID,即所謂的XID
          2. RM向TC注冊分支事務(wù),匯報(bào)資源準(zhǔn)備狀態(tài)
          3. TM通知TC 提交/回滾 分布式事務(wù),事務(wù)一階段結(jié)束
          4. TC匯總各分支事務(wù)信息,決定分布式事務(wù)是提交還是回滾
          5. TC通知所有RM 提交/回滾 資源,分布式事務(wù)的二階段結(jié)束

          933900918e8a5f52b4eee5886ef591ad.webp

          figure 1.png

          具體地,Seata支持AT、TCC、Saga、XA四種模式。這里就AT模式進(jìn)行展開說明,其是一種無侵入的分布式事務(wù)解決方案,使得開發(fā)者只需關(guān)注自己的業(yè)務(wù)SQL即可。Seata會自動(dòng)進(jìn)行二階段的提交/回滾。流程如下

          • 一階段: Seata對業(yè)務(wù)SQL進(jìn)行攔截、語義解析,進(jìn)而確定業(yè)務(wù)SQL需要操作的相關(guān)業(yè)務(wù)數(shù)據(jù)記錄。然后在執(zhí)行業(yè)務(wù)SQL前,將相關(guān)業(yè)務(wù)數(shù)據(jù)記錄保存為Before Image。在執(zhí)行業(yè)務(wù)SQL后,再將其保存成After Image。并最終生成行鎖。上述操作會在一個(gè)數(shù)據(jù)庫的本地事務(wù)內(nèi)完成,以保證一階段操作的原子性

          ac1b5037a31728b0ab62671623fd5d17.webp

          figure 2.png
          • 二階段提交: 二階段提交時(shí),因?yàn)闃I(yè)務(wù)SQL在一階段已經(jīng)提交至各數(shù)據(jù)庫。故Seata只需將一階段保存的快照數(shù)據(jù)和行鎖刪掉,完成數(shù)據(jù)清理即可

          0c8b221365d68f33363691b6e0f724ff.webp

          figure 3.png
          • 二階段回滾: 二階段回滾時(shí),首先需要對數(shù)據(jù)庫當(dāng)前相關(guān)的數(shù)據(jù)與After Image進(jìn)行比對,如果完全一致,這說明未發(fā)生臟寫。即沒有被除當(dāng)前全局事務(wù)之外的其他操作修改過,可以放心進(jìn)行回滾。而具體回滾則是通過Before Image生成逆向SQL來進(jìn)行反向補(bǔ)償,并最終刪除相應(yīng)快照數(shù)據(jù)和行鎖

          5a4e4c65bedc5ab60d3694ea6abdd694.webp

          figure 4.png基于Seata AT模式的實(shí)踐

          搭建Seata Server環(huán)境

          基于Docker Compose的服務(wù)部署

          Seata Server事實(shí)上就是上文提到的事務(wù)協(xié)調(diào)者TC。這里通過Docker Compose來進(jìn)行部署,如下所示。可以看到我們不僅創(chuàng)建了Seata Server服務(wù),還創(chuàng)建了MySQL、Nacos服務(wù)。后面會一一進(jìn)行解釋

          #?Compose?版本
          version:?'3.8'

          #?定義Docker服務(wù)
          services:

          ??#?Seata?服務(wù)
          ??Seata-Service-1:
          ????image:?seataio/seata-server:1.3.0
          ????container_name:?Seata-Service-1
          ????ports:
          ??????-?"9091:8091"
          ????networks:
          ??????seata_service_net:
          ????????ipv4_address:?120.120.120.21
          ????depends_on:
          ??????-?MySQL-Service-1
          ??????-?Nacos-Service-1

          ??#?MySQL?服務(wù)
          ??MySQL-Service-1:
          ????image:?mysql:5.7
          ????container_name:?MySQL-Service-1
          ????ports:
          ??????-?"9306:3306"
          ????environment:
          ??????MYSQL_ROOT_PASSWORD:?12345
          ????networks:
          ??????seata_service_net:
          ????????ipv4_address:?120.120.120.22

          ??#?Nacos?服務(wù)
          ??Nacos-Service-1:
          ????image:?nacos/nacos-server:1.4.2
          ????container_name:?Nacos-Service-1
          ????ports:
          ??????-?"9848:8848"
          ????environment:
          ??????MODE:?standalone
          ????networks:
          ??????seata_service_net:
          ????????ipv4_address:?120.120.120.23

          #?定義網(wǎng)絡(luò)
          networks:
          ??seata_service_net:
          ????ipam:
          ??????config:
          ????????-?subnet:?120.120.120.0/24

          配置Seata Server的持久化

          Seata-Server支持多種持久化方式包括文件、DB、Redis等,默認(rèn)為文件File。這里我們使用剛剛部署MySQL-Service-1服務(wù)進(jìn)行持久化。進(jìn)入Seata-Service-1容器,修改/seata-server/resources下的file.conf文件,將存儲模式修改為db,同時(shí)修改相應(yīng)的數(shù)據(jù)庫連接信息。如下所示,可以看到這里datasource我們選擇了druid

          086683f2c1f22011b2f0eb4a4d078f47.webp

          figure 5.jpeg

          然后,通過數(shù)據(jù)庫客戶端連接MySQL-Service-1實(shí)例。首先創(chuàng)建file.conf文件中所連接的數(shù)據(jù)庫seataServer,然后在該數(shù)據(jù)庫中執(zhí)行建表語句。其中SQL腳本可通過Github進(jìn)行獲取,地址如下所示

          #?下載地址:?Seata?Server使用DB進(jìn)行持久化的SQL初始化腳本
          https://github.com/seata/seata/blob/1.3.0/script/server/db/mysql.sql

          效果如下所示

          d4b9e1156542f56d89c81c47bfd327b9.webp

          figure 6.jpeg

          配置Seata Server的注冊中心、配置中心

          前面提到,我們還創(chuàng)建了一個(gè)Nacos容器,即Nacos-Service-1實(shí)例。其是用于作為整個(gè)分布式環(huán)境的配置中心、注冊中心。同樣進(jìn)入Seata-Service-1容器,修改/seata-server/resources下的registry.conf文件。將注冊中心、配置中心均設(shè)置Nacos。詳細(xì)配置如下所示

          43c2fd84d6e624fa23a333d6db728141.webp

          figure 7.jpeg

          導(dǎo)入配置信息至Nacos

          事實(shí)上對于Seata而言,其配置信息支持兩種形式:本地文件、配置中心。對于后者而言,我們需要將Seata的相關(guān)配置項(xiàng)導(dǎo)入到配置中心。同樣,我們需要通過Github來下載配置文件config.txt及相應(yīng)的導(dǎo)入腳本nacos-config.sh

          #?下載地址:?配置中心的配置項(xiàng)
          https://github.com/seata/seata/blob/1.3.0/script/config-center/config.txt

          #?下載地址:?用于將配置項(xiàng)導(dǎo)入至Nacos的腳本
          https://github.com/seata/seata/blob/1.3.0/script/config-center/nacos/nacos-config.sh

          對于配置文件config.txt而言,有以下兩點(diǎn)需要注意

          1. 將配置項(xiàng)store.mode存儲模式修改為db,同時(shí)修改以store.db為前綴的相關(guān)配置項(xiàng),保證其與file.conf文件中相關(guān)數(shù)據(jù)庫的配置一致
          2. 配置項(xiàng)service.vgroupMapping.my_test_tx_group=default的含義是,事務(wù)分組my_test_tx_group使用名為default的Seata Server集群。換言之,my_test_tx_group即為事務(wù)分組的名稱,支持自定義。這里我們直接使用默認(rèn)的事務(wù)分組名。而Seata Server集群名default實(shí)際上就是來自registry.conf文件的cluster配置項(xiàng)

          4a7131c121877f1a3163630778cf129c.webp

          figure 8.jpeg

          在完成配置文件config.txt的修改后,即可利用Shell腳本導(dǎo)入至Nacos中。值得一提的是,配置文件config.txt應(yīng)與Shell腳本的上一級目錄保持平行。然后在Shell腳本所在目錄中執(zhí)行如下命令即可

          #?執(zhí)行Shell腳本
          sh?nacos-config.sh?-h?localhost?-p?9848

          該Shell腳本支持的選項(xiàng)如下所示

          • -h: Nacos服務(wù)的IP地址,默認(rèn)為localhost
          • -p: Nacos服務(wù)的Port端口,默認(rèn)為8848
          • -g: Nacos分組名,默認(rèn)為SEATA_GROUP
          • -t: Nacos命名空間ID。默認(rèn)為“”,即使用public命名空間
          • -u: Nacos服務(wù)的用戶名
          • -w: Nacos服務(wù)的密碼

          效果如下所示

          bf60078564cdcba52a85b9906138264e.webp

          figure 9.jpeg

          至此,Seata server相關(guān)環(huán)境及配置就完成了。最后,重啟Seata-Service-1容器以讓修改生效即可。通過Nacos的Web管理頁面可以看到,Seata服務(wù)已經(jīng)注冊到Nacos

          098cd765ea660654330e55d27ce6d218.webp

          figure 10.jpeg

          搭建order服務(wù)

          POM依賴

          這里通過SpringBoot搭建一個(gè)微服務(wù)——order服務(wù)。這里給出關(guān)鍵性的依賴及版本,如下所示

          <dependencyManagement>
          ??<dependencies>
          ??
          ????
          ????<dependency>
          ??????<groupId>org.springframework.bootgroupId>
          ??????<artifactId>spring-boot-dependenciesartifactId>
          ??????<version>2.3.2.RELEASEversion>
          ??????<type>pomtype>
          ??????<scope>importscope>
          ????dependency>
          ??
          ????
          ????<dependency>
          ??????<groupId>org.springframework.cloudgroupId>
          ??????<artifactId>spring-cloud-dependenciesartifactId>
          ??????<version>Hoxton.SR8version>
          ??????<type>pomtype>
          ??????<scope>importscope>
          ????dependency>
          ??
          ????
          ????<dependency>
          ??????<groupId>com.alibaba.cloudgroupId>
          ??????<artifactId>spring-cloud-alibaba-dependenciesartifactId>
          ??????<version>2.2.3.RELEASEversion>
          ??????<type>pomtype>
          ??????<scope>importscope>
          ????dependency>

          ??dependencies>
          dependencyManagement>

          <dependencies>

          ??
          ??<dependency>
          ????<groupId>com.alibaba.cloudgroupId>
          ????<artifactId>spring-cloud-starter-alibaba-seataartifactId>
          ????<exclusions>
          ??????<exclusion>
          ????????<groupId>io.seatagroupId>
          ????????<artifactId>seata-spring-boot-starterartifactId>
          ??????exclusion>
          ????exclusions>
          ??dependency>
          ??
          ??<dependency>
          ????<groupId>io.seatagroupId>
          ????<artifactId>seata-spring-boot-starterartifactId>
          ????<version>1.3.0version>
          ??dependency>

          ??
          ??<dependency>
          ????<groupId>com.alibaba.cloudgroupId>
          ????<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
          ??dependency>

          ??
          ??<dependency>
          ????<groupId>com.alibaba.cloudgroupId>
          ????<artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
          ??dependency>

          ??
          ??<dependency>
          ????<groupId>com.alibabagroupId>
          ????<artifactId>fastjsonartifactId>
          ????<version>1.2.76version>
          ??dependency>

          ??
          ??<dependency>
          ????<groupId>com.baomidougroupId>
          ????<artifactId>mybatis-plus-boot-starterartifactId>
          ????<version>3.4.1version>
          ??dependency>
          ??
          dependencies>

          服務(wù)配置

          order服務(wù)的配置文件application.yml,如下所示。這里關(guān)于Seata數(shù)據(jù)源的代理,我們選擇自動(dòng)代理的方式。此外配置文件中的相關(guān)IP、端口信息均為容器內(nèi)部的IP、Port。因?yàn)閷τ赟pringBoot服務(wù)我們也會通過Docker的方式進(jìn)行構(gòu)建、打包及部署

          server:
          ??port:?89

          spring:
          ??application:
          ????name:?order
          ??datasource:
          ????type:?com.alibaba.druid.pool.DruidDataSource
          ????driver-class-name:?com.mysql.jdbc.Driver
          ????url:?jdbc:mysql://120.120.120.42:3306/order?allowPublicKeyRetrieval=true&useSSL=false
          ????username:?root
          ????password:?12345
          ??cloud:
          ????nacos:
          ??????discovery:
          ????????#?注冊中心?Nacos?地址信息
          ????????server-addr:?120.120.120.23:8848
          ????alibaba:
          ??????seata:
          ????????#?配置所使用的事務(wù)分組名稱
          ????????tx-service-group:?my_test_tx_group

          #?Mybatis-Plus?配置
          mybatis-plus:
          ??mapper-locations:?classpath:mapper/*.xml

          #?Seata?Server配置
          seata:
          ??#?Seata服務(wù)端所在注冊中心的配置信息
          ??registry:
          ????#?注冊中心類型
          ????type:?nacos
          ????nacos:
          ??????#?Seata服務(wù)端的服務(wù)名
          ??????application:?seata-server
          ??????#?Seata服務(wù)端所在的注冊中心信息
          ??????server-addr:?120.120.120.23:8848
          ??????username:?nacos
          ??????password:?nacos
          ??????group:?SEATA_GROUP
          ??#?Seata服務(wù)端所在配置中心的配置信息
          ??config:
          ????type:?nacos
          ????nacos:
          ??????server-addr:?120.120.120.23:8848
          ??????username:?nacos
          ??????password:?nacos
          ??????group:?SEATA_GROUP
          ??#?使能Seata自動(dòng)代理數(shù)據(jù)源
          ??enable-auto-data-source-proxy:?true

          #?Actuator配置:?開啟所有端點(diǎn)
          management:
          ??endpoints:
          ????web:
          ??????exposure:
          ????????include:?"*"
          ??????base-path:?/actuator

          Controller層

          在order服務(wù)中通過添加一個(gè)Controller類用于進(jìn)行測試,核心代碼實(shí)現(xiàn)如下。addRecord方法邏輯很簡單。首先向自己的數(shù)據(jù)庫插入一條記錄,然后再調(diào)用另外一個(gè)服務(wù)pyament的接口。由于該方法是作為分布式事務(wù)的發(fā)起者,故需要在方法上添加 @GlobalTransactional 注解,以開啟一個(gè)分布式事務(wù)

          @RestController
          @RequestMapping("order2")
          public?class?OrderController2?{

          ????//?使用?注冊中心的服務(wù)名
          ????public?static?final?String?PAYMENT_URL?=?"http://payment";

          ????@Autowired
          ????private?RestTemplate?restTemplate;

          ????@Autowired
          ????private?OrderRecordMapper?orderRecordMapper;

          ????@GlobalTransactional
          ????@GetMapping("/addRecord")
          ????public?String?addRecord(@RequestParam?String?name,?@RequestParam?Integer?total)?{
          ????????OrderRecord?orderRecord?=?OrderRecord.builder()
          ????????????.name(name)
          ????????????.total(total)
          ????????????.build();

          ????????//?save方法通過MybatisPlus中的自定義SQL實(shí)現(xiàn)
          ????????orderRecordMapper.save(orderRecord);
          ????????String?msg?=?restTemplate.getForObject(PAYMENT_URL?+"/pay3/test1?name={1}",?String.class,?name);
          ????????return?"OK";
          ????}
          }

          ...

          @Configuration
          public?class?RestTemplateConfig?{
          ????@Bean
          ????@LoadBalanced
          ????public?RestTemplate?restTemplate()?{
          ????????return?new?RestTemplate();
          ????}
          }
          ...

          @Data
          @Builder
          @AllArgsConstructor
          @NoArgsConstructor
          @TableName("orderRecord")?????//?指定數(shù)據(jù)庫的表名
          public?class?OrderRecord?{
          ????@TableId
          ????private?int?id;
          ????private?String?name;
          ????private?int?total;
          }

          服務(wù)部署

          首先將SpringBoot服務(wù)打包為Docker鏡像,然后通過Docker Compose進(jìn)行服務(wù)部署。為保證各服務(wù)、容器間的網(wǎng)絡(luò)互通互聯(lián),這里order服務(wù)的容器同樣需要使用Seata Server所在的名為seata_service_net的自定義網(wǎng)絡(luò)。由于docker-compose.yml中自定義網(wǎng)絡(luò)在創(chuàng)建后,其最終的網(wǎng)絡(luò)名稱是包含項(xiàng)目名的。故首先用docker network ls查看該網(wǎng)絡(luò)的全名。如下所示,即該網(wǎng)絡(luò)全名為seata-service_seata_service_net

          0e70c6157e8ce7650b89450aa2e8e2f7.webp

          figure 11.jpeg

          在分布式環(huán)境下,每個(gè)微服務(wù)都是使用自己的數(shù)據(jù)庫。這一點(diǎn)在order服務(wù)的application.yml配置文件中也可以看到。故在docker-compose.yml中我們同樣需要為order服務(wù)創(chuàng)建一個(gè)MySQL實(shí)例。如下所示

          #?Compose?版本
          version:?'3.8'

          #?定義Docker服務(wù)
          services:

          ??#?Web服務(wù)
          ??Order-Service:
          ????image:?aaron1995/spring_boot_order:1.0
          ????container_name:?Order-Service
          ????ports:
          ??????-?"8089:89"
          ????networks:
          ??????seata-service_seata_service_net:
          ????????ipv4_address:?120.120.120.41
          ????depends_on:
          ??????-?Order-MySQL

          ??#?MySQL?服務(wù)
          ??Order-MySQL:
          ????image:?mysql:5.7
          ????container_name:?Order-MySQL
          ????ports:
          ??????-?"9307:3306"
          ????environment:
          ??????MYSQL_ROOT_PASSWORD:?12345
          ????networks:
          ??????seata-service_seata_service_net:
          ????????ipv4_address:?120.120.120.42

          #?定義網(wǎng)絡(luò)
          networks:
          ??#?聲明名為seata-service_seata_service_net的網(wǎng)絡(luò)是一個(gè)已存在的網(wǎng)絡(luò)
          ??seata-service_seata_service_net:
          ????external:?true

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

          通過數(shù)據(jù)庫客戶端連接Order服務(wù)的數(shù)據(jù)庫,即Order-MySQL容器。首先order服務(wù)所連接的數(shù)據(jù)庫order,然后在該數(shù)據(jù)庫中執(zhí)行相關(guān)業(yè)務(wù)的建表語句

          #?建庫建表
          create?database?`order`;
          use?`order`;
          create?table?orderRecord?(
          ????id?int?not?null?auto_increment,
          ????name?varchar(255)?null,
          ????total?int?null,
          ????primary?key?(id)
          );

          當(dāng)然上述這些并無什么特別,只是業(yè)務(wù)方面需要。而為了保證Seata在事務(wù)出現(xiàn)異常時(shí)可以實(shí)現(xiàn)對業(yè)務(wù)數(shù)據(jù)進(jìn)行回滾,我們還需要在業(yè)務(wù)的數(shù)據(jù)庫中建立undo_log表。類似地,該SQL腳本也可通過Github進(jìn)行獲取,下載地址如下所示

          #?下載地址:?業(yè)務(wù)數(shù)據(jù)庫中undo_log表的建表SQL腳本
          https://github.com/seata/seata/blob/1.3.0/script/client/at/db/mysql.sql

          效果如下所示

          1448fc8cd1f5cbcce1e1dd397e92df89.webp

          figure 12.jpeg

          搭建payment服務(wù)

          為了驗(yàn)證分布式事務(wù),自然不能只有一個(gè)微服務(wù)。故這里類似地我們再搭建一個(gè)payment服務(wù)。當(dāng)然基本搭建過程與order服務(wù)并無明顯差異。首先在POM依賴方面,payment服務(wù)的POM依賴與order服務(wù)一致,同樣也需要引入Seata、Nacos等相關(guān)依賴。其次在服務(wù)配置方面,payment服務(wù)的application.yml配置文件中關(guān)于Seata、Nacos相關(guān)的配置自然與order服務(wù)并無二致。但需調(diào)整修改其所連接的數(shù)據(jù)庫信息,如下所示。即使用自身的數(shù)據(jù)庫

          server:
          ??port:?8011

          spring:
          ??application:
          ????name:?payment
          ??datasource:
          ????type:?com.alibaba.druid.pool.DruidDataSource
          ????driver-class-name:?com.mysql.jdbc.Driver
          ????url:?jdbc:mysql://120.120.120.52:3306/payment?allowPublicKeyRetrieval=true&useSSL=false
          ????username:?root
          ????password:?12345

          在payment服務(wù)中添加相應(yīng)的Controller方法

          @RestController
          @RequestMapping("pay3")
          public?class?PaymentController3?{

          ????@Autowired
          ????private?PayRecordMapper?payRecordMapper;

          ????@GetMapping("/test1")
          ????public?String?test1(@RequestParam?String?name)?{
          ????????//?更新自身數(shù)據(jù)庫中id為1的記錄
          ????????PayRecord?payRecord?=?PayRecord.builder()
          ????????????.id(1)
          ????????????.serial(?name?+",?"+?UUID.randomUUID().toString()?)
          ????????????.build();
          ????????payRecordMapper.updateById(payRecord);
          ????????if(name.equals("Tony"))?{
          ????????????throw?new?RuntimeException("發(fā)生業(yè)務(wù)異常");
          ????????}
          ????????return?"OK";
          ????}
          }

          ...

          @Data
          @Builder
          @AllArgsConstructor
          @NoArgsConstructor
          @TableName("payRecord")?????//?指定數(shù)據(jù)庫的表名
          public?class?PayRecord?{
          ????private?int?id;
          ????private?String?serial;
          }

          類似地,將payment打包為Docker鏡像后,通過docker compose進(jìn)行部署,如下所示

          #?Compose?版本
          version:?'3.8'

          #?定義Docker服務(wù)
          services:

          ??#?Web服務(wù)
          ??Payment-Service:
          ????image:?aaron1995/spring_boot_payment:1.0
          ????container_name:?Payment-Service
          ????ports:
          ??????-?"8015:8011"
          ????networks:
          ??????seata-service_seata_service_net:
          ????????ipv4_address:?120.120.120.51
          ????depends_on:
          ??????-?Payment-MySQL

          ??#?MySQL?服務(wù)
          ??Payment-MySQL:
          ????image:?mysql:5.7
          ????container_name:?Payment-MySQL
          ????ports:
          ??????-?"9308:3306"
          ????environment:
          ??????MYSQL_ROOT_PASSWORD:?12345
          ????networks:
          ??????seata-service_seata_service_net:
          ????????ipv4_address:?120.120.120.52

          #?定義網(wǎng)絡(luò)
          networks:
          ??#?聲明名為seata-service_seata_service_net的網(wǎng)絡(luò)是一個(gè)已存在的網(wǎng)絡(luò)
          ??seata-service_seata_service_net:
          ????external:?true

          最后,在payment服務(wù)所使用的數(shù)據(jù)庫Payment-MySQL容器上完成建庫建表操作。不僅包含業(yè)務(wù)表,也包含上文提到的undo_log表。如下所示,由于PaymentController3的test1方法的業(yè)務(wù)邏輯是更新id為1記錄,故這里也提前插入便于后續(xù)演示

          9885a93dbec9d42ebe66fe1ab64bc9b8.webp

          figure 13.jpeg

          測試驗(yàn)證

          現(xiàn)在各服務(wù)部署完成后,從Nacos頁面可以看到Seata Server、order、payment服務(wù)均已注冊上線

          25208bce34ba9fa6ab8467fab076d39f.webp

          figure 14.jpeg

          當(dāng)向order服務(wù)的接口發(fā)送HTTP請求時(shí),由于name不為Tony未拋出異常。order的表中新增了一條記錄。而payment表id為1的數(shù)據(jù)也被正確地更新了

          48edcfb38d99963076091ea4134928c7.webp

          figure 15.jpeg

          而當(dāng)HTTP請求的name參數(shù)為Tony時(shí),payment服務(wù)發(fā)生異常。不僅payment表未發(fā)生更新,而且order的表中也沒有新增數(shù)據(jù)。即被正常回滾

          f58e92c3d3994181e5104b3759cec4d8.webp

          figure 16.jpegNote
          • 在本次實(shí)踐過程中,發(fā)現(xiàn)通過Mybatis Plus Mapper內(nèi)置的insert方法進(jìn)行插入的數(shù)據(jù)在發(fā)生異常時(shí)無法進(jìn)行回滾,故在order服務(wù)中添加記錄是通過在相應(yīng)的xml文件自定義SQL實(shí)現(xiàn)的。后者在發(fā)生異常時(shí),可以對插入的數(shù)據(jù)進(jìn)行回滾
          瀏覽 41
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  手机在线免费观看欧美日 | 性爱网址色婷婷丁香五月 | 日韩五月天在线 | 天天干天天草 | 91久久夜色精品国产九色 |