首页 > 其他分享 >可重入锁思想,设计MQ迁移方案

可重入锁思想,设计MQ迁移方案

时间:2024-07-02 21:20:40浏览次数:11  
标签:重入 消费 场景 MQ 消息 切量 迁移 ID

image

如果你的MQ消息要从Kafka切换到RocketMQ且不停机,怎么做?在让这个MQ消息调用第三方发奖接口,但无幂等字段又怎么处理?今天小傅哥就给大家分享一个关于MQ消息在这样的场景中的处理手段。

这是一种比较特例的场景,需要保证切换的MQ消息不被两端同时消费,并且还需要在一段消费失败后的MQ还可以继续重试。并且这一端消费的MQ消息,也要保证自身的幂等。

我们知道一般通用场景下,MQ消息都会有一个业务唯一ID值,用于接收方做仿重处理。但除此之外还应该有一个MQ消息本身的ID,这个ID也要全局唯一,每一条消息都要有一个ID,这是因为MQ是可能重复发送的(发送MQ成功,但获取MQ发送结果响应超时或更新库表消息状态失败,则重复发送),如果没有消息的唯一ID也就没法确保是哪一条消息了。

这个ID可以用于;唯一标识、去重、链路追踪、幂等性、事务以及安装性等,但可能有些伙伴在做MQ消息发送的时候,是容易忽略而没有在MQ中添加这个ID,或者随意用时间戳来当ID用,这样都是不合理的。会影响一些场景的代码健壮性设计。

需求背景描述好了,接下来,我们看看这样的场景怎么设计。

1. 场景问题

将原本使用 Kafka 的MQ方式,迁移到 RocketMQ,同时部分场景的 MQ 消息调用三方接口是没有幂等字段的,需要做好程序兼容处理。

2. 场景思考

首先我们要知道在分布式架构下,我们每做的技术方案都要考虑顺序性和临界状态。像是MQ的生产和消费都是多套应用实例部署的,那么生产端发送出来的MQ消息到不同的队列中也是有延迟和存放顺序以及拉取消费不同的情况。如;生产端发送MQ为A、B、C、D,但到Kafka/RocketMQ以及不同的消费端拉取时,不一定是A、B、C、D的顺序,那么直接做切量开关,是可能导致一个A消息在Kafka队列中消费完,点击切换开关(一种切量哈希计算手段,如消息{A}哈希值最后两位当做百分比用),正好RocketMQ也会把A消费掉。这样同一个消息就被重复消费了。

3. 方案设计

在整个方案设计中,我们要考虑几个非常重要的点。如图:

image

  • 一个是切换的两端MQ消费是抢占式加锁,避免重复消费。这是因为切量开关,切换过程中,两个消息队列中的MQ并不是顺序可靠的,可能存在重复消费,所以要加分布式锁。

  • 一段MQ消费失败要进行重试,但这个时候不能在消费失败后删分布式锁,因为MQ消费都是很快的,可能导致删锁后另外一端MQ进行了相同的消费。那可能有些伙伴会说,那也没关系呀,反正失败的这段没有消费成功。当往往失败并不一定是直接的结果失败,可能是网络失败,可能是超时失败等。也就是实际成功了,但超时反馈了。所以不能被其他端重复消费,并且要保证自己这一端消费失败后可重试。所以这块要设计可重入锁,也就是 setnx 加锁的值,为自身一段的 mq 类型,这样自己在接收mq消息以后,检查锁为自身加锁值可重试。这样也就保证了一端消费重试,不会让另外一端把MQ也跟着消费掉,因为setnx存在,并且有加锁值判断,所以不能进入。

  • 另外MQ消息还可能存在同一个MQ发送多次的场景,这个是非常正常的。比如,你再发送MQ的时候,超时网络抖动失败(1万次会有1次),那么就会补偿重发。但这个MQ已经发送过了,所以会接收2条MQ消息。那么在消费的时候,不能让2个MQ消息都进入消费中,因为多台实例消费,可能都去调用发奖了。那么这里还需要给MQ的ID进行幂等加锁。确保一个MQ消息,失败后,顺序轮训重试。也就保证了,发奖的过程中不会出现超发奖品。大部分三方接口还是有幂等字段的,有的话会更好。

  • 另外还有2个开关,一个是消费开关,一个是切量开关。消费开关要在整个新的MQ改造工程工程全部上线后开启,但还要被切量开关限定消费。开启后,切量开关才会生效。切量是一种哈希值的百分比比对,比如一个哈希值最后两位是10,那么切量配置小于等于10%则这个MQ则可以被切量后消费,另外一段则不消费这个MQ。

  • 另外,为了方便测试线上功能,还会加入白名单。不过大部分时候这类东西会用通用组件能力解决。

