清华主页 - 清华新闻 - 综合时讯 - 正文

Kafka 和 RabitMQ用哪个?一篇文章告诉你他们的区别

人们经常问我。

有个 xx 要求,我应该用 Kafka 还是 RabbitMQ ?
这个问题很常见󿀌而且许多人对两者的选择也没有很好的把握。

所以我决定写一篇文章来详细说明:Kafka 和 RabbitMQ 区别,什么场景适合#xff1f;

同时,面试中经常会问到这个问题。

下面我会通过的 6 场景,对比分析一下 Kafka 和 RabbitMQ 的优劣。

一、消息顺序。

有这样的需求:当订单状态发生变化时,向所有关心订单变化的系统发送订单状态变化的信息。

订单将创建成功、待付款、已付款、已发货的状态,这种状态是单向流动的。

好,现在我们将订单状态变化的消息发送给所有关心订单状态的系统,实现的方法是使用消息队列。

在这种业务下󿀌我们最想要的是什么?

  1. 新闻顺序:对于同一个订单,状态变化有严格的顺序。

  2. 吞吐量:类似于订单业务,我们自然希望订单越多越好。订单越多󿀌吞吐量越大。

在这种情况下󿀌我们先看看 RabbitMQ 是怎么做的。

首先,发消息󿼌并向多个消费者广播这种情况󿀌RabbitMQ 它将为每个消费者建立相应的队列。也就是说,�如果有 10 个人消费者󿀌RabbitMQ 会建立 10 对应的队列。然后,当一条消息发出时,RabbitMQ 这条消息将被复制 10 份放到这 10 个队列里。

当 RabbitMQ 将信息放入相应的队列后,我们面临的问题是,从消息队列中获取消息,我们应该在系统内启动多少线程。

如果只是单线程获取消息,自然没什么好说的。但是多线程情况󿀌可能会有问题......

RabbitMQ 有这样的特点,它在官方文档中声明,它不能保证同一队列的多线程消费,一定要保证顺序。不保证的原因,这是因为多线程时间,当线程消费信息报错时,RabbitMQ 消费失败的消息将再次进入团队,此时可能会出现乱序。

T0 时间,队列中有四条消息 A1、B1、B2、A2。其中 A1、A2 表示订单 A 两种状态:待付款,已付款。B1、B2 同样,是订单 B 待付款,已付款。

到了 T1 时刻,消息 A1 被线程 1 收到,消息 B1 被线程 2 收到。此时,一切都很正常。

到了 T3 时刻,B1 消费出错,同时,由于线程 1 处理速度快󿀌从消息队列中获取 B2。此时,问题开始出现。

到了 T4 时刻,由于 RabbitMQ 线程消费错误󿀌新闻可以重新入队的特点,此时 B1 队列头部将被重新放置。所以,如果不巧󿀌线程 1 获取到了 B1,乱序发生,B2 状态明明是 B1 后续状态,但是提前处理好了。

所以,你可以看到,这个场景用 RabbitMQ,三个问题:

  1. 发布订阅功能,复制使用的信息,降低性能,消耗更多资源。
  2. 许多消费者无法严格保证消息顺序。
  3. 大量订单集中在一个队列࿰上c;吞吐量有限。

那么 Kafka 怎么样󿄟Kafka 就在这三个问题上,表现的要比 RabbitMQ 要好得多。

首先,Kafka 发布订阅不会复制新闻,因为 Kafka 发布订阅是指消费者直接获取订阅 Kafka 将消息保存在日志文件中。无论有多少消费者,他们只需要主动在文件中找到消息的位置。

二是,Kafka 消费者出错后不会出现,将新闻重新入队的现象。

最终,Kafka 订单可以分区,将不同的订单保存在多个分区中c;这样,吞吐量可以更好。

所以,对此需求 Kafka 更合适。

二、新闻匹配。

我曾经做过一套营销系统。这个系统有一个非常显著的特点,匹配规则非常复杂和灵活。

例如,宣传应根据推广内容以不同的方式进行匹配。再比如,分发应根据不同的活动匹配不同的渠道。

总之,在这个系统中,无数的匹配规则是一个非常重要的特征。

