前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >消息队列(2)--如何利用事务消息实现分布式事务

消息队列(2)--如何利用事务消息实现分布式事务

原创
作者头像
小时的棒棒糖
发布2023-10-03 10:35:52
3630
发布2023-10-03 10:35:52
举报

1.怎么使用事务消息实现分布式事务

消息队列中的“事务”,主要解决的是消息生产者和消息消费者的数据一致性问题

应用场景:订单系统下订单后,需要在购物车系统清空购物车

事务消息适用的场景主要是那些需要异步更新数据,并且对数据实时性要求不太高的场景。比如我们在开始时提到的那个例子,在创建订单后,如果出现短暂的几秒,购物车里的商品没有被及时清空,也不是完全不可接受的,只要最终购物车的数据和订单数据保持一致就可以了。

方案:

1.TCC 2PC 3PC Saga(强一致性,并发量不发的情况下使用,比如下订单和使用优惠券)

2.可以使用本地消息表实现最终一致性(可以短时间接受不一致,前提是:异步执行的部分不依赖资源)

3.使用支持事务的消息中间件 RocketMQ Kafka(本地消息表思想的一种实现,使用起来更简单)

具体以方案3事务消息实现分布式消息为例:

1.开启事务

2.发送半消息

3.成功后执行本地事务,创建订单

4.本地事务执行成功,则提交事务;本地事务执行失败,则回滚事务

细心的同学发现步骤4:如果本地事务执行成功,提交事务的时候,请求失败了,怎么办?或者本地事务执行失败,回滚事务的时候失败了,怎么办?

Kafka给出的方案:简单粗暴,直接报错,用户可以重试(针对本地事务成功的情况),要不回滚之前本地事务成功的那部分(针对本地事务失败的情况)

Kafka 的解决方案比较简单粗暴,直接抛出异常,让用户自行处理。我们可以在业务代码中反复重试提交,直到提交成功,或者删除之前创建的订单进行补偿。

RocketMQ提供的方案:

提供了反查机制,需要业务代码提供接口

为了支撑这个事务反查机制,我们的业务代码需要实现一个反查本地事务状态的接口,告知 RocketMQ 本地事务是成功还是失败。

在我们这个例子中,反查本地事务的逻辑也很简单,我们只要根据消息中的订单 ID,在订单库中查询这个订单是否存在即可,如果订单存在则返回成功,否则返回失败。RocketMQ 会自动根据事务反查的结果提交或者回滚事务消息。

2.怎么保证消息顺序消费?

单个消息队列可以保证消息的有序性

在一个主题下的多个队列(分区)保证有序性,需要提供算法,相同订单id发到指定的队列,消费者占有这个队列进行消费即可

如果说,你的业务必须要求全局严格顺序,就只能把消息队列数配置成 1,生产者和消费者也只能是一个实例,这样才能保证全局严格顺序。

大部分情况下,我们并不需要全局严格顺序,只要保证局部有序就可以满足要求了。比如,在传递账户流水记录的时候,只要保证每个账户的流水有序就可以了,不同账户之间的流水记录是不需要保证顺序的。

如果需要保证局部严格顺序,可以这样来实现。在发送端,我们使用账户 ID 作为 Key,采用一致性哈希算法计算出队列编号,指定队列来发送消息。一致性哈希算法可以保证,相同 Key 的消息总是发送到同一个队列上,这样可以保证相同 Key 的消息是严格有序的。如果不考虑队列扩容,也可以用队列数量取模的简单方法来计算队列编号。

我正在参与2023腾讯技术创作特训营第二期有奖征文,瓜分万元奖池和键盘手表

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.怎么使用事务消息实现分布式事务
  • 2.怎么保证消息顺序消费?
相关产品与服务
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com