这样的场景方案设计,是非常值得积累的,同类的思想也可以帮我们解决很多共性问题。

标签:重入,消费,场景,MQ,消息,切量,迁移,ID
From: https://www.cnblogs.com/xw-01/p/18269823

相关文章

  • SpringAMQP
    快速入门在之前的案例中,我们都是经过交换机发送消息到队列,不过有时候为了测试方便,我们也可以直接向队列发送消息,跳过交换机。在入门案例中,我们就演示这样的简单模型,如图:也就是:publisher直接发送消息到队列消费者监听并处理队列中的消息:::warning注意:这种模式一般测试使......
  • RabbitMQ数据隔离
    1.用户管理点击Admin选项卡,首先会看到RabbitMQ控制台的用户管理界面:这里的用户都是RabbitMQ的管理或运维人员。目前只有安装RabbitMQ时添加的itheima这个用户。仔细观察用户表格中的字段,如下:Name:itheima,也就是用户名Tags:administrator,说明itheima用户是超级管理员,拥有所有......
  • DELL 服务器迁移数据恢复
    服务器数据恢复环境:一台DELL服务器,共有6块SAS硬盘,组成的Raid5,操作系统是Windows2008的。迁移目标服务器与原服务器配置型号完全相同。由于用户操作系统存在特殊软件,需要进行整体迁移。Dell服务器数据迁移流程:1.使用Winhex进行系统克隆,关闭源服务器和目标服务器电源,将源服务......
  • 2024RabbitMQ面试题
    1、为什么使用消息队列?        其实就是问问你消息队列都有哪些使用场景,然后你项目里具体是什么场景,说说你在这个场景里用消息队列是什么?        面试官问你这个问题,期望的一个回答是说,你们公司有个什么业务场景,这个业务场景有个什么技术挑战,如果不用MQ......
  • 将硬件的三轴传感器和可燃气体传感器和 AIR780E 数据打包至 EMQX 服务器
    localmqtt_host="www.visionexpand.com.cn"localmqtt_port=1883localmqtt_isssl=falselocalclient_id="emqx"localpub_topic="$thing/up/property/IQMPOB8BI9/temp/humi"localsub_topic="mqtt"localuart2_da......
  • Rabbit mq - 等待 Mnesia 表时出错
    集群节点关闭和启动如果关闭了集群中的所有节点,则需要确保在启动的时候最后关闭的那个节点是第一个启动。如果第一个启动的不是最后关闭的节点,那么这个节点会等待最后关闭的节点的启动。这个等待时间是30秒,如果没有等到,那么这个先启动的节点也会失败。会有重试机制,默认重试20......
  • RocketMQ 基础教程-高级功能汇总
    作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬学习必须往深处挖,挖的越深,基础越扎实!阶段1、深入多线程阶段2、深入多线程设计模式阶段3、深入juc源码解析阶段4、深入jdk其余源码解析......
  • RocketMQ 基础教程-RocketMQ整合SpringBoot
    作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬学习必须往深处挖,挖的越深,基础越扎实!阶段1、深入多线程阶段2、深入多线程设计模式阶段3、深入juc源码解析阶段4、深入jdk其余源码解析......
  • 达梦数据库迁移常见语法问题
    数据库迁移常见语法问题DM数据库常见语法差异一.Sql文语法1.杀进程语法select*fromv$lock;select*fromsysobjects;--(查询对象信息)select*fromv$sessions;--(查询会话信息)--上述3条语句组合一下就能查出哪张表上的某种锁是由哪个会话里的操作加上的--查哪张表上......
  • 在C#中使用RabbitMQ做个简单的发送邮件小项目
    在C#中使用RabbitMQ做个简单的发送邮件小项目前言好久没有做项目了,这次做一个发送邮件的小项目。发邮件是一个比较耗时的操作,之前在我的个人博客里面回复评论和友链申请是会通过发送邮件来通知对方的,不过当时只是简单的进行了异步操作。那么这次来使用RabbitMQ去统一发送邮件,我......