突破Java面试-如何保证消息消费时的幂等性?

举报
JavaEdge 发表于 2021/06/04 02:42:04 2021/06/04
2.2k+ 0 0
【摘要】 消费消息需要考虑: 会不会重复消费能不能避免重复消费重复消费了也别造成系统异常可以吗 使用MQ如何保证幂等性也是架构设计考虑的问题。 rabbitmq、rocketmq、kafka,都可能会出现消费重复消费,因为这个问题不是MQ自身保证的,是我们开发自己需要保证的。 何时重复消费? kafka有个offset概念,每个消息写进去,都有一个offset,代表他的...

消费消息需要考虑:

  • 会不会重复消费
  • 能不能避免重复消费
  • 重复消费了也别造成系统异常可以吗

使用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的唯一键保证重复数据不会重复插入多条。

文章来源: javaedge.blog.csdn.net,作者:JavaEdge.,版权归原作者所有,如需转载,请联系作者。

原文链接:javaedge.blog.csdn.net/article/details/90203760

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。