前言 在微服务项目中,分布式事务也是我们需要处理的问题之一。在涉及到服务间相互调用的过程中,例如A服务调用B服务,在A服务调用B服务成功之后,A服务出现异常导致事务回滚,这个时候B服务已经调用成功,B服务的事务是不会回滚的,那么毫无疑问B服务中执行的增删改操作会导致最终B服务数据库中出现脏数据,从而导致业务出错。上述服务间相互调用出现的问题就是我们要使用分布式事务的原因,我们要保证A服务在出现异常回滚的时候,利用分布式事务的补偿机制使B服务的事务在异常情况下也可以回滚。本节我们主要使用alibaba开源的分布式事务组件seata实现分布式事务的控制,Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。(官方说明,请参考官方文档地址https://seata.io/zh-cn/docs/overview/what-is-seata.html)另外使用Seata处理分布式事务要慎重,仅适合在并发量不是很高的场景中,在高并发服务中,我们一般使用MQ消息中间键的方案实现分布式事务处理。
正文
- Seata安装
①使用docker方式安装Seata服务
命令:docker run --name seata-server -p 8091:8091 --restart=always -d seataio/seata-server:latest
文章图片
- 整合Seata
①manager和member微服务pom中引入seata依赖结语 ok,关于seata分布式事务的实战到这里就结束了,我们下期见。。。
com.alibaba.cloud spring-cloud-starter-alibaba-seata2.2.5.RELEASE
文章图片
文章图片
ps:注意引入的seata版本要和Seata服务版本一致
②配置seata
#====================================Seata Config=============================================== seata: enabled: true application-id: ${spring.application.name} tx-service-group: ${spring.application.name}-seata-service-group # 事务群组(可以每个应用独立取名,也可以使用相同的名字) client: rm-report-success-enable: true rm-table-meta-check-enable: false # 自动刷新缓存中的表结构(默认false) rm-report-retry-count: 5 # 一阶段结果上报TC重试次数(默认5) rm-async-commit-buffer-limit: 10000 # 异步提交缓存队列长度(默认10000) rm: lock: lock-retry-internal: 10 # 校验或占用全局锁重试间隔(默认10ms) lock-retry-times: 30 # 校验或占用全局锁重试次数(默认30) lock-retry-policy-branch-rollback-on-conflict: true # 分支事务与其它全局回滚事务冲突时锁策略(优先释放本地锁让回滚成功) tm-commit-retry-count: 3 # 一阶段全局提交结果上报TC重试次数(默认1次,建议大于1) tm-rollback-retry-count: 3 # 一阶段全局回滚结果上报TC重试次数(默认1次,建议大于1) undo: undo-data-validation: true # 二阶段回滚镜像校验(默认true开启) undo-log-serialization: jackson # undo序列化方式(默认jackson) undo-log-table: undo_log# 自定义undo表名(默认undo_log) log: exceptionRate: 100 # 日志异常输出概率(默认100) support: spring: datasource-autoproxy: true service: enable-degrade: false # 降级开关 disable-global-transaction: false # 禁用全局事务(默认false) grouplist: default: 192.168.23.134:8091 vgroup-mapping: aiyundun-manager-seata-service-group: default # TC 集群(必须与seata-server保持一致) transport: shutdown: wait: 3 thread-factory: boss-thread-prefix: NettyBoss worker-thread-prefix: NettyServerNIOWorker server-executor-thread-prefix: NettyServerBizHandler share-boss-worker: false client-selector-thread-prefix: NettyClientSelector client-selector-thread-size: 1 client-worker-thread-prefix: NettyClientWorkerThread type: TCP server: NIO heartbeat: true serialization: seata compressor: none enable-client-batch-send-request: true # 客户端事务消息请求是否批量合并发送(默认true) registry: file: name: file.conf type: file config: file: name: file.conf type: file
文章图片
文章图片
ps:seata的配置可以使用file、nacos、zk等方式,为了简便演示这里我们使用file方式,其它方式请参考官方文档。
【Springcloud|(九)SpringCloud系列——分布式事务seata整合实战】③创建分布式事务表
说明:在manager和member微服务的数据库中分别创建一个undo_log表,用于分布式事务的管理。
CREATE TABLE `undo_log`( `id` bigint(0) NOT NULL AUTO_INCREMENT, `branch_id` bigint(0) NOT NULL, `xid` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `context` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `rollback_info` longblob NOT NULL, `log_status` int(0) NOT NULL, `log_created` datetime(0) NOT NULL, `log_modified` datetime(0) NOT NULL, `ext` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'seata事务控制表' ROW_FORMAT = Dynamic;
文章图片
④编写测试方法
说明:在A服务上加上全局事务注解@GlobalTransactional,A服务是一个保存数据的服务,B服务是通过openfeign远程保存数据的服务,这俩个服务可根据自身业务自行定义,验证当异常发生时B服务是否也会出现事务回滚。
文章图片
⑤验证
A服务出现异常回滚
文章图片
B服务也回滚
文章图片
查看数据库,manager和member微服务都没有新增数据成功,说明分布式事务生效,实现了分布式事务的回滚。
推荐阅读
- SpringCloud技术专题「Feign」从源码层面让你认识Feign工作流程和运作机制
- Spring Cloud 升级之路 - 2020.0.x - 5. 理解 NamedContextF
- Spring Cloud 升级之路 - 2020.0.x - 7. 使用 Spring Cloud
- 保护亿万数据安全,Spring有“声明式事务”绝招
- 万字长文(SpringCloud gateway入门学习&实践)
- 从内部类内部访问局部变量,需要将其声明为final(java)
- Spring Bean定义的加载解析过程之注解的过程
- 如何在Android中使用JSCH(SFTP)将文件上传到服务器
- 如何显示使用JSCH(SFTP)Android进行上传和下载的进度