开发者学堂课程【RocketMQ 知识精讲与项目实战(第三阶段):消息幂等性处理】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/704/detail/12457
消息幂等性处理
消息的幂等性指的是在消息的消费方对于同一条消息不论消费多少次结果都是一样的。这就是消息消费的幂等性。
其中有一个关键的点:消费方接收了很多次相同的消息这时候才有必要保证幂等性。
重复的消息是如何产生的?
一般来说有以下三种情况会产生重复的消息:
1、发送的时候发送重复的消息
如果生产者在给服务端发送消息的时候,服务端MQ接收到消息之后会给生产者做出响应。如果这时由于网络的闪断或者客户端突然宕机,就不会收到服务端对客户端的应答。这时生产者就会认为消息没有发送成功,就会再次发送这个消息。这样就会产生重复的消息。
2、消息投递时的重复
消息投递的时候对于rocketMQ来说主要指的是消费方在消费了这个消息之后由于网络的闪断或者自身的问题导致没有给rocketMQ做出正确的响应。这时rocketMQ就会尝试投递之前已经被处理过的消息,这时消费者就会收到两条内容相同的消息。因此在消息投递的时候也可能会出现消息的重复。
3、在负载均衡时消息的消费方是负载均衡,那么负载均衡的特点是不同的消费者消费不同的消息。如果这时消费者组当中的某一个消费的实例发生了变化。例如:突然间宕机,这种情况下都会触发组内所有实例的负载均衡。这时就会出现不同的消费者消费了相同的消息。
那么以上三种情况能否避免?
网络原因是不能避免的,还有一些意外的其他情况,包括消费者突发宕机,之后又自己重新启动了。这时是避免不了一些意外的情况的。
能够解决的是如果出现了消息的重复怎样保证幂等性。如果出现了消息的重复,需要保证消费一次或者多次,结果是一样的。
第一种手段:用消息ID去保证,因为之前说重复消息,那么消息的ID是一样的。但是这个地方需要慎重。因为rocketMQ不保证消息ID的唯一性。意思就是有可能不同的消息,但是消息ID是一样的。
那么用消息ID来保证幂等性可能会屏蔽其他的消息。所以消息ID不是很好的办法。
最好使用业务标识处理,在发送消息的时候给消息中设置一个业务KEY,这个消息在被投递到消费方的时候,消费方在拿到这个消息之后,通过业务KEY去判断消息有没有被处理。
Message message = new Message.
message.setKey("ORDERID_100");
SendResult sendResult
= producer. send (message) ;
如何判断?怎么知道消费了哪些?
可以在消费方把自己所消费过的消息去存起来。存起来时候在每一接收新信息的时候在处理之前,先从数据库中判断一下消息有没有包含业务KEY。如果包含了,直接舍弃即可。需要在消费方将消息进行存储。将处理过的消息存起来,这样的话就可以明确哪些消息处理过,哪些消息没有处理过。
小结:
消息的幂等性的意思。消息的幂等性指的是对于消费方来讲,接收到多个消息去消费的时候,消费一次和消费多次的结果是一样的。
这时分析了为什么会出现重复的消息。有三种情况会出现重复的消息:消息发送的时候由于网络的闪断或者是客户端发送者的宕机,没有及时的收到rocket响应的信息。这时就会再发一条信息出去。
投递的时候也会出现消费方如果出现了网络的异常,对于客户端来说没有及时收到消费方的应答也会出现重复的投递。
负载均衡也会出现重复的消息。如果出现了消费者组中的当前实例的变化,都会重新造成负载均衡的重来。这时就会造成不同的消费者对
一个消息消费了很多次。以上是消息重复的原因。
消息重复的情况是不可避免的,所以需要考虑的是在有重复消息的情况下怎么保证幂等性。
保证幂等性有一个关键就是在发送消息的时候会携带一个业务key,在接受到一个消息后先获得业务key,在本地消费方的数据库中判断业务key所对应的消息有没有消费过。如果没有消费过,那么就正常消费。消费完之后给数据库中存一下。如果已经消费过则直接舍弃即可。
以上是关于幂等性的内容。