深入了解 Kafka 和 Pulsar 的区别

在本篇博文中,我们将深入探讨 Apache Kafka 和 Apache Pulsar 之间的主要区别。通过研究这两个消息传递系统的核心区别和独特功能,我们希望让您初步了解它们的核心机制和实现。我们希望这种分析不仅能帮助您在两者之间做出选择时做出明智的决定,而且还能作为宝贵的资源来支持进一步探索和理解它们的功能。

MQ 与 Pub/Sub

在深入探讨 Pulsar 和 Kafka 之间的区别之前,让我们先回顾一下 Message Queues 的历史背景。我们相信,这些背景信息有助于您理解为什么 Kafka 和 Pulsar 中的某些功能是以特定的方式设计的。

消息队列 (MQ) 和发布-订阅 (Pub/Sub) 是两种流行的消息传递模型。MQ 具有简单的逻辑,具有悠久的历史,存在于从数据结构到操作系统流水线的各个领域。MQ 由一个队列组成,该队列在发送方和接收方之间保存消息。消息管道的特征包括:

  • 无数据存储
  • 无数据保留
  • 无消费状态跟踪(光标)

然而,在大数据时代,这种"一次读即删"的模式(发布一次、消费一次、删除一次)已经无法满足数据繁荣的需求。单个消息队列的吞吐量有限;当数据量超过单个队列的容量时,我们需要多个业务部门(队列)来处理数据。这是一种常见的分布式模型,此类队列也称为消息代理。

代理是处理消息的程序,充当彼此独立的中介。当我们有多个代理时,每个代理都会处理一部分数据。如果数据没有顺序要求,则处理逻辑非常简单。这类似于 MapReduce,它允许您在再次聚合之前对问题进行划分和单独处理。当数据量达到一定水平时,这是一个经典的解决方案。

Pub/Sub 模型的成熟度

随着数据量的增长,越来越多的业务场景需要分布式处理。数据可能来自多个生产者,并且只有一个使用者使用数据。

那么,我们是如何处理这个新模型的呢?简单地说,为了处理大约 80% 的 MQ 场景(海量数据处理),该模型被抽象出来,以推动专门用于分布式处理的新产品的开发,包括 Apache Kafka。

这种新模式带来了新的市场机遇,同时也面临着新的挑战,包括:

  • 海量数据存储、消费状态跟踪(游标)和中间状态存储。
  • 延迟读取、重复读取、多次读取和从特定位置读取。
  • 消费隔离和资源管理
  • 实时处理、高吞吐量、低延迟
  • 事务
  • 高扩展性
  • 企业功能和安全性

为了提供一个更具体的例子,考虑一个电信供应商,它需要从全国用户那里收集某些数据。由于数据量巨大,不可能直接从所有用户那里收集它们。另一种解决方案是按区域对数据进行分区。在为每个分区独立收集数据后,可以对数据进行聚合。这种模式在当今的消息传递中间件解决方案中非常普遍,并导致了行业先驱 Kafka 的出现。

Kafka 在早期确实面临一些挑战,并不断发展以满足市场需求。今天,Kafka 被认为是大数据时代事实上的领导者或"潮汐骑士"。

Kafka:潮汐骑士

Apache Kafka 实现了一个经典的分布式系统。为了处理数据分区,Kafka 将整个分区数据存储在每个节点(即 Broker)中,该节点负责计算和存储。一个分区可以有多个副本,相应的副本同时存储在分区领导者和同步副本 (ISR) 中。这种开创性的分布式处理方法有效地解决了 Kafka 诞生时的一系列挑战,例如峰值削波和异步通信。具有高性能(高吞吐、低时延)和数据持久化等特点,满足大数据时代的数据迁移需求。

多年来,由于蓬勃发展的开源社区和商业公司支持该项目,一个全面的 Kafka 生态系统已经形成。许多大大小小的企业都认可了 Kafka,这充分说明了它作为一个产品的成熟度。

虽然 Kafka 的简单架构使其能够快速发展并抢占先机,但它也为适应不同场景的潜在困难留下了空间。其中一些挑战包括:

  • 重新平衡的痛苦
  • 难以扩展代理、主题、分区和副本
  • 代理故障处理
  • 延迟和抖动
  • 企业级功能
  • 云迁移

Kafka 出现在 2010 年左右,当时正值大数据的最初爆炸式增长时期。随着数据量在随后的几年中持续增长,功能要求和易用性变得越来越重要。更重要的是,"云原生"的概念开始受到关注,这预示着 Kafka 的新挑战者,Apache Pulsar 就是其中的佼佼者。

