34 生产案例:从RocketMQ底层原理分析为什么会发生重复发优惠券

1. 问题的定位:优惠券系统重复消费了一条消息

在当前案例的项目背景中,订单系统与各个系统是解耦的,也就是说订单支付成功之后,会发送一条消息到MQ去,然后红包系统(消费者)会从里面获取消息派发红包,优惠券系统从里面获取消息派发优惠券,其他系统同理。

可能发生的问题:在生产环境下,优惠券系统可能会对同一条消息重复的处理两次,导致它给一个用户重复的派发了两个优惠券,也可能是其他系统重复操作两次(派发积分等)。

 定位问题:优惠券重复派发两次的问题可以定位到,那就是优惠券系统对同一个订单支付成功的消息处理了两次,从而导致给用户重复发放了两张优惠券。

2.订单系统重复发送消息到MQ的原因:接口超时

在生产环境中,订单系统收到一个支付成功的通知之后,它在发送消息到MQ的时候,是有可能会重复把一个消息发送两次的。

场景分析:

假设用户在支付成功之后,订单系统收到了一个支付成功的通知,此时就会向MQ发送一条订单支付成功的消息,这是第一次

但是,可能由于接口超时等原因,导致订单系统处理的速度有点慢,也就是说此时还没来得及向MQ发送订单支付成功的消息。

 可能就因为订单系统处理的速度慢了,从而会导致支付系统跟订单系统之间的请求出现了超时,此时有可能支付系统再次重试调用了订单系统的接口去通知订单系统(生产者)这个订单支付成功了,然后订单系统在这个时候可能又一次推送了一条消息到MQ里去,这是第二次。

加上第一次推送的消息,相当于一个订单支付成功的消息,订单系统已经重复推送了两次到MQ。

重复派发优惠券

因为订单系统对一个订单重复推送了两次支付成功消息到MQ,MQ里有两条重复的支付成功消息,导致优惠券系统(消费者)必然会消费到一个订单的两条重复的支付成功消息,从而导致该订单给用户重复的派发两个优惠券。

小结:在MQ全链路中,用于发送消息到MQ的订单系统,如果出现了接口超时等问题,可能会导致上游的支付系统重试调用订单系统的接口,进而导致订单系统对一个消息重复发送两条到MQ里去。

3. 订单系统重复发送消息到MQ的原因:重试

场景分析:

在订单系统(生产者)为了保证消息一定能投递到MQ里去,会采用重试的代码。

代码段如下,如果发现MQ发送有异常,则会进行几次重试。

这种重试的机制,就可能导致消息重复发送。

假设订单系统(生产者)发送了一条消息到MQ,而MQ也已经接受到这条消息了,结果MQ返回响应给订单系统(生产者)的时候,由于网络超时等问题,导致订单系统没能及时收到MQ返回的响应。

此时的前提是,MQ里其实已经有订单系统发送过的消息了,只不过MQ返回的响应还没达到订单系统(生产者)而已。

超时重发

这个时候,可能由于网络超时的原因,代码在timeout后捕获网络超时的异常,然后进入到catch区域去进行重试再次发送这个消息到MQ去,然后MQ就会收到一条一模一样的消息,进而导致你的消息重复发送了。

小结:重试代码,有一定的概率会导致重发消息。

 4.优惠券(消费者)系统重复消费一条消息

在保证订单系统(生产者)没有重复发送消息到MQ的前提,MQ里只有一条消息的情况下,优惠券(消费者)系统也有可能会重复进行消费。

消费者重复消费场景

当优惠券(消费者)系统拿到一条订单支付成功的消息,然后进行了处理,也就是已经对该订单进行派发了一张优惠券了。

但是,好巧不巧,优惠券刚派发完成,还没来得及提交消息offset到broker。优惠券系统就进行了一次重启。

此时,由于优惠券系统未提交该消息的offset到broker,broker并不知道你已经处理完了这条消息,然后优惠券系统重启后,broker就会再次把这条消息交给你,让你再一次进行处理,然后你会再一次派发一张优惠券,导致重复发送了两次优惠券。

这也就是对同一条消息,优惠券系统重复处理两次的原因。

 5. 消息重复消费问题总结

(1)生产者接口超时导致多次被回调发送mq消息重复

(2)生产者发送消息到mq时发送成功未获取到响应然后进行消息发送重试导致消息发送多次

(3)消费者消费消息时本地事务执行,但是提交offset时宕机导致mq给消费者重复推送消息

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值