首先,先看看 RabbitMQ ,你会发现 RabbitMQ 允许在新闻中添加 routing_key 或者定制信息头�然后通过一些特殊的 Exchange,新闻匹配分发的实现非常简单。开发几乎没有成本。

而 Kafka ?如果要实现消息匹配󿀌开发成本要高得多。

首先,不可能通过简单的配置自动匹配和分发给合适的消费者端。

二是,不管需要不需要,消费者必须首先要把所有的消息都放在#xff0上c;都取出来。然后,然后根据业务需求󿀌实现各种准确和模糊的匹配。也许是因为过度的复杂性,还需要引入规则引擎。

这个场景下 RabbitMQ 扳回一分。

三、信息超时。

电子商务业务,需求:下单后,如果用户在 15 分钟内未支付�订单自动取消。

你可能会奇怪󿀌这种消息队列ñ怎么用?f;

先简单解释一下,单一服务系统,定时任务可以完成。

但是,在 SOA 或者在微服务架构下󿀌这样做是不可能的。因为很多服务都关心是否支付#xff0c;如果每个服务󿀌实现一套定时任务的逻辑,重复,又难以维护。

在这种情况下󿀌我们经常做一层抽象:将要执行的任务包装成新闻。时间到了󿼌直接扔进消息队列󿀌获取消息后的订阅者,可以直接执行。

希望将消息推迟一定时间处理,被称为延迟队列。

这类业务的订单取消,在创建订单时,我们将,同时,向延迟队列࿰投掷包含执行任务信息的信息c;指定15分钟后,让所有订阅这个队列的消费者,你可以收到这个消息。随后,所有消费者所在的系统都可以执行扫描订单的相关任务。

RabbitMQ 和 Kafka 如何选择新闻队列?

先看下 RabbitMQ 的。

RabbitMQ 自带手表࿰的消息c;消息中有个 TTL 字段,可以设置消息 RabbitMQ 存储时间,超时会被转移到一个叫死信队列的地方。

所以,延迟队列 RabbitMQ 最简单的实现方法是设置 TTL,然后一个消费者去监控死信队列。当消息超时,监控死信队列的消费者收到消息。

但是,这样做有个大问题:假设,我们先把一个过期时间放在队列里 10 秒的 A 新闻,再次放一个过期时间是 5 秒的 B 消息。 所以问题来了,B 消息会先于 A 消息进入死信队列,#xff1f;

答案是否定的。B 新闻将优先遵守先进先出的队列规则,在 A 新闻过期后󿀌与之一起进入死信队列被消费者消费。

在 RabbitMQ 的 3.5.8 版本后󿀌官方推荐的 rabbitmq delayed message exchange 插件可以解决这个问题。

  • 使用此插件,当我们发送消息时,把消息发送到一个特殊的地方 Exchange。
  • 同时,在消息头指定延迟时间。
  • 收到消息的 Exchange 不会马上把消息放在队列里,相反,在消息延迟到达后,只有这样才能把消息放进去。

再看下 Kafka :

Kafka 实现延迟队列非常麻烦。

  • 首先,你需要把消息放在一个临时的位置 topic。
  • 然后你必须开发自己的中转消费者。让中间的消费者从这个临时消息开始 topic 取出来。
  • 取出,这个消息不能马上处理,因为没有时间。也不能保存在自己的内存中,害怕崩溃,消息没了。所以,不到时间的消息必须存储在数据库中。
  • 存储在数据库中的消息需要在时间到达后放入 Kafka 里,让真正的消费者实现真正的业务逻辑。
  • ……。

想想就大了,这几乎是一个调度平台。再高级点󿀌需要时间轮算法才能更好更准确。

这次,RabbitMQ 上一个戴手表的消息,是最好的选择。

四、保留消息。

微服务,常用的事件溯源模式。如果你想用信息队列实现󿀌事件通常被视为新闻,依次发送到消息队列。

事件溯源有最经典的场景,这是事件的重放。简单来说,就是在处理之前依次取出系统中一段时间发生的事件。而且,不同的业务场景󿀌这些事件很可能不是一次性重放的,更有可能是重复 N 次。

假设,我们现在需要一批在线事件重播󿀌调查一些问题。

RabbitMQ 这个时候真的不行,因为消息被拿出来就被删除了。想再次被重复消费?对不起。

