【RocketMQ系列】RocketMQ一条消息被多台机器消费问题

本文讲述了在重构项目中遇到的消息重复消费问题,分析了由于网络抖动导致MQ消息被同一topic和消费者消费两次的情况。提出了通过Redis实现幂等性校验的解决方案,以避免对用户体验的影响。同时强调了检查服务连接情况和幂等性设计的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

业务背景

重构项目,在测试环境联调,发布到一台服务器上启动。在app上触发一条消息到mq topic A,然后我这边消费消息,将消息通过微信推送给用户。

问题描述

触发消息后,结果却在1s内收到了两次微信通知,并且回执和库中却都收到了两条记录。

但是在服务器上面查找日志时只收到了其中的一次请求。

原因分析

触发了一条,却发了两条。百思不得其解?

于是就想到了其中一个方案,停了服务器上的服务后,再次触发,发现还会触发微信消息。那就说明有一台服务在跑。怎么找到这台服务?

想到mq监控台页面可以看到是哪些ip在连接。然后就通过对应的topic和消费者,直接查找到连接的实例ip。

果不其然,有个同事在20多分钟前本地启动了重构前的服务。而测试环境和本地的mq连接并没有隔离,并且重构前后的topic和消费者是一样的。

所以mq又被另一台消费了一次。

但是同一个topic和消费者,为什么会被消费两次呢?

RocketMQ提供了ack机制,以保证消息能够被正常消费。发送者为了保证消息肯定消费成功,只有使用方明确表示消费成功,RocketMQ才会认为消息消费成功。中途断电,抛出异常等都不会认为成功——即都会重新投递。

经过分析发现:

这条消息先是被本地的服务给消费到了,但是本地的网络和服务器是比较卡的。

相当于网络是不稳定的,那么mq就没有收到成功的返回,那它就会重新发送到另外一台服务上了。

消息会被重复消费,那对客户的体验是很不好的。所以,幂等性校验还是很有必要的。

解决办法

RocketMQ不解决消息重复推送问题。所以需要自己处理。

  1. 每次消费数据,将唯一标识放入redis,key为唯一标识,value为incr自增。

    过期时间设置在60s。

    然后消费时看redis是否存在。

    注意点:用redis的set和get时都做好分布式锁

  2. 可以用消息表做去重幂等操作:设置唯一索引,如果重复就不处理;

目前选择的是第一种。没有选择第二种的原因是:每天消费的数据量非常大,但重复消息的概率又非常低,如果直接操作表的话,会对系统的吞吐量有影响。

复盘

  • 一个接口/服务被调用了两次,这台服务上没有,那么就要考虑是否有另一台在调用。

  • 如何看到连接情况:直接通过界面上消费者来查看;

  • MQ会因网络抖动的情况出现消息重复消费的问题,所以要做好幂等校验;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值