消息队列经典面试问题(三)

415 阅读2分钟

常见面试问题

  • 如何保证消息不会被重复消费(保证消息的幂等性)

什么叫做消息的幂等性

幂等:在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。

消息的幂等性:就是即使多次收到了消息,也不会重复消费。所以保证消息的幂等性就是保证消息不会重复消费,这在开发中是很重要的。比如客户点击付款,如果点击了多次,那也只能扣一次费。

问题产生的原因

我们常使用的rabbitmq、rocketmq、kafka这些消息队列中间件都有可能出现消息的重复发送,这个mq是无法保证的,例如生产者重复发送消息mq(生产者把消息发送给MQ之后,MQ收到消息在给生产者返回ack的时候,网络中断了)、mq重复发送消息给消费者(消费者从MQ中拉取消息进行消费,当消费者已经消费了消息但还没向MQ返回ack的时候,消费者宕机或者网络断开了。)。

  • kafka重复消费场景:kafka中有个offset的概念,就是每个消息写入队列都一个offset,代表它的序号,然后consumer消费了数据之后,每隔一段数据,会把自己消费过的消息offset提交一下代表我已经消费过了,那问题就来了,比如有时候意外情况,你需要重启系统,着急一点直接kill进程再重启,这样就会导致consumer有些消息处理了,但是还没来的及提交offset,那重启后少数消息还是会重复消费。

如何解决

其实重复消费并不可怕,可怕的是没有考虑消息的幂等性,那我们怎么解决重复消费呢?其实想想也很简单。

1、利用redis set 保证幂等性,每个消息都生成一个唯一的id,才进行业务处理前,利用set sadd操作来判断消息是否有被消费过。

2、利用数据库的主键,如果数据存在就更新不插入了。