如何选择消息队列?

作为一个程序员,我们必须要认识到,软件工程中是不存在”银弹“的。

在消息队列的选型问题上,也是同样的道理。并不存在哪个消息队列就是最好的,能够解决所有的问题。常用的消息队列有好几个,每一种都有自己的优势和劣势,需要业务方根据自己的系统的情况,选择最适合的产品。

选择消息队列的基本标准

1、开源

​ 首先,必须是开源的产品,因为一旦在开发过程中遇到一个系统 Bug,你至少有机会通过修改源代码来修复这个 Bug,而不是只能无期限地等待产品的开发者发布新版本解决该问题。

2、流行

​ 其次,这个产品必须是近年来比较流行并且有一定社区活跃度的产品。流行意味着使用的人很多,只要你的场景不是很冷门,几乎你遇到的 Bug 都有前辈已经踩过坑了,都能找到类似的解决方案。

​ 同时流行的产品与周边生态系统会有一个比较好的集成和兼容,大部分场景下不需要为自己的业务额外地去开发其他中间件。

3、可靠

​ 需要保证消息传递的可靠,确保消息不会丢失。

4、支持 Cluster

​ 支持集群,确保不会因为某个节点宕机导致服务不可用的情况,同时也需要保证消息不会丢失

5、性能

​ 具备足够好的性能,能满足大多数场景的性能要求。

可供选择的消息队列产品

1、RabbitMQ

​ 老牌消息队列 RabbitMQ,俗称兔子 MQ。它是用一种比较小众的语言:Erlang 编写的,最早为电信行业系统之间的可靠通信设计的,支持 AMQP 协议。

​ 它的特点是:轻量级、迅捷,宣传口号是:”开箱即用的消息队列“,是一个相当轻量级的消息队列,非常容易部署和使用。因此 RabbitMQ 成为了 ”最流行的消息中间件之一“。

​ RabbitMQ 一个比较有特色的功能是支持非常灵活的路由配置,和其他消息队列不同的是,它在生产者和队列之间增加了一个类似交换机的 Exchange 模块。这个模块根据配置的路由规则将生产者发出的消息分发到不同的队列中。路由的规则也非常灵活,甚至可以自己来实现路由规则。

这里通过一个示例,详细解释一下 Exchange 模块的作用:

假设你有一个电商网站,你希望根据用户的购买地理位置将订单消息路由到不同的队列,以便分别处理。

  1. 创建 Exchange: 首先,你会创建一个 Exchange,可以命名为 “OrderExchange”。这是消息的中转站,它会接收生产者发送的订单消息,并负责将这些消息路由到一个或多个队列中。
  2. 创建队列: 然后,你会创建多个队列,每个队列代表一个不同的地理位置,比如 “USOrders”、”EUOrders” 和 “AsiaOrders”。
  3. 定义绑定规则: 接下来,你会定义绑定规则。这些规则告诉 Exchange 如何将消息路由到队列。例如,你可以定义规则,将订单消息中的地理位置信息与队列的名称进行匹配。如果订单来自美国,它将被路由到 “USOrders” 队列,如果来自欧洲,它将被路由到 “EUOrders” 队列。
  4. 生产者发送消息: 当用户在网站上下订单时,订单服务会将订单消息发送到 “OrderExchange”。这个消息会带有订单信息,包括地理位置。
  5. Exchange 路由消息: “OrderExchange” 根据你定义的规则,将消息路由到相应的队列。如果订单来自美国,它将被发送到 “USOrders” 队列。
  6. 队列消费消息: 各个队列中的消费者(可能是不同的处理订单的系统)订阅相应队列并处理订单消息。”USOrders” 队列中的消费者处理来自美国的订单,”EUOrders” 队列中的消费者处理来自欧洲的订单,依此类推。

​ RabbitMQ 的客户端所支持的编程语言是消息队列中最多的,如果你的系统是使用某种冷门语言开发,那你可以尝试找到对应的 RabbitMQ 客户端,不出意外的话,应该是能找到的。

​ 接下来说说 RabbitMQ 的几个问题:

  1. 消息堆积:RabbitMQ 的设计理念是管道,它对消息堆积的支持有限,大量消息堆积可能导致性能下降。因此,它不是最佳选择用于需要大规模消息堆积的应用。
  2. 性能较差:相对于其他消息队列系统,RabbitMQ 的性能较差。它通常能够处理每秒数万到十几万条消息,性能依赖于硬件配置,虽然大多数的应用场景也够用了,但如果对消息队列的性能要求非常高的话,就不要选择 RabbitMQ。
  3. 二次开发难:RabbitMQ 使用的 Erlang 语言不仅非常小众,而且这个语言的学习曲线非常陡峭。如果想基于 RabbitMQ 做一些扩展和二次开发,则需要慎重考虑可持续维护的问题。

