当前位置: 首页 > 科技观察

MQ,如何保证消息的幂等性?

时间:2023-03-11 22:46:08 科技观察

MQ的核心架构是什么?MQ核心架构由发送方、服务器、固化存储、接收方四部分组成。MQ如何确保消息被传递?必须传递MQ消息。架构中有两个核心设计点:消息落地;消息超时、重传、确认;画外音:详见核心架构中的步骤1-6。MQ消息重传,会不会造成消息重复?有可能的。为了保证消息的可达性,超时、重传、确认机制可能会导致MQ或者业务方收到重复的消息,从而影响业务。举个例子:购买会员卡时,上游支付系统负责向用户扣款,下游系统负责发卡给用户,通过MQ异步通知。是前半段的ACK丢失,导致MQ收到重复的消息,还是后半段的ACK丢失,导致购卡系统收到重复的购卡通知,可能会出现上游扣了一次钱,以及下游发了多张牌。.为了避免对业务造成影响,MQ是如何保证幂等性的呢?MQ的幂等性由两部分组成:MQ发送端,到MQ-server的幂等性(上半部分);MQ-server,到MQreceiver端的幂等性(下半部分);如何保证消息发送前半部分的幂等性?MQ消息发送的前半部分,即上图中的1-3:发送端MQ-client向服务端MQ-server发送消息;服务器MQ-server向地面发送消息;服务器MQ-server向发送方MQ-client返回ACK;如果3丢失,发送方MQ-client会在超时后重新发送消息,这可能会导致服务端MQ-server收到重复的消息信息。此时重传由MQ-client发起,消息处理由MQ-server负责。为了避免步骤2中的重复消息,对于每条消息,在MQ系统内部都要生成一个inner-msg-id作为去重和取幂等待的基础,这个内部消息ID的特点是:全局唯一;MQ生成,与业务无关,屏蔽消息发送者和消息接收者;有了这个inner-msg-id,就可以保证前半部分的重传,只有一条消息落入MQ-server的DB,实现了前半部分的幂等性。消息发送的后半部分,如何保证幂等性?MQ消息发送的后半部分,即上图中的4-6:服务端MQ-server向接收端MQ-client发送消息;接收端MQ-client向server返回ACK;服务器MQ-server删除登陆消息;需要强调的是,接收端MQ-client向服务端MQ-server返回ACK,是消息消费业务方的主动调用行为,不能由MQ-client自动发起,因为我的MQ系统不才知道消费者什么时候才能真正消费成功。如果5丢失,服务端MQ-server超时后会重新发送消息,可能会导致MQ-client收到重复的消息。此时重传由MQ-server发起,消息处理由消息消费者业务方负责。消息的重传必然导致业务方的重复消费(上例中的一次支付,重复发卡)。为了保证业务的幂等性,业务消息体中,必须有一个biz-id作为去重和幂等的基础。这个业务ID的特点是:针对同一个业务场景,全球唯一;由业务消息发送方生成,与业务相关,对MQ透明;由业务消息消费者负责判断权重,保证幂等性;最常见的业务ID有:支付ID、订单ID、邮寄ID等。具体到支付卡购买场景,发送方必须将支付ID放在消息体中,消费者必须判断相同的支付ID,保证幂等性卡购买。有了这个业务ID,即使消息消费业务方在后半段收到重复的消息,也可以保证只消费一条消息,保证幂等性。综上所述,MQ是如何保证消息幂等性的?首先,前半部分是幂等的。MQ-client生成inner-msg-id以确保前半部分的幂等性。这个ID是全局唯一的,和业务无关,由MQ保证。那么,后半部分是幂等的。业务发送端传入biz-id,业务接收端去重保证幂等性。这个ID是单个业务唯一的,与业务相关,对MQ是透明的。所以幂等性不仅需要MQ,还需要上下游业务。【本文为专栏作者《58神剑》原创稿件,转载请联系原作者】点此阅读更多该作者好文