TM:事务管理器(事务发起者) TC事务协调器
两阶段方式(TPC)
一阶段:协调器问“你们几个子事务参与者对应的活能不能干成?” 子事务参与者们一一回复“能干/干不成”
二阶段:协调器问根据子事务参与者们的反馈如果都能干则告诉所有人都去干吧,如果有人说干不了,特通知大家别干了
一般的实现形式:所有的事务一阶段执行sql不提交 ,都成功之后TC通知所有事务进行二阶段主动提交,如果有一个失败TC通知所有事务进行二阶段回滚
例如:一般可以简单的自己写一个, seata-AT模式可以算两阶段模式的进阶演变
TCC
try阶段所有参与者进行尝试提交业务(eg:创建订单的订单状态是CREATING,减库存虽然进行了100-2=98,但是会记录本次有2个冻结中的库存,等类似try操作);Confirm阶段 如果try阶段的执行都成功了则TM通知所有参与者执行真正的提交(eg:创建订单的订单状态改为CREATED,减库存 被冻结的2个库存直接删掉,等类似Confirm操作【因为用网络超时等原因可能会有重复的调用所有要求支持幂等性】);cancel阶段 如果try中有一个执行失败则TM通知所有参与者进行补偿操作(eg:创建订单的订单状态改为CANCELED,减库存中被冻结的2重新加回到数据库中,等类似cancel操作【因为用网络超时等原因可能会有重复的调用所有要求支持幂等性】);
对于有些TCC的实现框架为了防止在Confirm和cancel出现异常(一般try成功了后续的操作不易失败,并且后续的Confirm和cancel支持幂等性失败了可以重复调用),若最终还是失败还会做一些log日志,此时可以报警待人工介入;
实现TCC框架:Hmily、seata的TCC模式
下边图是try失败走cancel的流程
MQ
实现可靠消息最终一致性方案:流程如下参考
其中可靠性消息服务如何确定可靠性:
可靠点1.如果步骤一失败,上游直接能感知就不必后续操作了直接抛异常
可靠点2.如果步骤四失败了,那么可靠性消息服务会定期询问状态长期为待确认的“老哥,你上游的事务成功了还是失败了?”成功变为已发送并投递消息,失败变为删除消息
可靠点3.因为已发送就意味着投递消息成功,二者需在一个事务中,要成功一起成功,若失败了也会有可靠点2保证下次还会执行
可靠点4.若可靠性消息服务发现长期处于已发送的消息,会尝试重新投递消息到MQ,所以下游的事务一定要支持幂等性操作
阿里开源的 RocketMQ(将可靠消息服务跟MQ融合,提供事务消息),就实现了可靠消息服务的所有功能,核心思想跟上面类似,只不过 RocketMQ 为了保证高并发、高可用、高性能,做了较为复杂的架构实现,非常的优秀
这种基于消息队列的可靠消息最终一致性方案优缺点:
优点:支持多个下游事务的异步操作
缺点:单向无法回滚,如果上游成功必须保证最终的都执行成功
例如:RocketMQ
saga框架模式
与TCC相比他没有try的操作,每个Saga由一系列sub-transaction Ti 组成每个Ti 都有对应的补偿动作Ci,补偿动作用于撤销Ti造成的结果,可以看到和TCC相比,saga没有“预留”动作,它的Ti就是直接提交到库。
例如:seata-saga模式