1、什么是消息的幂等性
幂等:在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。这是百度百科给出的幂等的概念。

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

2、MQ的幂等性如何保证
我们所熟悉的RabbitMQ、RocketMQ、kafka,都有可能出现消息的重复发送,这个是MQ无法保障的。但是我们又不能在系统中去重复消费消息,那么就需要我们开发人员去保证消息的幂等性。

2.1 MQ出现非幂等性的情况
2.1.1 生成者重复发送消息给MQ
       生成者把消息发送给MQ之后,MQ收到消息在给生产者返回ack的时候,网络中断了。这时MQ明明已经接收到了消息,但是生产者没接收到确定消息,就会认为MQ没有接收到消息。因此,在网络重新连接后,生产者会把已经发送的消息再次发送到MQ,如果MQ没有去重措施的话,那么就接收到了重复的消息。

2.1.2 MQ重复发送消息给消费者
       消费者从MQ中拉取消息进行消费,当消费者已经消费了消息但还没向MQ返回ack的时候,消费者宕机或者网络断开了。所以消费者成功消费了消息的情况,MQ并不知道。当消费者重启或网络重连后,消费者再次去请求MQ拉取消息的时候,MQ会把已经消费的消息再次发送给消费者,如果消费者没有去重就直接消费,那么就会造成重复消费的情况。便会造成数据的不一致。

2.1.3 Kafka重复消费的场景


2.2 保证消息幂等性的办法
2.2.1 生成者不重复发送消息到MQ
       mq内部可以为每条消息生成一个全局唯一、与业务无关的消息id,当mq接收到消息时,会先根据该id判断消息是否重复发送,mq再决定是否接收该消息。

2.2.2 消费者不重复消费
        消费者怎么保证不重复消费的关键在于消费者端做控制,因为MQ不能保证不重复发送消息,所以应该在消费者端控制:即使MQ重复发送了消息,消费者拿到了消息之后,要判断是否已经消费过,如果已经消费,直接丢弃。所以根据实际业务情况,有下面几种方式:

1、如果从MQ拿到数据是要存到数据库,那么可以根据数据创建唯一约束,这样的话,同样的数据从MQ发送过来之后,当插入数据库的时候,会报违反唯一约束,不会插入成功的。(或者可以先查一次,是否在数据库中已经保存了,如果能查到,那就直接丢弃就好了)。

2、让生产者发送消息时,每条消息加一个全局的唯一id,然后消费时,将该id保存到redis里面。消费时先去redis里面查一下有么有,没有再消费。(其实原理跟第一点差不多)。

3、如果拿到的数据是直接放到redis的set中的话,那就不用考虑了,因为set集合就是自动有去重的。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