网站首页 > 博客文章 正文
作者:lazasha
来源:
https://blog.csdn.net/lazasha/article/details/86739783
目录
- CAP原则
- Rocket mq实现思路
- Rabbit mq实现思路
- 需要考虑的问题
- 后记
严格的来说,消息中间件并不能实现分布式事务,而是通过事后补偿机制,达到和分布式事务一样的数据一致性。这里主要探讨Rocket mq 和 Rabbit mq的实现思路。Rocket mq只描述一下实现思路,Rabbit mq会有代码演示。还是那句话,由于水平有限,难免有不当或者错误之处,请大家指正,谢谢。
CAP原则
首先我们得了解CAP原则,又称CAP原理,指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得 。
- 一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
- 可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
- 分区容错性(P):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。
在分布式存储系统中,最多只能实现上面的两点。而由于当前的网络硬件肯定会出现延迟丢包等问题,所以分区容错性是我们必须需要实现的。所以我们只能在一致性和可用性之间进行权衡,没有系统能同时保证这三点。
我的理解,使用mq实现最终补偿事务一致性,是牺牲了同意时刻访问同一份数据的一致性,通过一段时间的延迟,最终达到一致性。
Rocket mq实现思路
首先推荐事务和消息解耦的方式。
- 开始事务,Prepared消息,RocketMQ会返回消息地址
- 执行本地事务
- 事务提交成功,通过拿到的消息地址去修改RocketMQ里面修改消息的状态,消息从Prepared变为发送成功;如果事务失败,则通过消息地址去修改消息状态,变为消息取消。
- 消息消费方居于Push或者Pull方式消费消息成功后,向服务器发送消费成功的消息通知。
所以,在事务内需要向mq提交两次消息请求,一次是发送,另外一次是确认(确认成功或者取消)。
如果确认消息发送失败了,RocketMQ会定期扫描消息集群中的事务消息,这时候发现了Prepared消息,它会向消息发送者确认,所以消息生产方需要实现一个check接口,RocketMQ会根据发送端设置的策略来决定是回滚还是继续发送确认消息。这样就保证了消息发送与本地事务同时成功或同时失败。
- 优点:实现了最终一致性,不需要依赖本地数据库事务。
- 缺点:实现难度大,主流MQ不支持,没有.NET客户端,RocketMQ事务消息部分代码也未开源
- 极端情况下仍然需要手工介入
Rabbit mq实现思路
和Rocket mq有所不一样。
消息生产方:
- 首先执行本地事务,写消息表
- 获取消息表的消息记录,向Rabbit mq发送消息
- 接收Rabbit mq返回的消息确认接收成功通知(ACK),更新消息表;如果失败,则不更新,保证发送消息和记录表状态一致。
这个会存在这样一个问题:消息已经发送成功,但是Rabbit mq没有返回,则无法更新消息表;或者接收到消息成功发送通知,但是更新数据库失败,也无法更新消息表,导致下一次重复发送。解决这个问题的思路,我只想到需要消息接收方要做幂等性检查,从而避免重复消费消息。
消息接收方:
- Rabbit mq通知有消息
- 消息接收方接收消息,处理成功或者失败,都要返回确认ACK, Rabbit mq接收到ACK,根据ACK更新消息状态为已经发送,删除队列中的消息;或者更改消息列,等待从新发送。
这里有个问题,如果消息接收方成功处理消息,但是由于特殊情况没有返回ACK, Rabbit mq没有接收到ACK,这条消息状态已经改变不会再发送,需要手工处理。
消息发送方代码示例:
配置:
消息接收方代码示例:
配置:
最需要考虑的两个问题:
- 消息消费的顺序问题:发送消息指定队列,消息消费者指定队列可以解决,消费者只能一个。
- 消息消费的重复问题:每次消费消息时候创建一消息表,在消费消息前先查询该表,如果消息存在就说明已经消费。
后记
对于Rocket mq实现的很多细节,大家可以参考官方网站的文档,这里写的比较粗。写博客很累,主要是没有经验,又担心有的地方理解错误,误导大家。出现问题,有的时候需要去从源码哪里找到答案。幸好我的博客只记录我的心得,没有任何其他的目的,聊以自慰吧。
猜你喜欢
- 2025-07-21 开源|一款类excel报表设计系统,支持拖拽式和word模板设计
- 2025-07-21 SpringBoot利用ThreadPoolTaskExecutor批量插入百万级数据实测!
- 2025-07-21 云端藏经阁:一款开源、精美、可独立部署的知识管理神器
- 2025-07-21 电商秒杀/库存扣减:基于JUC的并发控制实战案例
- 2025-07-21 简单易用的.NET免费开源RabbitMQ操作组件EasyNetQ
- 2025-07-21 亿级分库分表,如何丝滑扩容、如何双写灰度
- 2025-07-21 【RocketMQ】消息的拉取(rocketmq消息大小)
- 2025-07-21 RocketMQ消息消费-客户端拉取消息前的准备工作
- 2025-07-21 RocketMQ消费限流的几种方式(rocketmq并发消费与顺序消费)
- 2025-07-21 Spring Boot 3 中如何整合 RocketMQ 实现消息队列处理
你 发表评论:
欢迎- 07-21谷歌云发生全球范围大规模宕机(谷歌云什么时候上线的)
- 07-21谷歌云全球崩盘!OpenAI Shopify瘫痪,万亿级服务为何一夜失灵?
- 07-21国泰君安:谷歌云的利润率大超预期,AI投资的回报正逐步显现
- 07-21谷歌云技术故障引发全球互联网服务大瘫痪
- 07-21谷歌发生长达数小时云服务宕机事件,全球超70项谷歌云服务停止正常运行!谷歌致歉并发布事故报告
- 07-21开源|一款类excel报表设计系统,支持拖拽式和word模板设计
- 07-21SpringBoot利用ThreadPoolTaskExecutor批量插入百万级数据实测!
- 07-21云端藏经阁:一款开源、精美、可独立部署的知识管理神器
- 最近发表
-
- 谷歌云发生全球范围大规模宕机(谷歌云什么时候上线的)
- 谷歌云全球崩盘!OpenAI Shopify瘫痪,万亿级服务为何一夜失灵?
- 国泰君安:谷歌云的利润率大超预期,AI投资的回报正逐步显现
- 谷歌云技术故障引发全球互联网服务大瘫痪
- 谷歌发生长达数小时云服务宕机事件,全球超70项谷歌云服务停止正常运行!谷歌致歉并发布事故报告
- 开源|一款类excel报表设计系统,支持拖拽式和word模板设计
- SpringBoot利用ThreadPoolTaskExecutor批量插入百万级数据实测!
- 云端藏经阁:一款开源、精美、可独立部署的知识管理神器
- 电商秒杀/库存扣减:基于JUC的并发控制实战案例
- 简单易用的.NET免费开源RabbitMQ操作组件EasyNetQ
- 标签列表
-
- ifneq (61)
- 字符串长度在线 (61)
- googlecloud (64)
- flutterrun (59)
- 系统设计图 (58)
- powershellfor (73)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- qcombobox样式表 (68)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)