Pulsar:为云原生而生

Kafka 的经典架构启发了许多后继者,包括 Apache Pulsar。作为面向云原生环境的下一代消息传递平台,Pulsar 拥有用于计算和存储的解耦架构。

Pulsar broker 作为计算层,而存储则由另一个 Apache 顶级项目 Apache BookKeeper 支持,Apache BookKeeper 是一个分布式预写日志 (WAL) 系统。BookKeeper 可以有效地处理大量数据存储任务,元数据来源于 ZooKeeper。

Pulsar 的分层架构、云原生兼容性以及多租户等开源企业特性,为用户在生产中提供了更多的可能性。然而,其复杂的结构也意味着更高的学习成本和就业市场上缺乏人才。这也是为什么像腾讯这样的大型科技公司已经认可了Pulsar,但较小的公司一直在努力采用它的原因。

与 Kafka 相比,Pulsar 还有很长的路要走,尤其是在其生态系统方面,但它自成立以来一直保持着强劲的势头。

  • 2012 年:雅虎内部开发!
  • 2016 年:在 Apache 2.0 许可下开源
  • 2018 年:成为 Apache 顶级项目 (TLP)
  • 2023:600+ 贡献者,12.5K+ Stars,3.3K+ Forks

2021 年,Pulsar 的月活跃贡献者数量超过了 Kafka。在成为 TLP 的相差 5 年的情况下(2013 年的 Kafka 和 2018 年的 Pulsar),Pulsar 如何解决 Kafka 的痛点?它们之间有哪些主要区别?有了上面的背景信息,让我们更详细地回顾一下这些问题。

代理和分区:是否解耦

第一个主要区别是两个系统如何处理代理和分区之间的关系。Kafka 的分区和代理是紧密耦合的。当生产者将数据发布到 Kafka 集群时,数据会写入分区。每个分区都有一个领导节点,该节点具有多个(或零个)跟随节点,这些节点在领导节点发生故障时复制数据。

这种做法最困难的部分是分区的数据迁移。如果 Kafka 分区中有大量数据,则迁移过程可能是一场噩梦。分区和代理之间的强耦合关系,在某种程度上导致了 Kafka 中的一系列其他问题。

相比之下,分区和代理在 Pulsar 中是松散耦合的。一个分区可以进一步划分为多个段,这允许跨多个存储节点(i.e. bookies)对条目进行条带化。换句话说,单个分区中的数据可以存储在具有多个副本的多个节点中。

在上图中,分区 1 中有许多剥离的数据段,段 1 在 Bookie 1、Bookie 2 和 Bookie 4 中可能有副本。如果其中一个 Broker 失败,对分区的影响是微不足道的,因为它可能只影响一个或几个部分。此外,与整个分区的数据丢失相比,恢复过程要快得多。

当 Kafka 在十多年前发展起来时,它需要快速增长,并没有优先考虑细粒度的数据存储和管理。相比之下,Pulsar 在这方面提供了更复杂的方式,为其未来的增长带来了更大的空间。

可扩展性

可伸缩性是区分这两种邮件系统的另一个关键因素。

在 Kafka 中,您有多个代理来接收数据(一个领导者具有多个 ISR)。如果发生节点故障,则该代理上的分区将丢失。它需要手动维护(或脚本)进行恢复,并且逻辑相对复杂。您不能简单地将其替换为新的代理,并且以前的代理 ID 无法自动转移。

另一个麻烦是,新代理无法立即处理旧代理的流量,因为新代理没有分区。您需要手动将旧分区迁移到代理。但是,如果数据量很大,则迁移可能会很麻烦,如上一节所述。

那么,Pulsar 是如何处理同样问题的呢?

如果 Pulsar broker 发生故障,它将失去之前持有的分区的所有权,该分区的信息存储在 ZooKeeper 中。检测到更改后,其他经纪人会重新选择新的经纪人。对于整个 Pulsar 集群来说,代理故障并不是一个重大问题,因为另一个代理可以快速接管。

这个过程的效率在于 Pulsar 经纪人是无状态的。当代理出现故障时,可以立即扩展代理集群。代理不存储数据,仅作为计算层。Broker 存储数据,他们甚至不需要知道经纪人方面发生了什么。

