分布式事务 —— SpringCloud Alibaba Seata

打印 上一主题 下一主题

主题 986|帖子 986|积分 2958

Seata 简介

传统的单体应用中,业务操作使用同一条连接操作不同的数据表,一旦出现异常就可以整体回滚。随着公司的快速发展、业务需求的变化,单体应用被拆分成微服务应用,原来的单体应用被拆分成多个独立的微服务,分别使用独立的数据源,业务操作需要调用三个服务来完成。此时每个服务内部的数据一致性由本地事务来保证,但是全局的数据一致性问题无法保证。在微服务架构中,一次业务请求需要操作多个数据源或需要进行远程调用,就会产生分布式事务问题。
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务,Seata 为用户提供 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。AT 模式是 Seata 默认的工作模式,该模式是 XA 协议的演变。
关于分布式事务的知识可以参考:https://zhuanlan.zhihu.com/p/263555694

Seata 服务端

通过 https://github.com/seata/seata/releases 地址下载 Seata 安装包,本文使用的 Seata 版本是 seata-server-1.7.1
解压 seata-server-1.7.1 安装包,修改 conf/application.conf 文件
  1. server:
  2.   port: 7091
  3. spring:
  4.   application:
  5.     name: seata-server
  6. logging:
  7.   config: classpath:logback-spring.xml
  8.   file:
  9.     path: D:\seata-server-1.7.1\logs\seata
  10.   extend:
  11.     logstash-appender:
  12.       destination: 127.0.0.1:4560
  13.     kafka-appender:
  14.       bootstrap-servers: 127.0.0.1:9092
  15.       topic: logback_to_logstash
  16. console:
  17.   user:
  18.     username: seata
  19.     password: seata
  20. seata:
  21.   config:
  22.     # 使用nacos作为配置中心,seata将从nacos获取配置
  23.     type: nacos
  24.     nacos:
  25.       server-addr: 127.0.0.1:8848
  26.       namespace: 0178e474-2cfb-47c3-bded-da7cfa260f99
  27.       group: springcloud-project
  28.       data-id: seata-server.properties
  29.   registry:
  30.     # 使用nacos作为注册中心,seata将自身服务注册到nacos
  31.     type: nacos
  32.     nacos:
  33.       server-addr: 127.0.0.1:8848
  34.       namespace: 0178e474-2cfb-47c3-bded-da7cfa260f99
  35.       group: springcloud-project
  36.       application: seata-server
  37.       cluster: default
  38.   store:
  39.     # 存储模式:
  40.     # file模式为单机模式,全局事务会话信息内存中读写并持久化本地文件 rootdata,性能较高
  41.     # db模式为高可用模式,全局事务会话信息通过db共享,相应性能会差
  42.     # redis模式性能较高,存在事务信息丢失风险,需要提前配置适合当前场景的redis持久化配置
  43.     mode: file
  44. #  server:
  45. #    service-port: 8091 #If not configured, the default is '${server.port} + 1000'
  46.   security:
  47.     secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
  48.     tokenValidityInMilliseconds: 1800000
  49.     ignore:
  50.       urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login
复制代码
在 Nacos 控制台创建配置文件 seata-server.properties,注意分组和命名空间要与上述配置保持一致
具体配置项是从 script/config-center/config.txt 粘贴修改而来,这里只使用对我们有用的配置,主要是数据库配置信息
  1. #Transaction storage configuration, only for the server.
  2. store.mode=db
  3. store.lock.mode=db
  4. store.session.mode=db
  5. #These configurations are required if the `store mode` is `db`.
  6. store.db.datasource=druid
  7. store.db.dbType=mysql
  8. store.db.driverClassName=com.mysql.cj.jdbc.Driver
  9. store.db.url=jdbc:mysql://127.0.0.1:3306/test_db?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useAffectedRows=true
  10. store.db.user=root
  11. store.db.password=123
  12. store.db.minConn=5
  13. store.db.maxConn=30
  14. store.db.globalTable=global_table
  15. store.db.branchTable=branch_table
  16. store.db.distributedLockTable=distributed_lock
  17. store.db.queryLimit=100
  18. store.db.lockTable=lock_table
  19. store.db.maxWait=5000
复制代码
在上面配置的数据库内,执行 script/server/db 目录下的 sql 脚本,创建服务端所需的表
完成以后,即可进入 bin 目录使用脚本启动 Seata

Seata 客户端

为客户端微服务添加依赖
  1. <dependency>
  2.     <groupId>com.alibaba.cloud</groupId>
  3.     <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
  4. </dependency>
复制代码
配置文件添加如下配置
  1. seata:
  2.   enabled: true
  3.   tx-service-group: test-seata-group # 自定义事务组名称,需要与下面service.vgroup-mapping中的一个映射保持一致
  4.   service:
  5.     vgroup-mapping:
  6.       test-seata-group: default
  7.   registry:
  8.     type: nacos
  9.     nacos:
  10.       server-addr: 127.0.0.1:8847/nacos
  11.       namespace: 0178e474-2cfb-47c3-bded-da7cfa260f99
  12.       group: springcloud-project
  13.       application: seata-server
复制代码
Seata 默认使用 AT 模式,该模式需求每个客户端库内都存在一张 undo_log 表,用于回滚事务时临时记录数据
  1. CREATE TABLE `undo_log` (
  2.   `id` bigint(20) NOT NULL AUTO_INCREMENT,
  3.   `branch_id` bigint(20) NOT NULL,
  4.   `xid` varchar(100) NOT NULL,
  5.   `context` varchar(128) NOT NULL,
  6.   `rollback_info` longblob NOT NULL,
  7.   `log_status` int(11) NOT NULL,
  8.   `log_created` datetime NOT NULL,
  9.   `log_modified` datetime NOT NULL,
  10.   `ext` varchar(100) DEFAULT NULL,
  11.   PRIMARY KEY (`id`),
  12.   UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
  13. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
复制代码
在需要使用分布式事务的方法上添加注解 @GlobalTransactional,当方法内发生异常时,就可以带动所调用微服务进行回滚
  1. @GlobalTransactional
  2. public void create(Order order) {
  3.     log.info("下单开始");
  4.     orderDao.create(order);
  5.     log.info("下单结束");
  6.     log.info("开始扣减余额");
  7.     server02FeignClient.accountIncrUsed(order.getUserId(), order.getMoney());
  8.     log.info("扣减余额结束");
  9.     log.info("开始扣减库存");
  10.     server03FeignClient.storageIncrUsed(order.getProductId(), order.getCount());
  11.     log.info("扣减库存结束");
  12.     log.info("开始修改订单状态");
  13.     orderDao.updateStatus(1, order.getId());
  14.     log.info("修改订单状态结束");
  15. }
复制代码
配置完成,启动服务,即可开始测试


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

笑看天下无敌手

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表