面试题:为什么解决发送消息零丢失方案,一定要使用RocketMQ事务消息?

1 RocketMQ事务消息存在的问题

事务机制复杂度提高,会导致整体性能比较差,吞吐量比较低

2 能不能基于重试机制来确保消息到达MQ?

原则上是可以的,Kafka就是会采用同步发消息 + 反复重试多次的方案,去保证消息成功投递到Kafka的

3 如果不用RocketMQ 事务消息可能存在哪些问题?

3.1 先执行订单本地事务,在发消息到MQ

这种情况存在情况是 比如刚执行完成了订单本地事务了,还没等到你发送消息到MQ,结果你的订单系统突然崩溃了,这就导致你的订单状态可能已经修改为了“已完成”,但是消息却没发送到MQ去!

3.2 把订单本地事务和重试发送MQ消息放到一个事务代码中

依然有问题,假设用户支付成功了,然后支付系统回调通知你的订单系统说,有一笔订单已经支付成功了,这个时候你的订单系统卡在多次重试MQ的代码那里,可能耗时了好几秒种,
此时回调通知你的系统早就等不及可能都超时异常了

但是即便没有出现上面的问题也存在其他问题,
例如:如果在本地事务方法中还有更新redis缓存和elesticSearch的代码,
如果你要是已经完成了订单数据库更新、Redis缓存更新、ES数据更新了,
结果还没发送MQ呢,订单系统崩溃了虽然订单数据库的操作会回滚,
但是Redis、Elasticsearch中的数据更新是不会自动回滚,他们没有回滚机制。
因此依靠本地事务并不可靠

因此我们保证业务系统一致性的最佳方案:基于RocketMQ的事务消息机制

4 难道使用Rocketmq得事务消息就一定不会丢失消息嘛?

答案是也不一定,
情况1: 比如说 你虽然发送了commit消息,然后broker只是把消息从half-topic中移到了业务topic,这时下游系统仅仅能够看到这个消息而已,如果这个时候消息恰巧仅仅只是写入到os cache中还没有进入到ConsumeQueue磁盘文件里去,然后此时这台机器突然宕机了,那么os cache中得数据也就丢失了也就必然会导致你得消息丢失,下游得红包系统也就无法读取到这条消息了

情况2: 或者就算你的消息落地到了磁盘,写入到了ConsumeQueue磁盘文件里去,如果这时机器得磁盘突然坏了,那么就会一样导致消息丢失,而且可能消息再也找不回来了,同样会丢失数据。

总结来看就是有可能os cache中得内存数据丢失 或者磁盘中得数据丢失

5 那么针对上面两种情况又该如何解决呢?

针对os cache中得数据丢失情况–将异步刷盘改为同步刷盘机制
即异步刷盘是指broker将消息写入到os cache后 有后台线程再空闲得时候将os cache中得数据刷入到磁盘中去
而同步刷盘,是指只要数据落地磁盘后才会返回写入成功,比如我们发送half消息的时候,只要MQ返回响应是half消息发送成功了,那么就说明消息已经进入磁盘文件了,不会停留在os cache里。

而针对磁盘文件坏掉丢失消息得问题 —Broker使用主从架构模式
也就是说,必须让一个Master Broker有一个Slave Broker去同步他的数据,而且你一条消息写入成功,必须是让Slave Broker也写入成功,保证数据有多个副本的冗余。
这样一来,你一条消息但凡写入成功了,此时主从两个Broker上都有这条数据了,此时如果你的Master Broker的磁盘坏了,但是Slave Broker上至少还是有数据的,数据是不会因为磁盘故障而丢失的。
对于主从架构模式 或者基于DLedger技术和Raft协议的主从同步架构,你如果采用了这套架构,对于你所有的消息写入,只要他写入成功,那就一定会通过Raft协议同步给其他的Broker机器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值