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

消息总线真的能保证幂等吗?

时间:2023-03-21 13:25:28 科技观察

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