在分布式架构中,系统之间的通信构成了整个基础设施的基础。基础设施的性能、可扩展性和可靠性很大程度上取决于事件/消息/数据的交换和持久化方式。
Kafka 和 NATS 是处理流式数据和消息的两个流行工具。它们具有不同的架构和不同的性能特征。它们适用于特定的使用案例。在本文中,我们将比较 NATS 与 Kafka 的特性,并解释我在工作中处理的使用案例。
1. 架构和复杂性
NATS
NATS 基础设施有两个主要组件:
Core NATS
Core NATS 是基础消息框架。它支持发布-订阅(允许消息广播到多个订阅者)、请求-响应(实现同步通信)和队列组(在组内实现多个订阅者之间的负载均衡)。
它设计用于简单性、低延迟、高性能和可扩展性。在需要低延迟和高吞吐量的场景中表现非常出色。然而,Core NATS 仅提供非保证交付,意味着消息仅传递给活跃的订阅者。如果订阅者离线,数据将会丢失。当速度和规模优先于持久性时,Core NATS 是一个不错的选择。
JetStream
JetStream 为 Core NATS 带来了持久性功能。这有助于提供消息的耐久性和可靠性。它允许消息或事件被持久化(磁盘或内存)并可以重放。持久化的消息可以重放给新的或恢复中的订阅者。使用 JetStream,用户可以获得额外的功能:
- 流保留:消息被保留的时间。可以基于大小、时间或消费者限制。
- 消费者耐久性:使消费者能够从上次中断的地方恢复。
- 消息确认:确保交付的可靠性。
JetStream 为 Core NATS 增加了一层复杂性。然而,这带来了支持保证交付、持久性和重放性用例的重要特性。
Kafka
Kafka 是建立在基于日志的经纪人架构上的分布式消息系统。Kafka中的数据被安排到主题中,并可以有多个分区。消费者连接到这些分区。这种架构允许Kafka对单个主题进行消息消费的并行化。数据按顺序附加到主题/分区。Kafka保证分区内的顺序。在Kafka集群中,可以有许多经纪人,每个经纪人管理一个主题和分区列表。为了实现高可用性和防止数据丢失,Kafka依赖于复制因子,其中分区在多个Kafka经纪人之间复制。正如您所看到的,有多个组件必须管理才能实现高吞吐量、容错性、数据保留和横向扩展性。这增加了Kafka的架构复杂性。
2. 高可用性和性能
NATS
集群中的所有节点都以网格形式相互连接,客户端可以连接到任何节点。这种配置避免了单点故障。如果一个节点失败,客户端会自动连接到其他节点,无需任何手动干预。这被称为NATS中的自愈。启用JetStream的节点在所有节点之间分配流。流在网格集群中的JetStream启用节点之间高度管理和负载平衡。
JetStream还支持在多个集群或节点之间进行数据镜像。在JetStream中,每个流都选出领导者。可以配置每个流的复制。所有这些措施都确保了NATS中的耐用性和可用性。
Kafka
Kafka的高可用性基于复制。每个主题可以有一个或多个分区。每个分区在Kafka Broker之间进行复制。这确保了数据的冗余和可用性。Kafka遵循领导者-跟随者的复制机制。领导者负责读取和写入,而跟随者负责复制数据。
Kafka为每个分区维护了一种称为ISR(同步副本)的机制。如果领导者发生故障,ISRs中的一个将成为领导者。对于集群元数据管理和领导者选举,Kafka依赖于Zookeeper(在较新版本中为KRaft)。
Performance and Scalability
|
||
---|---|---|
特性
|
NATS
|
Kafka
|
吞吐量
|
高或低延迟。针对小消息进行了优化
|
针对高吞吐量和大消息进行了优化
|
扩展性
|
支持横向扩展和集群
|
支持横向扩展和分区
|
延迟
|
低于毫秒
|
毫秒
|
Recovery and FAILOver
|
||
---|---|---|
特性
|
NATS
|
Kafka
|
故障转移时间
|
亚秒级(客户端重新连接更快)
|
较慢(取决于领导者选举过程)
|
无缝恢复
|
客户端自动连接,无中断
|
部分中断在领导者选举期间
|
数据丢失风险
|
通过复制(JetStream)最小
|
如果配置了复制和ISR,风险最小
|
3. 消息模式
NATS
NATS使用基于主题的消息传递。这使得服务和流可以使用发布-订阅、请求-响应和队列订阅者模式。NATS中的主题可以构建层次结构和通配符。单个NATS流可以存储多个主题,客户端应用程序可以使用服务器端过滤来仅接收感兴趣的主题。NATS中的连接是双向的,允许客户端同时发布和订阅。NATS还支持类似于RabbitMQ的队列。
Kafka
Kafka中的流支持发布订阅和基于主题的消息传递。通过消费者组和对主题进行分区可以实现负载均衡。
4. 传递保证
NATS
NATS支持各种传递保证。NATS本身可以支持至多一次的传递保证。启用JetStream的NATS服务器可以支持另外两种类型的保证,即“至少一次”和“恰好一次”的保证。NATS可以向单独的消息发送“确认”。请参考NATS官方文档以了解它支持的各种“确认”类型。根据“确认”类型,NATS可以重新传递消息。
Kafka
Kafka支持至少一次和恰好一次的保证。消息排序在分区级别上是有保证的。在Kafka中不可能实现全局排序。
5. 消息保留和持久化
NATS
NATS支持基于内存和文件的持久化。有几种选项可以重放消息。消息的重放可以通过时间、计数或序列号进行。
Kafka
KAFKA仅支持基于文件的持久化。消息可以从最新、最早或特定偏移量进行重放。KAFKA支持日志压缩。
6. 语言和平台
NATS
四十八种已知的客户端类型。任何支持GOLANG的架构都可以支持NATS服务器。
Kafka
十八种已知的客户端类型。Kafka服务器可以在支持JVM的平台上运行。
使用案例
使用案例 1
需求
我们有一个带有流水线的数据平台。该平台使用Apache Flink引擎进行实时流处理,使用Apache Beam编写分析流水线。以下是关键需求:
- 高吞吐量和低延迟的消息处理
- 支持检查点和背压处理
- 处理以MB为单位的消息
- 消息的持久性和持久化
比较
Kafka优势s:
- 高吞吐量
- 具有可配置的保留策略并为容错性复制数据的数据保留
- 支持至少一种消息传递保证
- 从最早/最新/特定偏移量读取消息
- 服务器端的‘acks’以确保可靠传递
- 处理大规模数据流和大消息大小
- 支持Compaction主题
Kafka缺点:
- 高资源使用。我们的集群是在本地且资源受限
- Kafka 仅支持近实时
NATS 的优点:
- 高性能且资源使用最小。我们的集群是在本地且资源受限
- 支持至少一次。我们正在寻找至少一次的保证
- 低延迟消息处理
NATS 的缺点:
- 没有用于 Flink/Beam 的连接器,因此集成比较困难
- 随着消息大小的增加性能下降
最终决定
经过仔细分析,选择了 Kafka。我们必须在资源使用和 Kafka 提供的其他好处之间做出权衡,特别是与 Apache Beam 和 Flink 的良好集成。Kafka 的另一个优点是其处理大消息尺寸和高吞吐量消息处理的能力。
用例 2
需求
处理在本地集群中生成的事件,例如:审计日志。事件应以低延迟进行处理,并支持微服务通信。耐久性和持久性不是要求。消息大小很小。无需对事件进行任何分析。我们处于一个受限的环境中。资源使用和内存占用应尽量减少。
决策
选择 NATS 的原因:
- 高效的资源使用
- 低延迟事件处理。
- 由于它是一个 Go 应用程序,内存占用量非常低
- 能够处理小消息大小
- 支持请求-回复,有助于微服务通信
- 当 JetStream 未配置时,消息不会被存储
为什么没有选择 Kafka:
- 默认情况下,消息会被存储在磁盘上
- 与 NATS 相比,资源使用率更高
- 由于需要 JVM,内存占用量非常高
总结
在 Kafka 和 NATS 之间的选择取决于三个关键领域的具体要求:架构与复杂性,性能与可伸缩性,消息传递保证。Kafka 适用于需要强大的事件流处理、持久存储和高级处理能力的系统,但复杂度更高。另一方面,NATS 轻量级,易于管理,在低延迟、高吞吐量场景中表现出色,适用于较简单的消息需求。
在设计分布式消息系统时,仔细评估这些领域,以使您的选择与应用程序的目标和限制相一致。Kafka 和 NATS 都是强大的工具,正确的选择将取决于您的用例。
在选择 Kafka 和 NATS 之间之前需要考虑的关键领域:
- 架构与复杂性
- 高可用性和性能
- 消息传递保证
Kafka 非常适合需要事件流处理、持久存储和先进处理能力的分布式系统。然而,Kafka 的资源使用率高,并且内存占用较大。而且,与 NATS 相比,管理复杂性非常高。
另一方面,NATS 轻量且易于管理。低延迟消息处理是 NATS 的标志性特性。
最终,Kafka 和 NATS 都是强大的事件处理工具。选择取决于具体的使用案例。
Source:
https://dzone.com/articles/kafka-vs-nats-message-processing