在 Pulsar 中丢失热分区的影响远小于 Kafka,恢复速度也快得多。如果需要提升集群处理消息的能力,只需添加 broker 即可,无需担心存储层。

热点传输

在 Kafka 和 Pulsar 中,broker 处理流量热点的能力和方法不同。

在 Kafka 中,当代理的写入负载很重时,增加代理的数量无济于事,因为一次只有一个代理可以处理写入。如果代理有大量读取,则添加新的代理也不起作用,因为其中没有分区。如前所述,重新平衡流量是另一个棘手的问题。

通常,有两种解决方案可用于处理 Kafka 中的流量热点:

  1. 增加分区数量会带来很大的重新平衡困难。
  2. 扩大代理规模以提高其性能。如果代理发生故障,则需要使用另一个代理来处理繁重的流量,这也需要纵向扩展(最终是整个集群),使其成为一种成本低效的方法。

在 Pulsar 中,写入热点会导致大量剥离的段。随着写入的数据越来越多,经纪人会生成更多的细分市场,并将它们分配给多个 Broker。如有必要,Broker 集群可以简单地横向扩展以存储新添加的区段(在 BookKeeper 中也称为账本)。

对于读取热点,Pulsar 依赖于 bundle,每个 bundle 包含多个主题来处理客户端请求。每个捆绑包都分配给特定的代理。捆绑包提供了一种负载平衡机制,允许将超过某些预配置阈值(例如,主题计数和带宽)的捆绑包拆分为两个新捆绑包,其中一个捆绑包将卸载到新的代理。

写入和读取实现

Kafka 和 Pulsar 如何写入和读取请求直接关系到它们的延迟和抖动,这是选择消息传递系统时的两个重要因素。

Kafka 中的写入严重依赖于操作系统的页面缓存。数据直接写入页面缓存(内存),然后异步写入磁盘。Kafka 利用零复制原则,允许数据直接从内存传输到磁盘文件。换言之,Kafka 代理不需要分配额外的单独位置来存储数据。

但是,Kafka 对页面缓存的严重依赖可能会导致问题。在追赶读取方案中,从文件中读取历史数据需要将数据加载回内存。这可能会从缓存中逐出未读的拖尾读取(最新数据),从而导致内存和磁盘之间的交换效率低下。这可能会影响系统稳定性、延迟和吞吐量。

Pulsar 以不同的方式处理数据读取和写入。Pulsar 代理充当 BookKeeper 客户端,将数据写入账本。该过程涉及将数据作为预写日志写入日志文件(内存),然后以异步和顺序将数据写入日志磁盘。这提供了事务管理并确保数据持久性,允许在出现问题时快速回滚。

