dbaplus社群 2024年11月20日
后起之秀 RocketMQ 为什么性能不如 Kafka?
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

RocketMQ和Kafka都是常用的消息队列,RocketMQ的架构借鉴了Kafka,但在性能方面略逊一筹。Kafka在吞吐量上领先约50%,主要得益于其使用sendfile实现零拷贝技术,而RocketMQ则使用mmap。虽然RocketMQ的性能不及Kafka,但它在功能方面更强大,例如消息过滤、消息回溯、事务能力、延迟队列和死信队列等。本文探讨了零拷贝技术、RocketMQ和Kafka性能差异的原因,并给出了选择消息队列的建议:大数据场景下优先选择Kafka,其他场景下则可考虑RocketMQ。

🚀 **RocketMQ架构参考Kafka,但在性能方面略逊一筹:**阿里中间件团队测试表明,在相同条件下,Kafka的吞吐量比RocketMQ高约50%。

💡 **零拷贝技术是性能差异的关键:**Kafka使用sendfile实现零拷贝,而RocketMQ使用mmap,sendfile在数据拷贝次数和系统内核切换次数方面更少,因此性能更高。

🤔 **RocketMQ功能更强大,但牺牲了一部分性能:**RocketMQ在消息过滤、回溯、事务、延迟队列和死信队列等方面拥有更丰富的功能,这些功能需要获取消息内容,因此无法使用sendfile。

📊 **选择消息队列需根据场景:**大数据场景(例如Spark、Flink等)下优先选择Kafka,其他场景下则可考虑RocketMQ,需根据公司组件支持情况进行选择。

🔄 **RocketMQ与Kafka的权衡:**RocketMQ在架构和功能上做了加法,牺牲了一部分性能,以换取更强大的功能特性。

小白 2024-11-20 07:15 广东

RocketMQ 和 Kafka 到底该怎么选?


熟悉 RocketMQ 的都知道,RocketMQ 的架构其实参考了 kafka 的设计思想,同时又在 kafka 的基础上做了一些调整。看起来,RocketMQ 好像各方面都比 kafka 更能打。



但 kafka 却一直没被淘汰,说明 RocketMQ 必然是有着不如 kafka 的地方。是啥呢?性能,严格来说是吞吐量。阿里中间件团队对它们做过压测,同样条件下,kafka 比 RocketMQ 快 50% 左右。但即使这样,RocketMQ 依然能每秒处理 10w 量级的数据,依旧非常能打。你不能说 RocketMQ 弱,只能说 Kafka 性能太强了。


不过这就很奇怪了,为什么 RocketMQ 参考了 kafka 的架构,却不能跟 kafka 保持一样的性能呢?在回答这个问题之前,我们来聊下什么是零拷贝


一、零拷贝是什么


我们知道,消息队列的消息为了防止进程崩溃后丢失,一般不会放内存里,而是放磁盘上。那么问题就来了,消息从消息队列的磁盘,发送到消费者,过程是怎么样的呢?


消息的发送过程


操作系统分为用户空间内核空间。程序处于用户空间,而磁盘属于硬件,操作系统本质上是程序和硬件设备的一个中间层。程序需要通过操作系统去调用硬件能力。



如果用户想要将数据从磁盘发送到网络。那么就会发生下面这几件事:程序会发起系统调用read(),尝试读取磁盘数据,



程序再发起系统调用write(),将读到的数据发到网络:



最终数据就会经过网络到达消费者。



整个过程,本机内发生了 2 次系统调用,对应 4 次用户空间和内核空间的切换,以及 4 次数据拷贝



一顿操作猛如虎,结果就是同样一份数据来回拷贝。有没有办法优化呢?有,它就是零拷贝技术,常见的方案有两种,分别是 mmap 和 sendfile。我们来看下它们是什么。


mmap 是什么


mmap 是操作系统内核提供的一个方法,可以将内核空间的缓冲区映射到用户空间。



用了它,整个发送流程就有了一些变化。程序发起系统调用mmap(),尝试读取磁盘数据,具体情况如下:



程序再发起系统调用write(),将读到的数据发到网络:




