RabbitMQ和Kafka如何选择

最近很多人问RabbitMQ和Kafka要如何进行选择,甚至有一个风向:说是MQ性能不够了要切Kafka。且先不说成熟系统换组件的风险,光把那一坨沉淀了多年的醇酿翻新重构已然处于崩溃的边缘,蓦然回首,码是人非。

?

选型最快的方式就是了解下晚出现的中间件的起源,因为他们在付出努力之前肯定做了一波详细可研和成品的基准测试,我们直接拿来参考即可,然后再对比下各自的特性和差异,选型就有理论基础了,基本没有必要去了解各自的实现逻辑,因为其使用率都很高,不会有显而易见的问题。

RabbitMQ和Kafka如何选择

「 起源 」

RabbitMQ第一版发布于2007年,其构思的本质的原因是AMQP的出现。AMQP出现之前各家的MQ产品百花齐放,但也因此导致整合非常困难,没有形成统一的消息总线,在AMQP神兵天降之后RabbitMQ就开启了它的职业生涯。

Kafka起源于LinkedIn,开源于2011年,目标是为了帮助处理持续数据流而设计的组件,在尝试了消息系统、数据聚合、ETL工具等方式后,均无法满足其需求,因此Kafka就诞生了。

「 特性 」

RabbitMQ遵循了AMQP协议,拥有比较完善的消息交换模型:

  • 支持生产者消费者模式和发布订阅模式

  • 支持消息的ack机制:显式ack和自动ack

  • 支持多租户

  • 支持权限配置

  • 支持死信队列

  • 支持消息超时机制

  • ...

Kafka作为一个分布式流式组件:

  • 支持生产者消费者模式和发布订阅模式

  • 支持流回放

  • 支持分批次写入

  • 支持分片

  • 支持副本策略

  • 支持数据保存策略

  • ...

以上特性可以分别看出两者使用场景上的差别,下面补充一下两者针对消息存储和消费的差异性。

存储方式

RabbitMQ将消息存储于队列(Queue)中,消费者确认收到消息后(返回ack)才会移除消息。Kafka将消息存于主题(Topic)中,并分片分散在各个节点,提高了并行率。其存储策略可配置时间策略(如消息最长保存7天)或者空间策略(如消息最多保存10G)。

有序性

RabbitMQ中队列是先进先出队列,因此保证了消息的有序性。

Kafka如果分片配置为1,则消息也保证了有序性,但却降低了吞吐率;如果分片配置为多份,则只能保证每个分片里的数据是有序的,无法保证整个分片是有序的。


消息的ACK

RabbitMQ如果没有配置自动ack,消息或者队列也没有设置TTL,则MQ将会一直等待消费者显式响应ack后才会将消息移除,否则消息将一直存着,这种情况下,如果出现消费者崩溃或者消费速率低于生产速率等情况,会导致消息堆积占用内存,时间一长将蔓延影响到生产者生产数据。

Kafka不支持消息的ack,但提供了消息偏移量offset,消费者根据offset获取消息,且支持消息回放(重复消费)。

「 集群 」

可靠性和弹性拓展在生产环境中至关重要,前者保障服务能正常使用,后者保障服务遇到瓶颈后可以进行拓展。

RabbitMQ

RabbitMQ有多种集群方式,此处简单分为两大类:非镜像集群和镜像集群。在可靠性上,RabbitMQ使用集群+带有负载均衡的软硬件(如HAProxy)组件实现。在弹性拓展上,非镜像集群,拓展节点可线性提高性能,但由于并非所有节点都存储队列本身,因此如果某一个节点故障了,该节点的数据将会丢失。镜像集群,队列数据将同步到其他节点,保证了可用性,但同时也增加了网络和磁盘的负载,损失了性能。

Kafka

Kafka在设计时支持分片和副本策略,该架构保存消息会消息分散到在不同的节点,在拥有可靠性的同时也有较好的拓展能力,也因此,但因依赖了ZooKeeper,最好的方式是保证节点数为奇数个

「 结语 」

针对以上的分析不难看出二者的偏向性,如果单纯只为了削峰填谷和数据分发等RabbitMQ会是个更好的选择,如果需要大吞吐量的数据处理类,Kafka则更好。始于需求,基于业务,找到合适的组件才是关键。


RabbitMQ和Kafka如何选择