Pulsar 不使用 Zero Copy,而是依赖于 JVM 堆外内存。记录事务日志时,数据会进入写入缓存,然后存储在两个位置:条目日志缓存(数据异步写入账本磁盘)和账本缓存(数据异步写入索引磁盘(存储在 RocksDB 中)。

对于 Pulsar 中的读取,如果消费者需要读取数据,并且它恰好在内存中(在写入缓存中命中,这通常是拖尾读取的情况),则可以直接访问它。如果数据不在写入缓存中,则从读取缓存中读取数据。否则,会根据 RocksDB 中存储的索引从磁盘中读取数据。检索数据后,数据将写回读取缓存。这可确保下次请求数据时,很有可能在读缓存中找到该数据。

诚然,读取过程涉及许多组件,这可能会导致额外的网络开销和优化难度,有时查明有问题的组件可能具有挑战性。尽管如此,它带来的好处是相当明显的。这种多层架构允许在各个级别进行稳定的数据检索,并且其 JVM 堆外内存管理具有高度可控性(与 Kafka 相比,Pulsar 对内存的依赖更少)。

Kafka 和 Pulsar 中处理读写的不同方法导致了延迟和整个过程中的不同功能。

如下图所示,在大多数情况下,Kafka 在写入页面缓存时延迟较低,并且内存足够大来处理数据。但是,如果数据消耗速度较慢,并且内存中仍有大量数据,则需要将数据大块交换到磁盘上。如果磁盘速度无法与内存匹配(在大多数情况下都是如此),则会出现明显的延迟峰值,因为在内存数据交换到磁盘之前无法写入传入数据。这会导致抖动,这在延迟敏感的场景中可能很危险。虽然 Pulsar 的延迟可能不比 Kafka 低,但它的稳定性明显更好。即使有额外的组件和一些性能损失,Pulsar 的整体稳定性也值得权衡。

吞吐量是 Pulsar 的强项。其剥离存储可实现最大的吞吐量性能。从理论上讲,broker 的数量决定了将数据写入磁盘的速度,而磁盘又决定了 Pulsar 的吞吐量。相比之下,Kafka 的吞吐量受到单个 broker 节点写入速度的限制,因此 Pulsar 的吞吐量通常优于 Kafka。

企业级功能

现在我们已经讨论了 Kafka 和 Pulsar 为解决流媒体和消息传递中的一些常见问题而采取的不同方法,让我们从高层次上回顾一下它们为企业提供的功能。

|------------|-----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| | Kafka | Pulsar |
| 多租户 | 单租户系统 | 内置多租户 |
| 数据迁移 | 依赖于 Mirror Maker,需要额外的维护。市场上也有 Confluent Replicator 等供应商工具。 | 内置异地复制,开源、稳定且易于维护。 |
| 分层存储 | 由供应商提供用于商业用途。 | 内置分层存储,支持将冷数据移动到更便宜的存储选项,例如 AWS S3 或 Google Cloud Storage。 |
| 组件依赖关系 | Kafka Raft (KRaft) 从 Kafka 2.8 开始处于抢先体验模式,允许 Kafka 在没有 ZooKeeper 的情况下工作。这对 Kafka 来说是一个显著的优势,因为它简化了 Kafka 的架构并降低了学习成本。 | 对 Pulsar 的一个常见批评是它对 ZooKeeper 的强烈依赖,以及需要维护额外的存储系统,这需要操作员掌握更多的技能。 |
| 云原生部署 | 比较复杂 | 专为云原生环境而生,因为 Pulsar 将计算与存储分开。企业可以通过 Helm 或 StreamNative Pulsar Operator 在 Kubernetes 上安装 Pulsar。 |
| 生态系统 | 一个蓬勃发展的生态系统,拥有各种工具,例如连接器。 | 一个不断增长的生态系统,但与 Kafka 的生态系统相比,它要小得多。StreamNative 一直在努力创建一个 StreamNative Hub 来存储 Pulsar 的生态系统工具。 |
| 人才 | 大量专业人士专注于 Kafka 及其生态系统,使其成为选择 Kafka 的关键因素。 | 缺乏 Pulsar 专业人员和专家。 |

此表仅列出了企业可能感兴趣的一些关键差异。Pulsar 还具有其他独特的企业功能,例如灵活的订阅模式(独占、故障转移、共享和key_shared)和选择性确认。

结论

我们通常不会仅仅根据一两个因素做出技术选择。即使一个产品没有严重的缺陷或弱点,我们仍然需要进行更全面的评估。Kafka 和 Pulsar 从一开始就走了不同的道路。Kafka 在大数据领域拥有更多的先发优势,在人才库和生态方面无与伦比。不过,它的架构比较老旧,在云原生时代,面对有前途的新人 Pulsar,它的竞争力已经下滑。我们希望本文能帮助您更好地了解这两个系统,并在中间件选择过程中做出更明智的决策。

相关推荐
WX187021128737 小时前
在分布式光伏电站如何进行电能质量的治理?
分布式
Stringzhua7 小时前
【SpringCloud】Kafka消息中间件
spring·spring cloud·kafka
不能再留遗憾了10 小时前
RabbitMQ 高级特性——消息分发
分布式·rabbitmq·ruby
茶馆大橘10 小时前
微服务系列六:分布式事务与seata
分布式·docker·微服务·nacos·seata·springcloud
材料苦逼不会梦到计算机白富美13 小时前
golang分布式缓存项目 Day 1
分布式·缓存·golang
想进大厂的小王13 小时前
项目架构介绍以及Spring cloud、redis、mq 等组件的基本认识
redis·分布式·后端·spring cloud·微服务·架构
Java 第一深情13 小时前
高性能分布式缓存Redis-数据管理与性能提升之道
redis·分布式·缓存
杨荧14 小时前
【JAVA毕业设计】基于Vue和SpringBoot的服装商城系统学科竞赛管理系统
java·开发语言·vue.js·spring boot·spring cloud·java-ee·kafka
ZHOU西口14 小时前
微服务实战系列之玩转Docker(十八)
分布式·docker·云原生·架构·数据安全·etcd·rbac
zmd-zk15 小时前
kafka+zookeeper的搭建
大数据·分布式·zookeeper·中间件·kafka