RabbitMQ 和 Kafka 到底怎么选?

业余草

共 2488字,需浏览 5分钟

 · 2021-10-11

你知道的越多,不知道的就越多,业余的像一棵小草!

你来,我们一起精进!你不来,我和你的竞争对手一起精进!

编辑:业余草

cnblogs.com/haolujun/p/9632835.html

推荐:https://www.xttblog.com/?p=5281

前言

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

RabbitMQ 架构

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

  • broker:每个节点运行的服务程序,功能为维护该节点的队列的增删以及转发队列操作请求。
  • master queue:每个队列都分为一个主队列和若干个镜像队列。
  • mirror queue:镜像队列,作为 master queue 的备份。在 master queue 所在节点挂掉之后,系统把 mirror queue 提升为 master queue,负责处理客户端队列操作请求。注意,mirror queue 只做镜像,设计目的不是为了承担客户端读写压力。
RabbitMQ 集群

如上图所示,集群中有两个节点,每个节点上有一个broker,每个broker负责本机上队列的维护,并且borker之间可以互相通信。集群中有两个队列A和B,每个队列都分为master queue和mirror queue(备份)。那么队列上的生产消费怎么实现的呢?

队列消费

队列消费

如上图有两个 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 所在的节点上,这样才能进行消费。

队列生产

队列生产

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

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

Kafka

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

这里面的每个 master queue 在 Kafka 中叫做 Partition,即一个分片。一个队列有多个主分片,每个主分片又有若干副分片做备份,同步机制类似于 RabbitMQ。

Kafka集群

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

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 官方文档,所以真要搞懂一个中间件的原理最好去看官方文档,文档里面有详细的设计方案,我们可以自己进行设计方案的对比,从而找出符合自己实际情况的中间件。

浏览 31
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报