写点什么

如何保证消息消费时的幂等性?

作者:JavaEdge
  • 2022 年 1 月 14 日
  • 本文字数:734 字

    阅读完需:约 2 分钟

如何保证消息消费时的幂等性?

消费消息需要考虑:


  • 会不会重复消费

  • 能不能避免重复消费

  • 重复消费了也别造成系统异常可以吗


使用 MQ 如何保证幂等性也是架构设计考虑的问题。


rabbitmq、rocketmq、kafka,都可能会出现消费重复消费,因为这个问题不是 MQ 自身保证的,是我们开发自己需要保证的。

何时重复消费?

kafka 有个 offset 概念,每个消息写进去,都有一个 offset,代表他的序号,然后 consumer 消费了消息后,每隔一段时间,会把自己消费过的消息的 offset 提交一下,代表我已经消费过了,下次我要是重启啥的,你就让我继续从上次消费到的 offset 来继续消费。


但凡事有意外,比如重启系统,碰到急的,直接 kill 进程再重启。这会导致 consumer 有些消息处理了,但是没来得及提交 offset。重启之后,少数消息会再次消费。


其实重复消费不可怕,可怕的是你没考虑到重复消费之后,如何保证幂等性


比如你有个系统,消费一条往 DB 插一条,要是你一个消息重复两次,你不就插入两条,这数据不就错了?但你要是消费到第二次时,自己判断一下已消费了,直接扔了,不就只保留了一条数据!


一条数据重复出现两次,DB 里就只有一条数据,这就保证了系统的幂等性。


幂等性,就一个数据或一个请求,给你重复来多次,你得确保对应的数据是不会改变的,不能出错。


所以

怎么保证消息队列消费的幂等性?

还是得结合业务来思考,大体思路如下:


  • 写 DB,你先根据主键查一下,如果这数据都有了,你就别插入了,update 之

  • 写 redis,那没问题了,反正每次都是 set,天然幂等

  • 其它场景,你需要让生产者发送每条消息时,里面加一个全局唯一 id,然后你这里消费到了之后,先根据这个 id 去 redis 查一下,之前消费过吗?

  • 如果没有消费过你就处理,然后这个 id 写 redis

  • 如果消费过了那你就别处理了,保证别重复处理相同的消息


还有比如基于 DB 的唯一键保证重复数据不会重复插入多条。

发布于: 刚刚阅读数: 2
用户头像

JavaEdge

关注

正在征服世界的 Javaer。 2019.09.25 加入

曾就职于百度、携程、华为等大厂,阿里云开发者社区专家博主、腾讯云+社区2019、2020年度最佳作者、慕课网认证作者、CSDN博客专家,简书优秀创作者兼《程序员》专题管理员,牛客网著有《Java源码面试解析指南》。

评论

发布
暂无评论
如何保证消息消费时的幂等性?