RocketMQ场景问题

1.消息丢失

有这么一个场景,就是订单支付完成之后,订单系统会进行发送消息给RocketMQ集群,下游会有积分系统进行监听这个消息,进行消费然后给用户发放积分。在下面的这个场景中,通过查询日志发现了订单系统发送订单支付消息的日志。别的就没有了。

那我们进行分析

  1. 发送订单支付消息给RocketMQ集群会出现消息丢失的情况的吗?

会出现消息丢失的情况,可能出现的原因:在发送的过程中,出现了网络抖动,导致了消息没有发送的MQ的集群上;MQ集群收到了消息,但是在进行保存的时候,由于自身的一些bug或者其他原因导致数据没有存储上也是可能的等。

2.消息到达了MQ,MQ会自己导致数据丢失吗?

答案也是可能的,举个例子,我们发送消息到MQ集群上,此时消息还是在os cache中,还是没有写入到磁盘,此时Broker机器发生了宕机,那么消息就会出现丢失的情况。

3.消息到达了MQ,并且MQ将数据写入了磁盘,数据还会丢失吗?

答案还是有可能的,比方说磁盘发生了故障,导致数据的丢失。

4.消费者拿到了消息,消息就不会丢失了吗?

答案还是有可能会丢失的,假如我们的消费者拿到了消息,此时还没有进行消费,此时系统会有自动提交offset的能力,自动提交了offset,同时咱们的消息者宕机了,那么再次重启之后,这条消息就会出现丢失的情况。

解决方案:

针对情况一:我们可以采用RocketMQ的事务消息机制来保证消息发送的可靠性。

步骤一 都失败了,那就没必要进行更新订单状态可以直接返回了;

步骤二失败了 此时就会有步骤五算是一个补偿机制来进行反查状态;

步骤三失败了,会触发步骤四进行RollBack;

步骤四失败了此时就会有步骤五算是一个补偿机制来进行反查状态;

针对情况二,情况三:我们采用同步刷盘和Raft协议主从同步的策略

当我们的Broker接收到消息之后,会先写入到os cache中,此时还没写入到磁盘中,这个时候如果机器宕机了,消息就会丢失了。需要将默认的刷盘机制由异步刷盘改为同步刷盘,同时采用Broker集群的策略,一个Master broker写入成功,一个slave broker写入成功才认为是写入成功。这样的话就算Master Broker宕机了,slave Broker上也有消息,不会出现消息的丢失的情况。

针对情况四:我们采用消息消费完成之后,再进行提交offset。

2.消息重复消费的问题

还是上述的场景,可能会出现消息消费重复的问题。

情况一:生产者进行重复发送了两次消息。

情况二:消费者进行消费了两次消息,在进行第一次消费的时候,代码逻辑处理完成了,但还未来得及进行offset提交,此时机器宕机或者重启,那么下次进行拉取消息的时候,还是会把消息再次拉取一遍,再次进行消费。

针对情况一,我们的解决办法:

1.在进行发送的消息的时候,从MQ中进行查询一下消息是否存在MQ中,如果MQ中存在,那么就没必要进行再次的发送

2.基于Redis缓存的幂等控制:当你成功发送一条消息到MQ之后,就要在Redis缓存中存放一个消息的状态信息。

3.基于业务的判断逻辑:比方说你的业务里有一些操作,是发送完成消息之后就要做一些状态的变更,那么就可以根据状态的变更来做。

其实针对这种发送端来保证发送的幂等性,在我们的实际的开发中并不常用,因为我们基本上都能接受消息在发送端的重复,我们要进行保证的是消息在消费端的幂等性,这种方式跟在发送端保证消息发送的幂等性基本类似。这里就不再赘述。

3.消费者宕机的情况

正常情况下我们进行消费RocketMQ的消息,消费成功的话会进行返回CONSUME_SUCCESS,但当我们消费消息有异常的时候,我们就不会返回CONSUME_SUCCESS而是返回CONSUME_LA TER状态。那RocketMQ收到这个状态之后,会把这个消息放入到重试队列中去,过一段时间,重试队列中的消息会给我们,让我们进行再次消费,这个也是有次数的限制,并不会一直让我们进行重试,默认重试的次数是16次。如果超过了16次还是没成功呢,此时消息就会进入到死信队列中,针对死信队列中的消息要进行如何的处理,就要看我们的业务场景来说,如果需要处理死信队列中数据,我们可以订阅死信队列,然后开启消费。

4.消息乱序的情况

在进行消费消息的时候,会出现消息乱序的情况,我们举一个例子,我们有一个场景是要进行数据同步,在进行数据同步的时候,进行监听的数据库的binlog消息,一般情况下,都是先有insert的binlog,然后才会有update的binlog消息,但是在实际场景中出现了先有update的binlog,然后再有insert的binlog的情况。

出现这种的情况的原因:因为Topic会有多个MessageQueue,咱们再进行发送消息的时候会将消息发送到不同的MessageQueue上,当有两个消费者来进行拉取消息的时候,就会出现update的binlog先进行消费,insert的binlog后进行消费的场景。

相关推荐
RunningShare18 小时前
大数据消息中间件选型终极指南:深度解析Kafka、Pulsar、RocketMQ架构与性能
大数据·kafka·rocketmq·pulsar
Lxinccode1 天前
python(44) : docker构建支持消费rocketmq的客户端
python·docker·rocketmq·importerror·not found·dynamic library·pyrocketmq
求你不要出Bug了1 天前
RokcetMQ事务消息详解
分布式·rocketmq·事务消息
阿里云云原生2 天前
阿里云 AI 中间件重磅发布,打通 AI 应用落地“最后一公里”
云原生·rocketmq
cominglately3 天前
kafka和rocketmq的副本机制区别: isr 主从模式,Dledger模式
分布式·kafka·rocketmq
qyt19885203 天前
关于队列的比较(Kafka、RocketMQ、RabbitMQ)
kafka·rabbitmq·rocketmq
用户9446814013505 天前
定时/延时消息在RocketMQ 4.x到RocketMQ 5.0的演变:从固定延时等级到精准延时时间
消息队列·rocketmq
syty20206 天前
kafka vs rocketmq
分布式·kafka·rocketmq
菠菠萝宝7 天前
【Java八股文】13-中间件面试篇
java·docker·kafka·rabbitmq·canal·rocketmq·es
承悦赋7 天前
微服务通信:5大消息队列横向对比
微服务·架构·kafka·rabbitmq·rocketmq