0

RabbitMQ 和 Kafka

 9 months ago
source link: https://www.ttalk.im/2023/12/rabbitmq-and-kafka.html?amp%3Butm_medium=Atom
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

这是一篇2015年时我对Kafka和RabbitMQ的一些了解和使用。本文中提及的kafka特性是2.8.2之前版本的,RabbitMQ的特性也是2.x版本的,也算年代久远了。

最近公司 RabbitMQ 的集群出了点问题,然后有些亲就说 RabbitMQ 慢且不好用,是一个瓶颈,不如换成 Kafka。而我本人,使用 RabbitMQ 有一点久了,认为这个事情应当辩证的去看。所以就在没事的时候简单的看了看 RabbitMQ 的代码。但是我并没有看太多 Kafka 的代码,我只简单提下。

关于 Kafka

根据 Kafka 官方的文档,Kafka 可以被认为一个高大上的集群消息中间件,但是读了下以前一个朋友给的部署文档和 Kafka 的官方的文档。发现 Kafka 确实不错,真的可以说是集群消息中间件。

  1. 用 topic 来进行消息管理,每个 topic 包含多个 part,每个 part 对应一个逻辑 log,有多个 segment 组成。
  2. segment 中的消息 id 由其逻辑位置决定,可以用消息 id 直接定位到消息的存储位置,避免 id 到位置的额外映射。
  3. 生产者发到某个 topic 的消息会被均匀的分布到多个 part 上,broker 收到消息会写入最后的 segment 文件中,当某个 segment 上的消息条数达到配置值或消息发布时间超过阈值时,segment 上的消息会被 flush 到磁盘,只有 flush 到磁盘上的消息消费者才能收到。并且通过 rolling 的机制,保证 segment 的文件不至于过大。
  4. 消费者可以 rewind back 到任意位置重新进行消费,当消费者故障时,可以选择最小的 offset 进行重新读取消费消息。

是不是看起来很爽,但是深入往下看,发现了一些深坑

  1. Kafka 对消息的重复、丢失、错误以及顺序型没有严格的要求。但是 part 只会被 consumer group 内的一个 consumer 消费,故 kafka 保证每个 parti 内的消息会被顺序的消费。
  2. broker 没有副本机制,一旦 broker 宕机,该 broker 的消息将都不可用。同时 broker 是无状态的,broker 不保存消费者的状态,由消费者自己保存。无状态导也致消息的删除成为难题,所以 Kafka 选择消息保存一定时间后会被删除。
  3. 大量的依赖 Zookeeper,需要 Zookeeper 来管理 broker 与 consumer 的动态加入与离开。以及消费关系及每个 partion 的消费信息。

看到这里,你如果还明白我说这些深坑是什么意思,那就请带入运维场景和特定故障场景思考下。我稍后会说一下这些坑会带来什么问题。

关于 RabbitMQ

RabbitMQ 是使用 Erlang 开发的一个消息队列,可以构建成集群,也可以单独使用。

根据测试,RabbitMQ 在不使用 ACK 机制的,Msg 大小为 1K 的情况下,QPS 可达 6W+。再双方 ACK 机制,Msg 大小为 1K 的情况下,QPS 瞬间降到了 1W+。从某种意义上 RabbitMQ 还真是慢,但是我们需要思考下。

  1. 我们真的每个消息都能到 1K 吗?
  2. 我们真的需要双方都对消息 ACK 的系统吗?

好了,如果两个回答都是 YES,那么 RabbitMQ 就是慢的。如果是 No,那么 RabbitMQ 还是一个非常快的队列。

RabbitMQ 慢有几个原因:

  1. RabbitMQ 做为一个 Broker,不单单做到了简单的数据转发功能,还保证了单个队列上的数据有序,即便是有多个消费者和多个生产者。
  2. RabbitMQ 的策略是实时转发,而不像 Kafka 那样等待刷盘之后才让消费者来消费。
  3. 如果消费者和生产者不对等,会产生大量的磁盘 IO 操作,进行消息换出。

RabbitMQ 为什么不好用:

  1. AMQP 协议本身比较复杂,参数比较多。
  2. Erlang 写的,很多人不熟悉,并且 Mnesia 出现问题好多人解决不了。

RabbitMQ 和 Kafka 相比没价值了吗?

很多亲们读到这里,就会想 RabbitMQ 好像也不怎么样呀。和 Kafka 相比没什么价值可言了,但是我前面说了一些 Kafka 的坑,我就在这里面揭示一下。

  1. Kafka 大量依赖 Zookeeper,它的 broker 并不保存任何状态,如果 Zookeeper 集群不幸悲剧了,那么整个 Kafka 集群的消息就全完蛋了。
  2. 上面问题有人会说这概率好小,我也同样认为这个概率很小,那么一个 broker 当机呢?当一个 broker 当机了整个消息队列由于负载均衡的算法,在一瞬间消费者和生产者之间的消息就全乱掉了。很多需要保证消息顺序的系统一下子就完蛋了。

这就是 RabbitMQ 存在的价值和意义,同时 RabbitMQ 使用了 MirrorQueue 的机制,也可以做到多个机器进行热备。

RabbitMQ 该怎么用

  1. RabbitMQ 的消息应当尽可能的小,并且只用来处理实时且要高可靠性的消息。
  2. 消费者和生产者的能力尽量对等,否则消息堆积会严重影响 RabbitMQ 的性能。
  3. 集群部署,使用热备,保证消息的可靠性。

Kafka 该怎么用

  1. 应当有一个非常好的运维监控系统,不单单要监控 Kafka 本身,还要监控 Zookeeper。
  2. 对消息顺序不依赖,且不是那么实时的系统。
  3. 对消息丢失并不那么敏感的系统。

来自与2023年的一些补充

Kfaka从2.8.2的版本都已经把consumer的信息自己管理了,并且引入了ISR模式。ISR模式备份机制是通过partition的备份实现的, 如果一个broker宕机, 在这个broker上的partition的leader会切到正常的机器上, 然后正常提供服务。 但是对Zookeeper的强依赖还是存在的,即便是consumer信息自己管理了,broker的ISR机制和Topic还是很依赖Zookeeper的。

在Kafka的3.5及以后的版本中,Kafka又引入了一个新的机制KRaft,从此不再需要Zookeeper了。(此处感谢广大读者的提问和修正)

RabbitMQ在3.x版本可以通过插件实现hash队列,consumer也是可以在镜像队列上进行数据消费。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK