34 | 分布式事务:使用 Nacos+Seata 实现AT模式
Seata AT 底层原理
- 深入了解
- 翻译
- 解释
- 总结
Seata AT方案通过Nacos和Seata的结合,实现了无侵入式的编程体验,为分布式事务提供了高效的解决方案。文章首先介绍了Seata AT的底层原理,包括TC、TM和RM三个重要角色,以及业务流程的两个阶段执行。其核心在于undo_log表的记录回滚日志,实现了一阶段和二阶段的独立本地事务执行,以及异步化的全局事务提交和回滚。接着,文章通过实际业务模型展示了Seata AT的底层原理,以及在微服务项目改造中的应用。通过添加依赖项、声明数据源代理和添加Seata配置项,读者能够了解如何在微服务中实现Seata AT的解决方案。整体而言,本文通过清晰的解释和实际案例,帮助读者快速了解了Seata AT方案的技术特点和应用方法。 Seata的配置项定义在application.yml文件中,分为上下两部分,一部分在spring.cloud.alibaba节点下面,它指定了当前应用的事务分组;另一部分在根节点seata下面,定义了连接Seata Server的方式。在项目启动的时候,Seata框架会尝试从Nacos获取Seata Server的地址信息,执行这个操作的类是NacosRegistryServiceImpl。在开启Seata分布式事务的时候,你必须把异常抛出到全局事务的发起方,让@GlobalTransactional注解的方法能够感知到这个异常,才能顺利触发事务的回滚。 文章还展示了一个删除券模板的分布式事务用例,通过@GlobalTransactional注解开启分布式事务,展示了全局事务的回滚操作。最后,文章提出了对Seata AT方案的思考,建议在本地业务非常简单的情况下,不必引入Seata,而是使用传统的事务型消息+日志补偿+跑批补偿的方式。整体而言,本文对Seata AT方案进行了全面的介绍和应用案例展示,为读者提供了深入了解分布式事务解决方案的机会。
《Spring Cloud 微服务项目实战》,新⼈⾸单¥59
全部留言(14)
- 最新
- 精选
- 药味怎么理解"传统的事务型消息 + 日志补偿 + 跑批补偿的方式"
作者回复: 使用MQ的事务消息模式 + 事务日志表记录执行状态 + batch job扫表做反向补偿。最经济实惠的方法
2022-03-02512 - 奔跑的蚂蚁大佬,能加个餐 详情说下 传统的方式嘛,最好再说点rocketMq
作者回复: 传统的方式其实就是利用MQ的事务型消息,或者整一个事务表控制执行状态(有的干脆就直接在业务表上记状态也成),再加一个batch job定时跑批补偿。没啥高端的货
2022-03-0245 - 奔跑的蚂蚁今天用seata 遇到一个问题,没有配置代理数据源 好像也能使用,请问下老师 这个和配置数据源在使用上有什么区别嘛
作者回复: 同学发现了一个小机关,没错,这个是在0.9版里的一个改进,不用再显示的声明,seata框架会在背后把datasource放到proxy里。我在课程里把这一步单独拿了出来手动操作,主要是想让大家对seata底层的工作原理,即数据源代理,有一个直观一些的认识
2022-03-154 - peter请教老师几个问题啊: Q1:undo_log问题: A undo_log是文件还是数据库的表?从文中看,似乎是数据库的表。B 如果是表的话,该表由seata框架自己创建并维护,不需要开发人员维护,对吗? Q2:RM是怎么监测到业务代码的DB操作的? 既然seata AT方案是无感知的,那seata框架又是怎么知道业务代码做了哪些DB操作? Q3:阶段二回滚的时候,RM 无法获取本地锁,它会原地打转不停重试。一直处于这个状态吗?这样岂不是相当于死机了? Q4:阶段一,每个本地事务会提交或回滚吗? 每个本地事务不都是在阶段二执行提交或回滚吗? Q5:能否单独讲一讲"“传统的事务型消息 + 日志补偿 + 跑批补偿的方式”? 比如以加餐形式写一章?
作者回复: 1. 数据库表,seata框架做CRUD 2. 通过GlobalTransactional注解和datasource拦截器 3. 不会,因为当前业务在二阶段了,一定已经持有了全局锁。另一个拿到本地锁的业务会因为无法获取全局锁而回滚,进而释放本地锁 4. 回滚是二阶段异步执行
2022-03-0223 - Geek_eabafe姚老师,阶段二是全局事务的 Commit 和 Rollback 是异步执行。 1. 这里的异步执行是指哪里异步呢? 2. 如果异步执行失败了 TC 仍认为整个事务已经结束了吗? 如果是这样 肯定有脏数据的
作者回复: 1. 异步简单来说,就是一旦服务被认为应该rollback,那么框架不会使用“阻塞式”的方式来执行rollback,而是异步去通过seata记录的rollback info来做回滚,上层调用方的体验是“fast fail” 2. 是的,框架不能100%保证一致性,总会有很特例的情况,就像早期TCC框架在蚂蚁应用的时候,这些个团队每天来了就要处理各种悬挂问题。因此从seata协调器和框架层面做各种error handling的同时,使用告警机制通知人工介入仍然是一个兜底策略
2024-01-11归属地:北京 - Amy老师,请教下几个问题 1.RM执行第一阶段完成,是不是可以理解为对于mysql来说已经执行了commit,只是在undo_log表中记录了回滚的数据,第二阶段依赖这个数据对数据进行还原 2.基于问题1,如果RM1执行了一个update操作,比如把id=1的姓名从张三更新了李四,那RM2,第一阶段还没执行完,此时有其他的业务B去查id=1的数据,取出的名字是李四,然后RM2执行失败,触发了RM1的回滚操作,这个时候业务B查的不就是错误数据了吗
作者回复: 没错,一阶段commit其实已经提交了happy flow里的业务数据,并记录rollback上下文。问题二,分布式方案要在可用性和一致性之间做取舍,如果一定要保证一致性那么就是类似重量级xa方案,那么seata相当于牺牲了一部分一致性换来了可用性的提升。 针对你说的这个问题,在写阶段由于全局锁本地锁的机制在,不会出现对同一条记录的并发修改。但读的业务里,你就要考虑这个业务对一致性的容忍程度是多少,如果要将读来的数据做任何写操作且不一致性低容忍,那么通常做法就是业务层做日志表,代替框架的lock机制,或者最终修改的时候sql update里做版本控制(version字段)
2023-05-16归属地:北京 - Q老师customer调template卡流程了,脑壳痛 template服务启动一直报 ERROR [coupon-template-serv,,] 21120 --- [ main] i.s.c.r.netty.NettyClientChannelManager : no available service 'null' found, 这个错 customer调template的时候报这个错Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: Unable to commit against JDBC Connection; nested exception is org.hibernate.TransactionException: Unable to commit against JDBC Connection] with root cause,我查了下是jpa和seata在强数据库资源,
作者回复: 看上去可能是seata锁占用的问题,同学你打开seata的日志,如果是global/local锁竞争应该有相关error log打印出来,盯紧Rollback关键字,看一下报错的具体error是什么
2022-06-25 - 西门吹牛本地锁该如何理解呢?
作者回复: 本地锁可以理解为当前微服务对应的后台DB中,该次请求所操作的对象上的锁,生命周期绑定本地事务
2022-06-02 - 天天有吃的请问下,阶段二是全局事务的 Commit 和 Rollback 是异步执行。这里的异步执行是指哪里异步呢?2023-11-09归属地:广东
- 天天有吃的这个图中,tm也是rm吗2023-11-09归属地:广东