分布式事务管理

分布式事务管理
有一个业务操作包含了服务A、服务B、服务C的三个操作,当且仅当三个事务的操作都成功,算该业务场景成功完成。否则需要进行回滚。
解决方案:
基于XA协议的两阶段提交
XA是一个分布式事务协议。XA中大致分为两部分:事务管理器和本地资源管理器。其中本地资源管理器往往是由数据库实现的,如Oracle、DB2这些商业数据库都实现了XA接口,而事务管理器作为全局的调度者,负责各个本地资源的提交和回滚。
优点:XA协议比较简单,而且一旦商业数据库实现XA协议,使用分布式的成本也比价低。
缺点:性能不理想,特别是在交易下单链路,往往并发量很高,XA无法满足高并发场景。
消息事务+最终一致
所谓的消息事务就是基于消息中间件的两个阶段提交,本质是对消息中间件的一种特殊利用,它是将本地事务和发送消息放在了一个分布式事务里,保证要么本地操作成功并且对外发消息成功,要么两者都失败,开源的的RocketMQ(Alibaba)就支持一致性。该方案采用最终一致的,牺牲了一致性,换来性能的大幅度提升。存在造成数据不一致的风险。
TCC编程模式
所谓TCC编程模式,也是两阶段提交的一个变种。TCC提供了一个编程框架,将整个业务逻辑分为三块:Try、Confirm和Cancel三个操作。以在线下单为例:Try阶段回去扣库存,Confirm阶段则是去更新订单状态,如果更新订单失败,则进入Cancel阶段,会去恢复库存。总之,TCC就是通过代码【人为】实现两阶段提交,不同的业务场景所写的代码都不一样,复杂对也不一样,因此,这种模式并不能很好的被复用。

具体实现:
LCN:LCN分布式事务框架的核心功能是对本地事务的协调控制,框架本身并不创建事务,实施对本地事务做协调控制。因此该框架与其他第三方的框架兼容性强,支持所有的关系型数据库事务,支持多源数据,支持与第三方数据库框架一块使用(例如sharding-jdbc),在使用框架的时候只需要添加分布式事务的注解即可,对业务的入侵低。LCN框架主要是为微服务框架提供分布式事务的支持,在微服务框架上做了进一步的事务优化,在一些负载场景上LCN事务机制要比本地事务机制的性能更好,4.0以后框架开发了插件机制可以让更多的滴单方框架支持进来。
以上是在他处看到的内容,用于知识点扫盲。
个人总结一下:分布式事务,无论是MQ保证最终一致性,还是依靠某种协议。还是基于Spring对数据库的事务控制。通过其他业务逻辑的控制(MQ和TCC都可以理解为业务逻辑,并没有涉及新的技术,就是在业务上有更加严谨的思维模式)。
就现在自己即将接触到的技术以及业界内使用比较多的,对Rocket MQ的事务消息,做一个更深入的学习(只看应用,不讲原理)。
概念扫盲:
Topic:Topic是生产者在发送消息和消费者在拉取消息的类别。Topic与生产者和消费者之间的关系非常松散。具体来说,一个Topic可能有0个或则和多个生产者向它发送消息;相反,一个生产这可以发送不同类型的Topic的消息。类似的,消费者组可以订阅一个或多个主题,只要该组的实例保持其订阅一致即可。
Tag:标签,换句话的意思就是子主题,为用户提供了额外的灵活性。有了标签,来自同一业务模块的具有不同目的的消息可以具有相同的主题和不同的标记。标签有助于保持代码的清晰和连贯,同时标签也可以方便RocketMQ提供的查询功能。
GroupName:和现实世界中一样,RocketMQ中也有组的概念。代表具有相同角色的生产者组合或者消费者组合。称为生产者组或消费者组。作用是在集群HA的情况下,一个生产者挂掉之后,本地事务回滚后,可以继续联系该组下的另外一个生产者实例,不至于导致业务走不下去。在消费者组中,可以实现消费者的负载均衡和消息容错目标。另外,有了GroupName,在集群下,动态扩展容量很方便。只需要在新加的机器中,配置相同的GroupName。启动后,就立即能加入到所在群组中,参与消息生产或消费。
producer通过broker集群提供的各种负载均衡策略将消息发送到broker集群中,发送过程支持快速失败是低延迟的。consumer支持集群和消息广播。提供实时的消息订阅机制,能够满足大多数消费者的需求。
为了确保不会丢失发布成功的消息,RocketMQ提供了同步和异步两种复制方式来增强消息的可靠性与高看我用性。
以下内容从阿里云指导文档摘录:
事务消息
概念介绍
●事务消息:消息队列MQ提供类似X/Open XA 的分布式事务功能,通过消息队列MQ事务消息能达到分布式事务的最终一致;
●半事务消息:暂不能投递的消息,发送方已经成功地将消息发送到消息队列MQ服务端,但是服务端未收到生产者对消息的二次确认,此时该消息被标记成"暂不能投递"状态,处于该中状态下的消息即半事务消息;
●消息回查:由于网络闪断、生产者应用重启等原因,导致某条事务消息的二次确认丢失,消息队列MQ服务通过扫描发现某条消息长期处"半事务消息"时,需要主动向消息生产者询问该消息的最终状态(Commit或是Rollback),该询问过程即消息回查。
事务消息交互流程图
事务消息发送步骤:
1.发送方将半事务消息发送至消息队列MQ服务端;
2.消息队列MQ服务端将消息持久化成功之后,向发送方返回Ack确认消息已经发送成功,此时消息为半事务消息;
3.发送方开始执行本地事务逻辑;
4.发送方根据本地事务执行结果向服务端提交二次确认(Commit或是Rollback),服务端收到Commit状态则将半事务消息标记为可投递,订阅方最终将受到该消息;服务端收到Rollback状态则删除半事务消息,订阅方将不会接受该消息。
事务消息回查步骤:
1.在断网或者应用重启的特殊情况下,上述步骤4提交的二次确认最终未到达服务端,经过固定时间后服务端将对该消息发起消息回查;
2.发送方收到消息回查后,需要检查对应消息的本地事务执行最最终结果;
3.发送方根据检查得到本地事务的最终状态再次提交二次确认,服务端任按照步骤4对半事务消息进行操作。
注意事项:
1.事务消息的Group ID不能与其他类型消息的Group ID共用。与其他类型的消息不同,事务消息有回查机制,回查时消息队列MQ服务端会根据Group ID去查询客户端。
2.通过ONSFactory.createTransactionProducer创建事务消息的时必须指定LocalTransactionChecker 的实现类,处理异常情况下事务消息的回查;
3.事务消息发送完成本地事务后,可在execute方法中返回一下三种状态:
⭕TransactionStatus.CommitTransaction:事务提交,允许订阅方消费该消息;
⭕TransactionStatus.RollbackTransaction:回滚事务,消息将被丢弃不允许消费;
⭕TransactionStatus.Unknow:暂时无法判断状态,等待固定时间以后消息队列MQ服务端向发送方进行消息回查。
4.可以通过一下方式给每条消息设定第一次消息回查的最快时间:

 Message message = new Message();
 // 在消息属性中添加第一次消息回查的最快时间,单位秒。例如,以下设置实际第一次回查时间为 120 秒 ~ 125 秒之间
 message.putUserProperties(PropertyKeyConst.CheckImmunityTimeInSeconds,"120");
// 以上方式只确定事务消息的第一次回查的最快时间,实际回查时间向后浮动 0 秒 ~ 5 秒;如第一次回查后事务仍未提交,后续每隔 5 秒回查一次

未完待续

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值