【面试宝典】消息队列如何保证幂等性?

  |   0 评论   |   4,963 浏览

面试题:那么来说税如何保证消息队列的幂等性?

面试官心理剖析:
主要是看你对消息队列数据重复消费的问题,是否有了解,是否知道怎么解决?如果这块不知道,那么面试官会觉得如果交给你做功能,可能会出现多次消费的情况。

回答:

为什么会出现重复消费?
分析:
imagepng
如图,在什么场景会出现消息重复消费?比如说消费端已经消费了offset=2,offset=3,offset=4的三条数据,正准备把这个offset的值传给kafka,这时候消费端机器宕机了,这个数据没传过去;重启之后,消费端同步kafka,kafka那边消费的记录offset还是1,那么kafka会认为之前的2、3、4都没有消费过,会把这几个数据在传给消费端;这样消费端这边就重复对这几条数据进行消费了。在数据库里面可能就多了很多重复的数据。
像其他的MQ,也是一样,消费端再返回给MQ的时候,当机了或者重启了,那么都会出现重复消费的问题。

问题解决:

幂等性:一个请求,不管重复来多少次,结果是不会改变的。

每个消息都会有唯一的消息id。
1)、先查再保存
每次保存数据的时候,都先查一下,如果数据存在了那么就不保存。这个情况是并发不高的情况。

2)、业务表添加约束条件
如果你的数据库将来都不会分库分表,那么可以在业务表字段加上唯一约束条件(UNIQUE),这样相同的数据就不会保存为多份。

3)、添加消息表
再数据库里面,添加一张消息消费记录表,表字段加上唯一约束条件(UNIQUE),消费完之后就往表里插入一条数据。因为加了唯一约束条件,第二次保存的时候,mysql就会报错,就插入不进去;通过数据库可以限制重复消费。

4)、使用redis
如果你的系统是分布式的,又做了分库分表,那么可以使用redis来做记录,把消息id存在redis里,下次再有重复消息id在消费的时候,如果发现redis里面有了就不能进行消费。

5)、高并发下
如果你的系统并发很高,那么可以使用redis或者zookeeper的分布式对消息id加锁,然后使用上面的几个方法进行幂等性控制。

本文为博主原创文章,未经博主允许不得转载。

评论

发表评论