欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

RabbitMQ 和 Kafka 到底怎么选?

程序员文章站 2022-04-16 07:50:25
前言 开源社区有好多优秀的队列中间件,比如RabbitMQ和Kafka,每个队列都貌似有其特性,在进行工程选择时,往往眼花缭乱,不知所措。对于RabbitMQ和Kafka,到底应该选哪个? RabbitMQ架构 RabbitMQ是一个分布式系统,这里面有几个抽象概念。 broker:每个节点运行的服 ......

RabbitMQ 和 Kafka 到底怎么选?

前言

开源社区有好多优秀的队列中间件,比如rabbitmq和kafka,每个队列都貌似有其特性,在进行工程选择时,往往眼花缭乱,不知所措。对于rabbitmq和kafka,到底应该选哪个?

rabbitmq架构

rabbitmq是一个分布式系统,这里面有几个抽象概念。

  • broker:每个节点运行的服务程序,功能为维护该节点的队列的增删以及转发队列操作请求。

  • master queue:每个队列都分为一个主队列和若干个镜像队列。

  • mirror queue:镜像队列,作为master queue的备份。在master queue所在节点挂掉之后,系统把mirror queue提升为master queue,负责处理客户端队列操作请求。注意,mirror queue只做镜像,设计目的不是为了承担客户端读写压力。

RabbitMQ 和 Kafka 到底怎么选?

如上图所示,集群中有两个节点,每个节点上有一个broker,每个broker负责本机上队列的维护,并且borker之间可以互相通信。集群中有两个队列a和b,每个队列都分为master queue和mirror queue(备份)。那么队列上的生产消费怎么实现的呢?消息队列的应用场景可以看这篇文章《消息队列常见的几种使用场景介绍》

队列消费

RabbitMQ 和 Kafka 到底怎么选?

如上图有两个consumer消费队列a,这两个consumer连在了集群的不同机器上。rabbitmq集群中的任何一个节点都拥有集群上所有队列的元信息,所以连接到集群中的任何一个节点都可以,主要区别在于有的consumer连在master queue所在节点,有的连在非master queue节点上。

因为mirror queue要和master queue保持一致,故需要同步机制,正因为一致性的限制,导致所有的读写操作都必须都操作在master queue上(想想,为啥读也要从master queue中读?和数据库读写分离是不一样的。),然后由master节点同步操作到mirror queue所在的节点。即使consumer连接到了非master queue节点,该consumer的操作也会被路由到master queue所在的节点上,这样才能进行消费。

队列生产

RabbitMQ 和 Kafka 到底怎么选?

原理和消费一样,如果连接到非 master queue 节点,则路由过去。

所以,到这里小伙伴们就可以看到 rabbitmq的不足:由于master queue单节点,导致性能瓶颈,吞吐量受限。虽然为了提高性能,内部使用了erlang这个语言实现,但是终究摆脱不了架构设计上的致命缺陷。

kafka

说实话,kafka我觉得就是看到了rabbitmq这个缺陷才设计出的一个改进版,改进的点就是:把一个队列的单一master变成多个master,即一台机器扛不住qps,那么我就用多台机器扛qps,把一个队列的流量均匀分散在多台机器上不就可以了么?注意,多个master之间的数据没有交集,即一条消息要么发送到这个master queue,要么发送到另外一个master queue。

这里面的每个master queue 在kafka中叫做partition,即一个分片。一个队列有多个主分片,每个主分片又有若干副分片做备份,同步机制类似于rabbitmq。
RabbitMQ 和 Kafka 到底怎么选?

如上图,我们省略了不同的queue,假设集群上只有一个queue(kafka中叫topic)。每个生产者随机把消息发送到主分片上,之后主分片再同步给副分片。

RabbitMQ 和 Kafka 到底怎么选?

队列读取的时候虚拟出一个group的概念,一个topic内部的消息,只会路由到同group内的一个consumer上,同一个group中的consumer消费的消息是不一样的;group之间共享一个topic,看起来就是一个队列的多个拷贝。所以,为了达到多个group共享一个topic数据,kafka并不会像rabbitmq那样消息消费完毕立马删除,而是必须在后台配置保存日期,即只保存最近一段时间的消息,超过这个时间的消息就会从磁盘删除,这样就保证了在一个时间段内,topic数据对所有group可见(这个特性使得kafka非常适合做一个公司的数据总线)。队列读同样是读主分片,并且为了优化性能,消费者与主分片有一一的对应关系,如果消费者数目大于分片数,则存在某些消费者得不到消息。

由此可见,kafka绝对是为了高吞吐量设计的,比如设置分片数为100,那么就有100台机器去扛一个topic的流量,当然比rabbitmq的单机性能好。

总结

本文只做了kafka和rabbitmq的对比,但是开源队列岂止这两个,zeromq,rocketmq,jmq等等,时间有限也就没有细看,故不在本文比较范围之内。

所以,别再被这些五花八门的队列迷惑了,从架构上找出关键差别,并结合自己的实际需求(比如本文就只单单从吞吐量一个需求来考察)轻轻松松搞定选型。最后总结如下:

  • 吞吐量较低:kafka和rabbitmq都可以。

  • 吞吐量高:kafka。

本文内容参考自rabbitmq和kafka官方文档,所以真要搞懂一个中间件的原理最好去看官方文档,文档里面有详细的设计方案,我们可以自己进行设计方案的对比,从而找出符合自己实际情况的中间件。

推荐去我的博客阅读更多:

1.java jvm、集合、多线程、新特性系列教程

2.spring mvc、spring boot、spring cloud 系列教程

3.maven、git、eclipse、intellij idea 系列工具教程

4.java、后端、架构、阿里巴巴等大厂最新面试题

生活很美好,明天见~