[{"createTime":1735734952000,"id":1,"img":"hwy_ms_500_252.jpeg","link":"https://activity.huaweicloud.com/cps.html?fromacct=261f35b6-af54-4511-a2ca-910fa15905d1&utm_source=V1g3MDY4NTY=&utm_medium=cps&utm_campaign=201905","name":"华为云秒杀","status":9,"txt":"华为云38元秒杀","type":1,"updateTime":1735747411000,"userId":3},{"createTime":1736173885000,"id":2,"img":"txy_480_300.png","link":"https://cloud.tencent.com/act/cps/redirect?redirect=1077&cps_key=edb15096bfff75effaaa8c8bb66138bd&from=console","name":"腾讯云秒杀","status":9,"txt":"腾讯云限量秒杀","type":1,"updateTime":1736173885000,"userId":3},{"createTime":1736177492000,"id":3,"img":"aly_251_140.png","link":"https://www.aliyun.com/minisite/goods?userCode=pwp8kmv3","memo":"","name":"阿里云","status":9,"txt":"阿里云2折起","type":1,"updateTime":1736177492000,"userId":3},{"createTime":1735660800000,"id":4,"img":"vultr_560_300.png","link":"https://www.vultr.com/?ref=9603742-8H","name":"Vultr","status":9,"txt":"Vultr送$100","type":1,"updateTime":1735660800000,"userId":3},{"createTime":1735660800000,"id":5,"img":"jdy_663_320.jpg","link":"https://3.cn/2ay1-e5t","name":"京东云","status":9,"txt":"京东云特惠专区","type":1,"updateTime":1735660800000,"userId":3},{"createTime":1735660800000,"id":6,"img":"new_ads.png","link":"https://www.iodraw.com/ads","name":"发布广告","status":9,"txt":"发布广告","type":1,"updateTime":1735660800000,"userId":3},{"createTime":1735660800000,"id":7,"img":"yun_910_50.png","link":"https://activity.huaweicloud.com/discount_area_v5/index.html?fromacct=261f35b6-af54-4511-a2ca-910fa15905d1&utm_source=aXhpYW95YW5nOA===&utm_medium=cps&utm_campaign=201905","name":"底部","status":9,"txt":"高性能云服务器2折起","type":2,"updateTime":1735660800000,"userId":3}]
<>1 前言
在使用单个服务,多数据源时,也存在分布式事务问题。
当单体系统需要访问多个数据库(实例)时就会产生分布式事务。 比如:用户信
息和订单信息分别在两个MySQL实例存储,用户管理系统删除用户信息,需要分别删除用户信息及用户的订单信
息,由于数据分布在不同的数据实例,需要通过不同的数据库链接去操作数据,此时产生分布式事务。 简言之:跨数据库实例产生分布式事务。
<>2 问题场景
参考此文档搭建一个多数据源项目Mybatis-Plus入门系列(19) -多数据源使用详解。
在插入订单数据时,模拟一个异常:
@Override @DS("db_order") @Transactional public void insertOrder() { // 插入订单
OrderTbl orderTbl = new OrderTbl(); orderTbl.setUserId("12"); orderTbl.
setCommodityCode("IPHONE 13"); orderTbl.setCount(1); orderTblMapper.insert(
orderTbl); int i = 5 / 0; }
当进行业务操作时,订单发生异常 ,进行了回滚操作,因为在不同的数据库实例中,余额却扣除成功,此时发现数据不一致问题。
<>3 使用Seata 解决多数据源事务问题
<>3.1 集成Nacos Seata
参考该系列,给当前服务添加Nacos Seata 相关依赖,并启动Nacos Seata 。
<>3.2 多数据源集成Seata
多数据源集成Seata 时,主要是需要修改一下几个配置即可。
多数据源中,开启分布式事务,设置事务模式:
datasource: # 多数据源 dynamic: # 省略其他 # 开启分布式事务 seata: true # 事务模式 为AT seata-mode:
AT
seata 中,关闭数据源自动代理
seata: # 是否开启spring-boot自动装配,默认true,包括数据源的自动代理以及GlobalTransactionScanner初始化
enabled: true # 是否开启数据源自动代理,默认开启 enable-auto-data-source-proxy: false
<>3.3 测试
添加@GlobalTransactional注解。
@GlobalTransactional @GetMapping("/test") public Object test() throws
InterruptedException { accountTblService.reduceMoney(); orderTblService.
insertOrder(); return "执行完毕!"; }
测试发现,异常时,余额和订单服务都进行了回滚,集成成功。