整个过程,发生了 2 次系统调用,对应 4 次用户空间和内核空间的切换,以及 3 次数据拷贝,对比之前,省下一次内核空间到用户空间的拷贝。



看到这里大家估计也蒙了,不是说零拷贝吗?怎么还有 3 次拷贝。mmap 作为一种零拷贝技术,指的是用户空间到内核空间这个过程不需要拷贝,而不是指数据从磁盘到发送到网卡这个过程零拷贝。



确实省了一点,但不多。有没有更彻底的零拷贝?有,用 sendfile.


sendfile 是什么


sendfile,也是内核提供的一个方法,从名字可以看出,就是用来发送文件数据的。程序发起系统调用sendfile(),内核会尝试读取磁盘数据然后发送,具体情况如下:




整个过程,发生了 1 次系统调用,对应 2 次用户空间和内核空间的切换,以及 2 次数据拷贝。这时候问题很多的小明就有意见了,说好的拷贝怎么还有 2 次拷贝?



其实,这里的零拷贝指的是零 CPU拷贝。也就是说 sendfile 场景下,需要的两次拷贝,都不是 CPU 直接参与的拷贝,而是其他硬件设备技术做的拷贝,不耽误我们 CPU 跑程序。


kafka 为什么性能比 RocketMQ 好


聊完两种零拷贝技术,我们回过头来看下 kafka 为什么性能比 RocketMQ 好。这是因为 RocketMQ 使用的是 mmap 零拷贝技术,而 kafka 使用的是 sendfile。kafka 以更少的拷贝次数以及系统内核切换次数,获得了更高的性能。但问题又来了,为什么 RocketMQ 不使用 sendfile?参考 kafka 抄个作业也不难啊?我们来看下 sendfile 函数长啥样。


ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count);// num = sendfile(xxx);


再来看下 mmap 函数长啥样。


void *mmap(void *addr, size_t length, int prot, int flags,           int fd, off_t offset);// buf = mmap(xxx)

注释里写的是两个函数的用法,mmap 返回的是数据的具体内容,应用层能获取到消息内容并进行一些逻辑处理。



而 sendfile 返回的则是发送成功了几个字节数,具体发了什么内容,应用层根本不知道。



而 RocketMQ 的一些功能,却需要了解具体这个消息内容,方便二次投递等,比如将消费失败的消息重新投递到死信队列中,如果 RocketMQ 使用 sendfile,那根本没机会获取到消息内容长什么样子,也就没办法实现一些好用的功能了。



而 kafka 却没有这些功能特性,追求极致性能,正好可以使用 sendfile。


除了零拷贝以外,kafka 高性能的原因还有很多,比如什么批处理,数据压缩啥的,但那些优化手段 rocketMQ 也都能借鉴一波,唯独这个零拷贝,那是毫无办法。



所以还是那句话,没有一种架构是完美的,一种架构往往用于适配某些场景,你很难做到既要又要还要。当场景不同,我们就需要做一些定制化改造,通过牺牲一部分能力去换取另一部分能力。做架构,做到最后都是在做折中。是不是感觉升华了。


kafka 和 RocketMQ 怎么选?


这时候大家估计还是想知道 kafka 和 RocketMQ 到底该怎么选,用哪个。官方点的回答是"这个要看场景的"。说了等于没说,这不是我的风格。我的标准只有一个,如果是大数据场景,比如你能频繁听到 spark,flink 这些关键词的时候,那就用 kafka。除此之外,如果公司组件支持,尽量用 RocketMQ。


现在大家通了吗?


二、总结


RocketMQ 和 kafka 相比,在架构上做了减法,在功能上做了加法。


跟 kafka 的架构相比,RocketMQ 简化了协调节点和分区以及备份模型。同时增强了消息过滤、消息回溯和事务能力,加入了延迟队列,死信队列等新特性。


凡事皆有代价,RocketMQ 牺牲了一部分性能,换取了比 kafka 更强大的功能特性。


作者丨小白

来源丨公众号小白debug(ID:xiaobaidebug)

dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn


跳转微信打开

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

RocketMQ Kafka 消息队列 零拷贝 性能
相关文章