而 Kafka ,在一份特殊的日志文件中,新闻将持续下去。不会因为被消费而被删除。

所以,永不放弃消息 Kafka 使用后相对抛掷 RabbitMQ,请选择 Kafka。

五、错误处理消息。

很多时候�在记录数据相关业务时,Kafka 一般是最好的选择。但是,有时候记录数据吞吐量不大的时候,我更喜欢自己用 RabbitMQ。

原因就是 Kafka 有一个我不喜欢的设计原则:

一旦单个分区的消息失败,我们只能停下来,而不是跳过这个失败的消息,继续消费后面的消息。也就是说,消息不允许空洞。

只要消息失败,不管是 Kafka 损坏自己的消息格式,还是消费者处理异常󿀌未来不允许跳过消费失败的消息继续消费。

所以,在。不需要非常准确的数据统计。选择了场景 Kafka,一旦出现消息消费问题,项目不可用的情况会发生。这真是徒增烦恼。

而 RabbitMQ ,当消息出现问题或消费错误时,它会,您可以重新加入或移动消息到死信队列,继续消费后面的,会省心很多。

坏消息就像群众中的坏人,Kafka 处理这个坏蛋太残忍了#xff0c;一定要把坏蛋拉出来。相对而言,,RabbitMQ 就温柔多了,群众󿼌坏蛋�分开处理。

六、新闻吞吐量。

Kafka 每秒几十万消息吞吐,而 RabbitMQ 吞吐量是每秒数万条新闻。

事实上,公司内部󿀌有必须用到 Kafka 那么大吞吐量的项目真的很少。大部分项目󿀌像 RabbitMQ 每秒吞吐成千上万的消息,已经够了。

在一些吞吐量较小的项目中引入 Kafka,我认为最好介绍一下 RabbitMQ。

为什么?

因为 Kafka 为更好的吞吐量,在很大程度上增加了你的复杂性。对于项目来说,这些复杂性是#xff0c;麻烦,主要体现在两个方面::

1、复杂的配置和维护。

Kafka 参数配置相对 RabbitMQ 很复杂。例如:磁盘管理相关参数,集群管理相关参数,ZooKeeper xff00交互相关参数c;Topic 等级相关参数等都需要一些思考和调优。

另外,Kafka 自身集群和参与管理集群的集群 ZooKeeper,这就带来了更多的维护成本。Kafka 用好,你要考虑 JVM,持久消息,集群本身的互动#xff00c;以及 ZooKeeper 本身和它与 Kafka 它们之间的可靠性和效率。

2、用好,使用正确的存在门槛。

Kafka 的 Producer 和 Consumer 使用好本身也有很高的门槛。

例如,Producer 信息可靠性保证、权等性、事务信息等,都需要对 KafkaProducer 有深入的了解。

而 Consumer 更不用说࿰了c;光是日志偏移管理就让很多人掉了很多头发。

相对而言,,RabbitMQ 就简单多了。你可能不需要配置任何,直接启动可以稳定可靠地使用。即使配置�也可以设置几个参数。

所以,当每个人都在项目中引入新闻队列时,真的要好好想想,不要因为大家都提倡而提倡 Kafka 好,无脑引入。

总结。

你可以看到�如果我们想做消息队列选择,有两件事必须做好:

  1. 列出业务最重要的特点。

  2. 深入比较消息队列的细节。

在我们非常熟悉这些中间件的特性之后,甚至可以将业务分解为不同的子业务,然后根据不同子业务的特点,引入不同的信息队列,也就是说,消息队列混用。这样,我们可能会最大化我们的利益,最小化我们的成本。

说了这么多,其实还是有很多的 Kafka 和 RabbitMQ 比较没有说,例如,两个集群的区别,占用资源的比较等。以后有机会再提。

总之,期待大家看完这篇文章后󿀌能对 Kafka 和 RabbitMQ 对差异有了更详细的了解。

最后,在网上分享一个比较完整的对比图:

2025-06-24 12:02:53

相关新闻

清华大学新闻中心版权所有,清华大学新闻网编辑部维护,电子信箱: news@tsinghua.edu.cn
Copyright 2001-2020 news.tsinghua.edu.cn. All rights reserved.