RocketMQ系列(五)异常处理:发送失败、重复消费


使用消息队列,不论是消息生产者还是消费者,都容易存在异常情况。

生产者失败

异常情况:
生产者在把消息发送到mq的broker的过程中,容易存在以下情况:
1.发送时,网络异常,消息没有到达broker;
2.发送同步消息时,消息到达broker,但是当broker相应生产者时,网络异常,生产者没有收到响应,认为发送失败;

解决方案:
如果是发送异步消息,也就是生产者不会等待broker响应,此种情况就会产生消息丢失;如果业务场景不在乎少量消息丢失,则不要处理;否则可以采用如下方法:

  • 使用带回调的消息发送方法,生产者的异步线程在发送消息后,会根据结果情况,调用回掉接口中的方法,成功或者失败,生产者根据具体情况记录日志or保存数据库,后续可以通过定时任务或者人工处理失败的消息,进行重新发送。

如果发送同步消息,生产者会等待broker返回结果,如果失败,可以进行重试或者保存到数据库,后续再从数据库中查询出来进行重发。

以上只能保证消息成功发送到broker,但无法保证唯一性,因为当消息到达broker,但是broker却没有响应时,生产者会重复发送(客户端默认重试3次),导致消息重复。

消费者幂等处理

上述分析中,消费者可能会重复发送消息,因此需要消费者进行幂等处理,否则会导致业务异常,比如重复扣减库存数量。
实际产生消息重复的情况有如下几种:

  1. 生产者重复发送;
  2. broker投递消息时,重复投递;当broker推送到消费者,但是没有得到消费者的响应(比如消费者响应时,网络异常),此时broker会重复投递消息;
  3. 负载均衡时消息重复:当rocketmq的broker宕机、重启、扩容、缩容时,可能会触发rebalance,导致消息重复消费。

常用的幂等处理方案:
消费者在接收到消息之后,在消息处理之前,先查询数据库中是否存在,存在则不处理。如果不存在,则首先将消息存入数据库,存入成功后,在处理消息。

这里注意的是,要使用一定的规则来界定消息的重复性,比如使用订单id(不要使用消息id,因为rocketmq不保证消息id的唯一性),如果使用mysql,这个订单id要加唯一索引,避免并发时,两个线程同时查询数据库,发现不存在,然后同时将消息存入数据库的情况。

更多最佳实践,请参考官方文档:best_practice

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值