33 基于RocketMQ设计的全链路消息零丢失方案总结
Posted 鮀城小帅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了33 基于RocketMQ设计的全链路消息零丢失方案总结相关的知识,希望对你有一定的参考价值。
1. 全链路消息零丢失方案总结
发送消息到MQ的零丢失:
- 方案一: 同步发送消息 + 反复多次重试
- 方案二: 事务消息机制
- 两者都有保证消息发送零丢失的效果,经过分析,事务消息方案整体会好一些
MQ收到消息之后的丢失:
开启同步刷盘策略 + 主从架构同步机制,只要让一个Broker收到消息之后同步写入磁盘,同时同步复制给其他Broker,然后再返回响应给生产者说写入成功,此时就可以保证MQ自己不会丢失。
消费消息的零丢失:
采用RocketMQ的消费者可以保证你处理完消息之后,才会提交消息的offset到broker去,但要尽量避免采用多线程异步处理消息的方式。
2. 消息零丢失方案的优势与劣势
如果在系统中落地一套消息零丢失方案,不管是哪个系统,不管是哪个场景,都可以确保消息流转的过程不会丢失。而这也是消息零丢失方案的优势所在,可以让系统的数据都是正确的,不会有丢失的。
但是, 它的劣势也是很明显的,采用这样的一套方案之后,会让整个从头到尾的消息流转链路的性能大幅度下降,让你的MQ的吞吐量大幅度的下降。
场景说明:比如业务服务系统和MQ配合起来,每秒可以处理几万条消息的,结果在落地消息零丢失方案之后,可能每秒只能处理几千条消息了。
3.为什么消息零丢失方案会导致吞吐量大幅度下降
普通的消费链路中,发送一个消息到MQ,这就是一次普通的网络请求而已,整个过程只需要发送请求到MQ然后接收响应回来,这个性能很高,吞吐量也是很高的。
而一旦采用了基于事务消息的机制之后。就会涉及到 half消息、commit or rollback、写入内部topic、回调机制,等诸多复杂的环节。
如下图,光是成功发送一条消息,就至少要 half + commit 两次请求。
所以一旦用上了上述复杂的方案之后,必然会导致全链路上发送消息的性能大幅度下降,同时发送消息到MQ的吞吐量大幅度下降。
在MQ收到消息之后的行为,同样会让性能大幅度下降。
MQ的一台broker进程收到消息之后,必然会直接把消息刷入磁盘里,该性能远远低于写入 os cache 了,这完全不是一个数量级的。比如写入os cache相当于内存,可能仅需要0.1ms,而写入磁盘文件可能就需要10ms。
并且,当前broker机器还必须把消息复制给其他的broker,完成多副本的冗余,这个过程涉及到两台broker机器之间的网络通信,而另一台broker机器写数据到自己本地磁盘去,同样会比较慢。
只有在broker完成了上述两个步骤之后,接着才能返回响应告诉生产者这次消息写入已经成功了。这两个步骤,将直接导致原本10ms的业务耗时就会变成100ms了。
为了保证数据不丢失,消费者必须是处理完一批消息再返回CONSUME_SUCCESS状态,这一过程中,消费者处理消息的速度会降低,吞吐量随之也下降了。
4. 消息零丢失方案的适用场景是什么?
如果一定要上消息零丢失方案,就必然导致从头到尾的性能下降以及MQ的吞吐量下降。
这种场景不能随意使用,否则付出的成本太高了。一般,对于跟金钱、交易以及核心数据相关的系统和核心链路,可以上这套消息零丢失方案。
比如支付系统,它是绝对不会丢失任何一条消息的,此时对于性能是可以低一些,但不能有任何一笔支付记录丢失。
又比如订单系统,企业一般是不能轻易丢失一个订单的,一个订单对应一笔交易,而如果订单丢失,用户还支付成功了,轻则要给用户赔偿损失,重则要吃官司。大点的订单涉及金额甚至达到了几十万以上。
诸如上面两种类似的核心场景和核心链路,才会建议使用消息0丢失方案。
以上是关于33 基于RocketMQ设计的全链路消息零丢失方案总结的主要内容,如果未能解决你的问题,请参考以下文章
互联网面试必杀:如何保证消息中间件全链路数据100%不丢失石杉的架构笔记