消息被重复消费?----- 消息队列踩坑系列

如何保证消息不被重复消费,或者说如何保证消息幂等性。

rbbitmq,rocketmq,kafka,都有可能出现消息重复消费的情况,以kafka来说
kafka实际上有个offset的概念,就是每个消息写进去,都有一个offset,代表的消息的序号,然后consumer消费了数据之后,每隔一段时间(定期定时),会把自己消费过的offset提交一下,表示“我已经消费过了,下次重启之后,还是从上次消费到的offset来继续消费。

如果遇到意外情况,还没来得及提交offset,进程就被杀掉了,重启之后,可能有些消息要重复消费一次。

实例;

数据1/2/3依次进入kafka,kafka会给这三条数据分配一个offset,代表这条数据的序号,假设分配的offset依次是152/153/154。消费者从kafka去消费的时候,也是按照这个顺序去消费的,假如当消费者消费了 offset= 153这条数据,刚准备提交offset到zookpeeper,此时消费者进程被重启了,那么此时消费过的数据1/2的offset并没有提交,kafka也就不知道你已经消费了offset=153,这条数据,那么重启之后,消费者会找kafka说,嘿,哥们儿,你给我接着把上次我消费的那个地方的数据继续给我传递进来,由于之前的offset没有提交成功,那么数据1/2数据会再次传进来,如果此时消费者没有去重的话,会导致重复消费。
在这里插入图片描述

如果消费者是拿一条数据就往数据库里写一条,会可能你把1/2数据在数据库里面插入了两次,数据就错了。

重复消费不可拍,重要的是你要考虑重复消费之后怎么保证消息的幂等性。
幂等性,通俗的说,就一个数据,或者一个请求,给你重复来多次,你的确保对应的数据是不会改变的,不能出错。

如何保证消息队列消息的幂等性?

具体思路:
  • 比如你拿个数据要写库,你先根据主键检查一下,如果这数据都有了,update一下就好了。

  • 比如你写入redis,那没问题了,反着每次都是set,天然幂等性

  • 如果你不是上面两个场景,你需要让生产者发送每条数据的时候,里面加一个全局唯一的id,类似订单id之类的东西,然后你这里消费到了之后,先根据id去比如redis(数据库)查一下,之前消费过了吗,如果没有消费,就处理,然后写入reids或者库中,如果消费过了,就不要处理了。

  • 比如基于数据库的唯一健来保证重复数据不会插入多条,因为有唯一健约束,重复数据插入只会报错,不会导致数据库出现脏数据
    在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值