如何保证消息消费时的幂等性?
消费消息需要考虑:
会不会重复消费
能不能避免重复消费
重复消费了也别造成系统异常可以吗
使用 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 的唯一键保证重复数据不会重复插入多条。
版权声明: 本文为 InfoQ 作者【JavaEdge】的原创文章。
原文链接:【http://xie.infoq.cn/article/b0d718ee6c0edceb21e03db25】。文章转载请联系作者。
评论