微服务-分布式事务-seata-消息队列
2024-12-04 10:26:39 0 举报
分布式事务seata,原理、方案
作者其他创作
大纲/内容
可靠消息最终一致性方案
校验状态
3.4步骤=写隔离避免了脏写
TC 配置下 注册中心、配置中心 启动即可
2-2 发送到消息队列
高并发,吞度量高
cancel
业务系统 + 事务消息队列
try()confirm()cancel()
TC (T coordinator)事务协调者,协调事务
3 执行本地业务executeLocalTransaction
1 发送预消息 half msg
第一阶段
默认16次后进入死信队列
TC
yes
源码方法spring boot方法。找spring.factories从 日志 中 看执行流程。全局去搜 关键字。
支付服务
1 执行业务数据2 回滚日志记录提交本地事务(1和2)释放资源
事务控制表
分布式事务1
提交(删除日志)回滚(依据日志记录回滚)
分布式事务2
TM
事务2获取到全局锁,才成继续执行3.4.5.6.7的步骤
1.获取本地锁(锁一段代码或者sql)(本地的) 2.执行sql 3.获取全局锁(同一事务所有服务的) 4.提交本地事务 5.释放本地锁
只有4 才可以被后面的服务消费掉
MQ
seata-server\\seata\\conf
AT
发消息
2- 注册分支事务
2 返回发送结果
启动RocketMQ 两个命令
最大努力通知应用场景:我方调用第三方:应用在第三方系统中调用第三方开发:属于第三方开放平台1. 尽最大可能通知2. 你来找我要
3-1 消费消息
try(){ 啥也不干;}confirm(){ +100;}cancel(){ 啥也不干;}也可做冻结处理
4-a 发送确认消息
支付db
RM
支持事务消息的MQRocketMQ
@seatacontroller(){ rm1 (别的服务) (请求里面:xid(全局锁id)、branchid(本地锁id)) rm2 (别的服务)}
TCC的各种问题
yes or no
5- confirm or cancel
1-3 成功 ,发送a、确认消息失败、发送b、取消消息
6.全局提交7.释放全局锁
执行空操作
本地锁+ 全局锁的使用
主要是开发三方用的(类似支付宝,微信支付等)
1-1-1保存消息为待确认
no
调用另一个RM
1-1 发送待确认消息
消费消息
5 回查checkLocalTransaction
一个分布式全局事务
4-1 回查消息状态
正常流程
try的记录、事件初始化
2-1 (1-3请求)更改消息状态已确认、已取消
TM:事务发起者(也是RM,因为是事务的发起的RM)
4-2 返回消息状态
启动RocketMQ的界面
half msg 后面服务是消费不到的
3-4 更改消息状态为已完成
3- 执行try
定时任务:如果长时间都是待确认状态,回查
请求
到账100
Seata
是否为空
第二阶段
seata下载http://seata.io/zh-cn/blog/download.htmldb脚本https://github.com/seata/seata/tree/1.2.0/script
RM资源管理者,每个参与事务的微服务
如何回滚:事务1调用另一个RM失败需要回滚,但是之前的本地锁已经被释放,由另一个线程的事务2获取到了本地锁,事务2此时获取到了本地锁正在等待获取全局锁进行提交,但是全局锁被事务1占着。事务2多次获取全局锁 超时 失败后,回滚,释放本地锁。事务1获取到本地锁,然后回滚。
相当于LCN中的TM
1-2 操作数据,执行业务逻辑
事务隔离级别:读未提交、读已提交、可重复读、串行化造成的问题:脏读、不可重复读、幻读=========================锁粒度 跨服务
重复读取等待获取全局锁
可靠消息服务db(本地事务表)
悬挂cancel在try之前解决办法:cancel的时候,新增一条记录(如果原来没有记录,执行空方法,再插入已回滚记录,当在try执行的时候,发现有记录,空try)加事务控制表 { tx_id(全局事务id) branch_id(本地事务分支id) 状态(1(事务初始化)、2(已提交)、3(已回滚))}
TCC
TM、RM 中需要添加的配置下面两个配置,不配置也行,走默认8091。
转账100
空
4-b 发送回滚
6 回查结果 commit、rollback
TCC业务场景不支持数据库事务的情况,比如redis,mango等
try,confirm,cancel 中独立事务。通过业务回滚。此时不用undo.log表了。tcc场景:(!(支持acid事务的关系型数据库) 和 xxx )。
异常
3-3 ack
两个线程(2个分布式事务):进入一个controller的同一个方法,sql一样
4- 提交或回滚
1- 开启全局事务
事务开始Try
RocketMQ
db
seata-server-db
元子操作
1.获取本地锁(锁一段代码或者sql)(本地的) 2.执行sql ===========================
已回滚状态、幂等
订单服务
不为空
可靠消息服务自行开发
幂等多次执行confirm 或 cancel解决办法:加事务控制表 { tx_id(全局事务id) branch_id(本地事务分支id) 状态(1(事务初始化)、2(已提交)、3(已回滚))}
日志记录参考
3-2 执行业务逻辑
执行空回滚,插入回滚事件控制记录
回查:定时任务去扫描half msg(长时间没有被确认的消息)加入一个事务表,回查只需要查事务表
业务处理和发消息,在一个事务中
业务系统
try(){ -100 提交入库;(冻结) 冻结字段 ,余额}confirm(){ 啥也不干; 冻结字段清空,删掉了100}cancel(){ +100; 冻结字段清空,删掉了100,余额中+100}
原余额1000元冻结字段, 余额100 900
AT:有数据库参与 需要sql事务支持1.释放本地资源2.全局提交时,删除日志记录
已提交
SEATA读隔离:只代理了 select for update如:事务1正在操作某条数据,事务2 读取这条数据如果使用 select * from 表名 允许事务2读取如果使用 select * from 表名 for update 不允许事务2读取 (牺牲性能,强制一致性 比如:金额操作)
处理高并发的分布式事务:1. 消息队列 + 本地事务表 (通过定时任务保证)2. 业务系统 + 事务消息队列 (通过事务消息保证)3. 可靠服务消息
seata支持的事务模式:AT、TCC、SAGA、XA
空回滚try未执行,cancel执行 (try由于某个原因超时了,导致cancel先执行了)解决办法:加事务控制表 { tx_id(全局事务id) branch_id(本地事务分支id) 状态(1(事务初始化)、2(已提交)、3(已回滚))}
为空、悬挂
0 条评论
下一页