2、RocketMQ

​ RocketMQ 是阿里巴巴开源的消息队列产品,后捐赠于 Apache 软件基金会,成为其顶级项目。它经历多次 ”双十一“ 的考研,性能、稳定性和可靠性都是值得信赖的,是一款优秀的国产消息队列。

​ RocketMQ 有非常活跃的中文社区,大多数问题都能够找到中文的答案,这或许也是越来越多国内大厂使用的原因。另外,它使用 Java 语言开发,贡献者大多数都是中国人,源代码也相对比较容易读懂,很方便进行扩展或二次开发。

​ RocketMQ 的好处是,它对于在线业务的相应做了很多的优化,大多数情况下可以做到毫秒级的响应,如果你的应用场景很在意响应时延,那应该选择使用 RocketMQ。

​ RocketMQ 的性能比 RabbitMQ 要高一个数量级,每秒钟大概能处理几十万条消息。

​ RocketMQ 的一个劣势是,国际知名度比较低,与周边生态系统的集成和兼容程度要略逊一筹。

3、Kafka

​ Kafka 最早是由 Linkedln 开发,目前也是 Apache 的顶级项目,它最初的设计目的是用于处理海量的日志

​ 在早期的版本中,为了获得极致的性能,在设计方面做了很多牺牲,比如不保证消息的可靠性,可能会丢失消息,也不支持集群,功能上也比较简陋。这些牺牲对于处理海量日志这个特定的场景是可以接收的,但此时的 Kafka 不能被称为一个合格的消息队列。在随后几年 Kafka 逐步补齐了短板,当下的 Kafka 已经发展为一个非常成熟的消息队列产品,无论数据可靠性、稳定性和功能特性等方面都可以满足绝大多数场景了。

Kafka 与周边生态系统的兼容性是最好的没有之一,尤其在大数据和流计算领域,几乎所有的相关开源软件系统都会优先支持 Kafka。

​ Kafka 使用 Scala 和 Java 开发,设计上大量使用了批量和异步的思想,这使得 Kafka 能做到超高的性能,尤其是异步收发的性能,是三者中最好的。但与 RocketMQ 并没有量级上的差异,大约每秒可以处理几十万条消息。

​ 然而,Kafka采用的异步批量消息处理设计会引发一个问题,即它的同步消息传递响应时延较高。这是因为在客户端发送一条消息后,Kafka不会立即传递消息,而是会等待一段时间以便累积一批消息后再一起处理。这种”批量处理”设计在Kafka的Broker中多次出现。在业务场景中,如果每秒的消息数量相对较低,Kafka的响应时延可能会变得较高。因此,Kafka通常不太适用于需要低延迟的在线业务场景。

第二梯队的消息队列

​ 除了上述比较常用的消息队列,还有一些不太常用的产品,之所以不太流行肯定是有原因的,所以不推荐使用。下面简单介绍一下:

1、ActiveMQ

​ ActiveMQ 的最老牌的开源消息队列,是十年前唯一可供选择的开源消息队列,目前已进入老年期,社区不活跃。无论是功能还是性能方面,与现代的消息队列都存在明显的差异,存在的意义仅限于兼容一些老系统。

2、ZeroMQ

​ 严格来说 ZeroMQ 并不能称之为一个消息队列,而是一个基于消息队列的多线程网络库,如果你的需求是将消息队列的功能集成到你的系统进程中,可以考虑使用 ZeroMQ。

3、Pulsar

​ Pulsar是一个相对较新的开源消息队列系统,最初由Yahoo开发,目前仍处于不断成长和发展的阶段。与其他传统消息队列系统最显著的不同之处在于其采用了存储和计算分离的设计思想。不少人比较喜欢这种设计,它有可能会引领未来消息队列的一个发展方向。

总结

​ 根据上述多种消息队列的讲解,对于消息队列的选择肯定已经心中有数了,下面给出几点意见:

  • 如果你的系统中消息队列不是主要部分,且对消息队列的功能和性能没有很高的要求,只需要用一个开箱即用易于维护的产品,则开源使用 RabbitMQ
  • 如果你的系统使用消息队列的场景是处理在线业务,比如交易系统中用消息队列传递订单,那么 RocketMQ低延迟和稳定性是比较推荐的
  • 如果需要处理海量的消息,像收集日志、监控信息或是你的应用场景使用了大数据、流计算相关的开源产品,那 Kafka 是最适合你的消息队列。

如何选择消息队列?
http://example.com/2023/10/25/MQ/如何选择消息队列?/
作者
Feng Tao
发布于
2023年10月25日
更新于
2023年10月25日
许可协议