MQ消息幂等
介绍
MQ中的消息可靠性主要靠两个方面实现:
- 消息落地
- 消息超时,重传,确认
整个消息体系由发送端、服务端、存储设施、接收端四块结构构成。
为保证消息的可达性,超时、重传、确认机制可能导致消息总线、或者业务方 收到重复的消息,从而对业务产生影响。
上半场幂等设计
消息发送的上半场就是图中的1、2、3过程,表示了消息的发送,保存过程。
如果3丢失,发送端MQ-client超时后会重发消息,可能导致服务端MQ-server收到重复消息。
这里的重新发送方是Client,而不是实际的业务发送方。
此时重发是MQ-client发起的,消息的处理是MQ-server,为了避免步骤2落地重复的消息,对每条消息, MQ系统内部必须生成一个msgId,作为去重和幂等的依据。
这个msgId的规则必须是:
全局唯一
MQ生成,具备业务无关性,对消息发送方和消息接收方屏蔽
有了这个msgId,就能保证上半场重发,也只有1条消息落到MQ-server的DB中,实现上半场幂等。
而业务方收到发送失败而重新发送的消息,对mq而言,会被认为是不同的消息(一条新的消息),只是这条重新发送的消息和上一条内容一样而已,这条重新发送的消息,会生成新的msgId。
下半场幂等设计
消息消费的下半场就是图中的4、5、6过程,表示消息的投递,消费过程。
接收端MQ-client回ACK给服务端MQ-server,是消息消费业务方的主动调用行为,不能由MQ-client自动发起,因为MQ系统不知道消费方什么时候真正消费成功。
如果5丢失,服务端MQ-server超时后会重发消息,可能导致MQ-client收到重复的消息,这样有可能造成重复消费。
此时重发是MQ-server发起的,消息的处理是消息消费业务方,消息重发势必导致业务方重复消费,为了保证业务幂等性 ,业务消息体中,必须有一个biz-id,作为去重和幂等的依据。
这个biz-id的规则是:
- 对于同一个业务场景,全局唯一
- 由业务消息发送方生成,业务相关,对MQ透明
- 由业务消息消费方负责判重,以保证幂等
有了这个业务ID,才能够保证下半场消息消费业务方即使收到重复消息,也只有1条消息被消费,保证了幂等。
总结
上半场
MQ-client生成inner-msg-id,保证上半场幂等。
这个ID全局唯一,业务无关,由MQ保证。
下半场
业务 发送方带入biz-id,业务 接收方去重保证幂等。
这个ID对单业务唯一,业务相关,对MQ透明。
结论
幂等性,不仅对MQ有要求,对业务上下游也有要求。
实际上,MQ只实现了自己内部的幂等性,对于业务的幂等性,消息重投之类的,MQ并没有做处理,业务的幂等性,需要自己手动实现。