惊雷无声 发表于 前天 08:50

一文搞懂Kafka:原理、架构与实战案例全解析

一、弁言

https://i-blog.csdnimg.cn/direct/1f128c0b541549baa29b79ce03ceb8e1.png
在大数据蓬勃发展的期间,数据的快速处理与高效传输成为了技术发展的核心驱动力之一。Kafka,作为大数据领域中不可或缺的分布式流处理平台,正以其杰出的性能和强大的功能,引领着数据处理的新厘革。
Kafka 最初由 LinkedIn 公司开辟,并于 2011 年开源,随后敏捷成为 Apache 软件基金会的顶级项目,在全球范围内得到了广泛的应用和承认。它的诞生,旨在办理大数据环境下高并发、低延迟的数据传输与处理问题,为企业提供了一种可靠、高效的数据处明白决方案。
以电商行业为例,在促销活动期间,体系会产生海量的订单数据、用户举动数据等。这些数据必要被快速收集、传输和处理,以便企业能够实时掌握业务动态,做出精准的决议。Kafka 依附其高吞吐量的特性,能够轻松应对每秒数十万甚至数百万条消息的写入,确保数据不会丢失或积压。同时,通过与 Spark、Flink 等大数据处理框架的集成,Kafka 可以将实时数据快速传输给这些框架举行分析和处理,帮助企业实实际时的业务监控、用户举动分析、精准营销等功能。
再如,在日志收集与分析场景中,分布式体系中的各个组件会产生大量的日志数据。这些日志数据包含了体系运行状态、用户操作记载等重要信息,对于体系的运维和优化至关重要。Kafka 可以作为日志收集的中心枢纽,将各个节点的日志数据集中收集起来,并按照不同的主题举行分类存储。然后,通过 Kafka 的消息订阅机制,将日志数据发送给日志分析体系举行处理,帮助运维人员快速定位体系故障、分析用户举动、优化体系性能。
Kafka 以其独特的设计和强大的功能,在大数据领域中扮演着至关重要的角色。它不仅为企业提供了高效的数据传输和处理本领,还为大数据生态体系的构建和发展提供了结实的基础。在接下来的内容中,我们将深入探讨 Kafka 的核心概念、架构原理、利用场景以及实际应用案例,帮助读者全面相识和掌握这一强大的技术工具。
二、Kafka 是什么

Kafka 是一个分布式发布 - 订阅消息体系,最初由 LinkedIn 公司开辟,并于 2011 年开源,如今已是 Apache 软件基金会的顶级项目。它被设计用于处理大规模的实时数据流,具备高吞吐量、可扩展性、恒久性和容错性等显著特点,在大数据生态体系中占据着举足轻重的地位 。
诞生背景

Kafka 的诞生源于 LinkedIn 对高效数据管道体系的迫切需求。在当时,LinkedIn 面临着数据量快速增长、数据处理需求多样化以及现有消息体系性能瓶颈等问题。传统的消息队列,如 ActiveMQ,无法满足其对高吞吐量和低延迟的要求,尤其是在处理海量的活动流数据(如用户举动数据、页面访问数据等)和运营数据时,经常出现消息壅闭、服务不可用等状况。为了突破这些困境,LinkedIn 决定自主研发一个全新的消息传递体系,Kafka 应运而生。
发展历程



[*]开源初期(2011 - 2012 年):2010 年底,Kafka 开源到 GitHub,初始版本为 0.7.0。其新颖的设计理念和杰出的性能表现,敏捷吸引了浩繁开辟者的关注。2011 年 7 月,Kafka 因其潜力巨大,被纳入 Apache 孵化器项目,并在次年 10 月顺利结业,成为 Apache 顶级项目,这标志着 Kafka 正式进入开源社区的核心舞台,开始得到更广泛的应用和贡献。


[*]功能扩展期(2013 - 2016 年):在此期间,Kafka 不断丰富自身功能。社区陆续引入了很多关键特性,比如支持副本机制以加强数据的可靠性和容错性,优化了分区策略以提拔体系的扩展性和性能。同时,Kafka 开始与其他大数据组件,如 Hadoop、Spark 等举行深度集成,进一步拓展了其在大数据处理领域的应用场景,渐渐成为大数据生态体系中不可或缺的一环。


[*]流处理拓展期(2017 - 至今):从 0.10.0.0 版本开始,Kafka 推出了流处理组件 Kafka Streams,实现了从单纯的消息引擎体系向分布式流处理平台的富丽转身。此后,Kafka 持续迭代,不断提拔流处理本领,加强对复杂变乱处理、实时数据分析等场景的支持。如今,Kafka 已经广泛应用于各个行业,在数据采集、消息队列、实时数据处理等方面发挥着重要作用,其版本也在持续更新,功能日益强大和完善。
开源社区近况

Kafka 的开源社区极为生动,吸引了全球浩繁开辟者的到场和贡献。在 GitHub 上,Kafka 拥有大量的星标和关注者,社区成员积极提交接码、修复漏洞、提出新功能发起。社区还定期举办各类线上线下活动,如 Kafka Summit,为开辟者提供了交流经验、分享最佳实践的平台。浩繁公司基于 Kafka 举行二次开辟和应用拓展,形成了丰富的生态体系,包罗各种客户端库、工具、插件等,进一步推动了 Kafka 的普及和发展 。
Kafka 从诞生到如今,依附其不断演进的技术和生动的开源社区,已经成为大数据领域的明星项目,为无数企业和开辟者办理了数据处理和传输的难题,并且在未来仍有着巨大的发展潜力和创新空间。
三、Kafka 核心概念详解

3.1 Topic(主题)

在 Kafka 中,Topic(主题)是消息的逻辑分类单位,类似于数据库中的表,它为消息提供了一种分类和构造的方式。每个 Topic 都有一个唯一的名称,生产者将消息发布到特定的 Topic,而消费者则通过订阅感爱好的 Topic 来接收消息 。
比方,在一个电商体系中,可能会创建以下几个 Topic:


[*]订单相干主题:order_topic,用于存储全部的订单数据,包罗订单创建、支付、发货等状态变化的消息。当用户下单时,体系会向order_topic发送一条包含订单详细信息的消息,后续订单状态的每一次更新,如支付乐成、商品发货等,也都会产生相应的消息发送到该主题。如许,关注订单业务的服务(如订单处理服务、物流跟踪服务等)就可以通过订阅order_topic来获取相干信息,举行后续的业务处理。


[*]用户举动主题:user_behavior_topic,用于收集用户在电商平台上的各种举动数据,如用户登录、欣赏商品、添加购物车、品评商品等举动产生的消息。通过分析这些消息,电商平台可以相识用户的举动习惯和偏好,为精准营销、个性化推荐等业务提供数据支持。比方,推荐体系可以根据用户在user_behavior_topic中记载的欣赏和购买汗青,为用户推荐符合其爱好的商品。
创建一个 Topic 非常简单,可以利用 Kafka 提供的命令行工具kafka-topics.sh 。比方,要创建一个名为test_topic,包含 3 个分区,复制因子为 1 的 Topic,可以执行以下命令:
kafka-topics.sh --create --topic test_topic --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1
此中,--create表示创建 Topic;--topic指定要创建的 Topic 名称;--bootstrap-server指定 Kafka 集群的地址;--partitions指定 Topic 的分区数;--replication-factor指定每个分区的副本数 。
3.2 Partition(分区)

Partition(分区)是 Topic 的物理划分,每个 Topic 可以包含一个或多个 Partition,每个 Partition 是一个有序且不可变的消息序列,新消息会被追加到 Partition 的末了。分区在 Kafka 中具有至关重要的作用,主要体如今以下几个方面:


[*]并行处理与负载平衡:通过将消息分布到多个分区,Kafka 能够实现并行处理,提高体系的吞吐量和处理本领。每个分区可以独立处理消息的生产和消费,不同的分区可以分布在不同的 Broker 上,从而实现负载平衡,避免单个 Broker 成为性能瓶颈。比方,在一个高并发的日志收集体系中,大量的日志消息被发送到 Kafka。如果只有一个分区,全部的消息都将集中在一个 Broker 上处理,很容易导致该 Broker 负载过高,处理速度变慢。而通过设置多个分区,这些消息可以被分散到不同的 Broker 上并行处理,大大提高了体系的处理本领和吞吐量。


[*]数据局部性与顺序性:分区答应 Kafka 将相干的消息存储在同一个分区中,提高数据的局部性。对于必要按特定顺序处理的消息,将它们发送到同一个分区可以包管消息的顺序性。比方,在一个金融交易体系中,订单的创建、支付、结算等操作必要严酷按照顺序举行处理。通过将这些相干的消息发送到同一个分区,Kafka 可以确保消费者按照消息的发送顺序举行消费,从而包管交易的正确性和一致性。
每个分区在消息日志中都有一个唯一的偏移量(offset),用于标识消息在分区中的位置。消费者通过消费特定 Partition 的某个 offset 开始读取消息,并且可以记载本身消费到的 offset,以便在下次消费时从上次停止的位置继承。分区的数据存储在磁盘上,以日志文件的形式保存。Kafka 接纳了高效的文件存储和读写机制,联合操作体系的页缓存(page cache),使得数据的读写性能非常高。纵然处理海量数据,Kafka 也能保持较低的延迟和较高的吞吐量。
分区数量的选择对 Kafka 的性能有很大影响。如果分区数量过少,可能无法充分利用集群的资源,导致体系吞吐量较低;而分区数量过多,则会增加管理和维护的成本,同时也可能导致每个分区的数据量过小,无法充分发挥 Kafka 的并行处理优势。一样平常来说,必要根据实际的业务场景、数据量和硬件资源等因向来合理选择分区数量。比方,对于一个数据量较小、并发度不高的应用场景,可以适当淘汰分区数量;而对于数据量巨大、并发度高的大数据处理场景,则必要增加分区数量,以提高体系的性能和扩展性 。
3.3 Producer(生产者)

Producer(生产者)是负责将消息发送到 Kafka 集群的应用程序。生产者将消息发送到指定的 Topic,并可以选择将消息发送到特定的分区,大概由 Kafka 自动分配分区 。
生产者发送消息到 Kafka 集群的过程如下:

[*]消息创建与封装:生产者起首创建一个ProducerRecord对象,该对象包含了要发送的消息内容、目标 Topic 以及可选的分区信息和消息键(key)等。比方:
ProducerRecord<String, String> record = new ProducerRecord<>("test_topic", "key1", "value1");
这里创建了一个要发送到test_topic主题的消息,消息键为key1,消息值为value1。
2. 序列化:由于 Kafka 在网络中传输的是字节数组,以是生产者必要将ProducerRecord中的消息键和值举行序列化,将其转换为字节数组。Kafka 提供了多种序列化器,如StringSerializer、IntegerSerializer、ByteArraySerializer等,也支持用户自定义序列化器。比方,如果消息值是一个自定义的 Java 对象,就必要实现自定义的序列化器将其转换为字节数组,以便在网络中传输。
3. 分区选择:如果在ProducerRecord中没有指定分区号,生产者会根据分区策略来选择一个分区。Kafka 默认的分区策略有以下几种:


[*]随机分区:如果消息键(key)为null,且没有指定分区号,Kafka 会利用随机分区策略,从全部可用分区中随机选择一个分区发送消息。这种策略可以实现消息在各个分区上的匀称分布,但无法包管具有雷同特性的消息被发送到同一个分区。


[*]轮询分区:Kafka 会按照轮询的方式依次将消息发送到各个分区,即第一个消息发送到第一个分区,第二个消息发送到第二个分区,以此类推。当到达最后一个分区后,再重新从第一个分区开始。这种策略也能实现消息的匀称分布,适用于对消息顺序性要求不高,只必要包管各个分区负载平衡的场景。


[*]按消息键哈希分区:如果消息键不为null,Kafka 会计算消息键的哈希值,并根据哈希值对分区数取模,得到的结果就是要发送到的分区号。这种策略可以包管具有雷同消息键的消息总是被发送到同一个分区,适用于必要包管某些相干消息在同一个分区中顺序处理的场景。比方,在一个用户举动分析体系中,将用户 ID 作为消息键,如许同一个用户的全部举动消息都会被发送到同一个分区,便于后续对用户举动举行按序分析。

[*]消息发送:生产者将序列化后的消息发送到 Kafka 集群。在发送过程中,生产者会与 Kafka 集群中的 Broker 创建毗连,并将消息发送到目标分区地点的 Broker 上。Kafka 生产者支持同步发送和异步发送两种方式:


[*]

[*]同步发送:生产者调用send方法后,会壅闭等候 Kafka 集群的响应,直到消息乐成发送大概发生错误。比方:

try {
RecordMetadata metadata = producer.send(record).get();
System.out.println("消息发送乐成,分区:" + metadata.partition() + ",偏移量:" + metadata.offset());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
System.out.println("消息发送失败:" + e.getMessage());
}
这种方式可以确保消息被乐成发送,但会降低体系的吞吐量,因为生产者在等候响应期间无法发送其他消息。


[*]异步发送:生产者调用send方法后,不会壅闭等候响应,而是立刻返回。Kafka 会在后台将消息发送到集群,并通过回调函数(Callback)关照生产者发送结果。比方:
producer.send(record, new Callback() {
@Override
public void onCompletion(RecordMetadata metadata, Exception exception) {
if (exception == null) {
System.out.println("消息发送乐成,分区:" + metadata.partition() + ",偏移量:" + metadata.offset());
} else {
e.printStackTrace();
System.out.println("消息发送失败:" + e.getMessage());
}
}
});
异步发送方式可以提高体系的吞吐量,适用于对消息发送实时性要求不高,但必要处理大量消息的场景。生产者还可以通过设置一些参数来优化消息发送性能,如batch.size(批次巨细)、linger.ms(延迟时间)等。batch.size表示生产者在发送消息时,会将多个消息封装成一个批次发送,以淘汰网络请求次数,提高发送服从;linger.ms表示生产者在发送批次消息时,如果批次巨细未达到batch.size,生产者会等候linger.ms时间,看是否有更多的消息到达,以凑齐一个批次再发送。通过合理调整这些参数,可以在一定程度上提高生产者的性能和吞吐量 。
3.4 Consumer(消费者)与 Consumer Group(消费者组)

Consumer(消费者)是从 Kafka 集群中订阅并消费消息的应用程序。消费者通过订阅一个或多个 Topic,从 Kafka 集群中拉取消息举行处理。Consumer Group(消费者组)是一组订阅雷同 Topic 的消费者的逻辑聚集,它为 Kafka 提供了一种负载平衡和消息消费的机制 。
消费者拉取消息的方式是主动从 Kafka 集群中拉取,而不是由 Kafka 推送。消费者在拉取消息时,会维护一个消费偏移量(offset),记载本身已经消费到的消息位置。每次拉取消息时,消费者会从上次记载的偏移量开始读取消息。比方,在一个实时数据分析体系中,消费者不断从 Kafka 集群中拉取用户举动数据举行分析,通过维护消费偏移量,消费者可以确保每次拉取的都是未处理过的新消息,避免重复处理。
消费者组实现负载平衡和消息消费的原理如下:


[*]负载平衡:在一个消费者组中,多个消费者实例可以同时消费同一个 Topic 的消息。Kafka 会将 Topic 的各个分区分配给消费者组中的不同消费者实例,使得每个分区只被一个消费者实例消费,从而实现负载平衡。比方,假设有一个包含 4 个分区的 Topic,一个消费者组中有 3 个消费者实例。Kafka 会将这 4 个分区分配给这 3 个消费者实例,可能的分配方式是消费者实例 1 消费分区 0 和分区 1,消费者实例 2 消费分区 2,消费者实例 3 消费分区 3。如许,每个消费者实例只必要处理部分分区的消息,提高了消费服从和体系的整体吞吐量。


[*]消息消费:当一个消费者组中的某个消费者实例发生故障时,Kafka 会自动将其负责的分区重新分配给其他存活的消费者实例,以确保消息的继承消费。比方,在上述例子中,如果消费者实例 2 发生故障,Kafka 会将分区 2 重新分配给消费者实例 1 或消费者实例 3,包管分区 2 的消息能够被及时消费,不会因为某个消费者实例的故障而丢失或积压。同时,消费者组中的每个消费者实例都可以独立地控制本身的消费进度,即维护本身的消费偏移量。这使得消费者组在处理消息时具有很大的机动性,可以根据实际需求举行个性化的处理。
以一个电商订单处理体系为例,假设存在一个order_topic主题,此中包含订单创建、支付、发货等消息。如今有一个消费者组,包含多个消费者实例,分别负责不同的业务处理:


[*]订单处理消费者:负责处理订单创建的消息,举行订单数据的入库、库存扣减等操作。


[*]支付处理消费者:订阅order_topic中支付相干的消息,对支付结果举行验证和处理,更新订单状态为已支付。


[*]物流处理消费者:消费订单发货的消息,关照物流体系举行发货操作,并跟踪物流状态。
在这个例子中,通过消费者组的机制,不同的消费者实例可以并行处理order_topic中的不同类型的消息,实现了业务的解耦和高效处理。同时,当某个消费者实例出现故障时,其他消费者实例可以自动接受其工作,包管订单处理流程的正常运行 。
3.5 Broker(署理)

Broker(署理)是 Kafka 集群中的核心组件,它是运行 Kafka 服务的节点,负责接收、存储和转发消息。每个 Broker 都有唯一的 ID 标识,集群中可以有多个 Broker 协同工作,共同构成一个高可用、可扩展的 Kafka 集群 。
Broker 在 Kafka 集群中的主要角色和功能如下:


[*]消息存储:Broker 负责将接收到的消息恒久化存储到本地磁盘上。Kafka 接纳了基于日志的存储结构,每个 Topic 的每个分区在磁盘上都对应一个日志文件,消息按照顺序追加到日志文件中。这种存储方式联合操作体系的页缓存(page cache),可以实现高效的读写操作,纵然处理海量数据也能保持较低的延迟和较高的吞吐量。比方,在一个大数据日志收集体系中,大量的日志消息被发送到 Kafka 集群,Broker 将这些消息存储在本地磁盘上,同时利用页缓存技术,使得后续对这些消息的读取操作能够快速响应。


[*]消息转发:Broker 接收来自生产者的消息,并将其转发到相应的分区。当消费者请求消息时,Broker 根据消费者的订阅信息和消费偏移量,从对应的分区中读取消息并返回给消费者。比方,生产者向 Kafka 集群发送一条消息到test_topic主题,Broker 会根据消息的分区信息,将其存储到对应的分区日志文件中。当消费者订阅了test_topic并请求消息时,Broker 从该主题的相应分区中读取消息,返回给消费者。


[*]副本管理:为了提高数据的可靠性和容错性,Kafka 为每个分区引入了副本机制。每个分区都有一个领导者副本(Leader Replica)和多个跟随者副本(Follower Replica)。Broker 负责管理这些副本,领导者副本负责处理生产者和消费者的读写请求,跟随者副本则从领导者副本同步数据,保持与领导者副本的数据一致性。当领导者副本地点的 Broker 发生故障时,Kafka 会从跟随者副本中推举出一个新的领导者副本,确保数据的可用性和一致性。比方,在一个包含 3 个 Broker 的 Kafka 集群中,某个分区有 1 个领导者副本和 2 个跟随者副本,分别分布在不同的 Broker 上。当领导者副本地点的 Broker 出现故障时,Kafka 会通过内部的推举机制,从另外 2 个 Broker 上的跟随者副本中推举出一个新的领导者副本,继承处理读写请求,包管数据不会丢失。


[*]集群协调:多个 Broker 之间通过 Zookeeper(早期版本)或 Kafka 自带的 KRaft(新版本)机制举行协调和管理。它们共同维护集群的元数据信息,如 Topic 的分区信息、副本分布、Broker 的状态等。通过这种协调机制,Kafka 集群能够自动感知 Broker 的到场、离开和故障,动态调整集群的状态和负载平衡。比方,当一个新的 Broker 到场到 Kafka 集群中时,它会向 Zookeeper(或 KRaft)注册本身的信息,集群中的其他 Broker 会通过 Zookeeper(或 KRaft)获取到这个信息,并根据必要调整分区和副本的分配,以实现负载平衡和高可用性 。
Broker 在 Kafka 集群中扮演着至关重要的角色,它是实现 Kafka 高吞吐量、高可用性和可扩展性的关键组件,通过高效的消息存储、转发和副本管理机制,为生产者和消费者提供了可靠的消息传递服务。
四、Kafka 架构与工作原理

4.1 Kafka 整体架构图剖析

Kafka 的整体架构主要由生产者集群、Kafka 集群、Zookeeper 集群(早期版本)和消费者集群构成,它们之间紧密协作,共同实现了高效、可靠的消息处理和传递 。


[*]生产者集群:由多个生产者构成,负责将应用程序产生的消息发送到 Kafka 集群。生产者可以根据业务需求将消息发送到指定的 Topic,并可以通过分区策略决定消息发送到 Topic 的哪个分区。比方,在一个电商订单体系中,生产者会将订单创建、支付、发货等消息发送到对应的order_topic,并根据订单 ID 的哈希值将消息发送到不同的分区,以实现负载平衡和并行处理。


[*]Kafka 集群:由多个 Broker 节点构成,是 Kafka 的核心部分。每个 Broker 负责存储和处理消息,消息以 Topic 的形式举行分类和构造,每个 Topic 可以包含多个分区。Broker 之间通过 Zookeeper(早期版本)或 KRaft(新版本)机制举行协调和管理,共同维护集群的元数据信息,如 Topic 的分区信息、副本分布、Broker 的状态等。比方,在一个包含 5 个 Broker 的 Kafka 集群中,某个 Topic 有 10 个分区,这些分区会分布在不同的 Broker 上,以实现数据的分布式存储和处理,提高体系的扩展性和容错性。


[*]Zookeeper 集群(早期版本):在 Kafka 早期版本中,Zookeeper 扮演着至关重要的角色。它为 Kafka 集群提供了分布式协调服务,帮助 Kafka 集群中的 Broker 节点相互发现并维持心跳,确保整个体系知道哪些 Broker 是活动的和可服务的。Zookeeper 还负责存储 Kafka 的元数据信息,如 Topic 的创建、删除及配置变更,Partition 的分配情况,Consumer Group 的相干信息(如消费进度、订阅关系等)。别的,Zookeeper 还负责监督并执行 Kafka 分区的 Leader 推举过程,当 Leader 节点出现故障时,能敏捷选出新的 Leader,从而保持服务的高可用性。不过,随着 Kafka 的发展,从较新版本开始,Kafka 渐渐淘汰对 Zookeeper 的依赖,转而接纳更轻量级的内部协调机制,特殊是对于消费者协调和服务发现等方面,但在很多现有的摆设方案中,Zookeeper 仍然是不可或缺的一部分 。


[*]消费者集群:由多个消费者构成,消费者订阅感爱好的 Topic,并从 Kafka 集群中拉取消息举行处理。消费者可以以消费者组的形式构造,每个消费者组可以有多个消费者。在消费者组内,每个分区只能由一个消费者举行消费,从而实现负载平衡和扩展性。比方,在一个实时数据分析体系中,有多个消费者组,每个消费者组中的消费者分别负责处理不同类型的消息,如用户举动分析组负责处理user_behavior_topic中的消息,订单分析组负责处理order_topic中的消息,通过消费者组的机制,实现了业务的解耦和高效处理 。
4.2 消息生产流程

生产者发送消息到 Kafka 集群的过程涉及多个关键步骤,这些步骤确保了消息能够准确、高效地发送到目标位置 。

[*]消息创建与封装:生产者起首创建一个ProducerRecord对象,该对象包含了要发送的消息内容、目标 Topic 以及可选的分区信息和消息键(key)等。比方:
ProducerRecord<String, String> record = new ProducerRecord<>("test_topic", "key1", "value1");
这里创建了一个要发送到test_topic主题的消息,消息键为key1,消息值为value1。
2. 序列化:由于 Kafka 在网络中传输的是字节数组,以是生产者必要将ProducerRecord中的消息键和值举行序列化,将其转换为字节数组。Kafka 提供了多种序列化器,如StringSerializer、IntegerSerializer、ByteArraySerializer等,也支持用户自定义序列化器。比方,如果消息值是一个自定义的 Java 对象,就必要实现自定义的序列化器将其转换为字节数组,以便在网络中传输。
3. 分区选择:如果在ProducerRecord中没有指定分区号,生产者会根据分区策略来选择一个分区。Kafka 默认的分区策略有以下几种:


[*]随机分区:如果消息键(key)为null,且没有指定分区号,Kafka 会利用随机分区策略,从全部可用分区中随机选择一个分区发送消息。这种策略可以实现消息在各个分区上的匀称分布,但无法包管具有雷同特性的消息被发送到同一个分区。


[*]轮询分区:Kafka 会按照轮询的方式依次将消息发送到各个分区,即第一个消息发送到第一个分区,第二个消息发送到第二个分区,以此类推。当到达最后一个分区后,再重新从第一个分区开始。这种策略也能实现消息的匀称分布,适用于对消息顺序性要求不高,只必要包管各个分区负载平衡的场景。


[*]按消息键哈希分区:如果消息键不为null,Kafka 会计算消息键的哈希值,并根据哈希值对分区数取模,得到的结果就是要发送到的分区号。这种策略可以包管具有雷同消息键的消息总是被发送到同一个分区,适用于必要包管某些相干消息在同一个分区中顺序处理的场景。比方,在一个用户举动分析体系中,将用户 ID 作为消息键,如许同一个用户的全部举动消息都会被发送到同一个分区,便于后续对用户举动举行按序分析。

[*]消息发送:生产者将序列化后的消息发送到 Kafka 集群。在发送过程中,生产者会与 Kafka 集群中的 Broker 创建毗连,并将消息发送到目标分区地点的 Broker 上。Kafka 生产者支持同步发送和异步发送两种方式:


[*]

[*]同步发送:生产者调用send方法后,会壅闭等候 Kafka 集群的响应,直到消息乐成发送大概发生错误。比方:

try {
RecordMetadata metadata = producer.send(record).get();
System.out.println("消息发送乐成,分区:" + metadata.partition() + ",偏移量:" + metadata.offset());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
System.out.println("消息发送失败:" + e.getMessage());
}
这种方式可以确保消息被乐成发送,但会降低体系的吞吐量,因为生产者在等候响应期间无法发送其他消息。


[*]异步发送:生产者调用send方法后,不会壅闭等候响应,而是立刻返回。Kafka 会在后台将消息发送到集群,并通过回调函数(Callback)关照生产者发送结果。比方:
producer.send(record, new Callback() {
@Override
public void onCompletion(RecordMetadata metadata, Exception exception) {
if (exception == null) {
System.out.println("消息发送乐成,分区:" + metadata.partition() + ",偏移量:" + metadata.offset());
} else {
e.printStackTrace();
System.out.println("消息发送失败:" + e.getMessage());
}
}
});
异步发送方式可以提高体系的吞吐量,适用于对消息发送实时性要求不高,但必要处理大量消息的场景。生产者还可以通过设置一些参数来优化消息发送性能,如batch.size(批次巨细)、linger.ms(延迟时间)等。batch.size表示生产者在发送消息时,会将多个消息封装成一个批次发送,以淘汰网络请求次数,提高发送服从;linger.ms表示生产者在发送批次消息时,如果批次巨细未达到batch.size,生产者会等候linger.ms时间,看是否有更多的消息到达,以凑齐一个批次再发送。通过合理调整这些参数,可以在一定程度上提高生产者的性能和吞吐量 。
4.3 消息存储机制

Kafka 将消息恒久化存储在磁盘上,接纳了一系列高效的存储策略和机制,以确保数据的可靠性、恒久性和高吞吐量 。


[*]日志分段:Kafka 中的每个分区都由多个日志段(Log Segment)构成。当日志文件巨细达到一定阈值(可通过log.segment.bytes参数配置,默认值为 1GB),大概距离上一次日志段切换的时间达到一定时长(可通过log.roll.hours参数配置,默认值为 168 小时,即一周)时,Kafka 会创建一个新的日志段,将新消息写入新的日志段中。每个日志段包含一个数据文件(.log 文件)和两个索引文件(偏移量索引文件.index 和时间戳索引文件.timeindex)。比方,假设一个分区的日志文件巨细达到了 1GB,Kafka 会创建一个新的日志段,新的日志段文件名为00000000000000000000.log,同时会创建对应的00000000000000000000.index和00000000000000000000.timeindex文件。


[*]索引文件:偏移量索引文件用于创建消息偏移量与物理地址之间的映射关系,时间戳索引文件用于创建时间戳与偏移量的映射关系。索引文件接纳稀疏索引的方式构建,即不是为每个消息都创建索引,而是每隔一定命量的消息创建一个索引项。如许可以大大淘汰索引文件的巨细,提高查询服从。比方,偏移量索引文件中,每隔 1000 条消息记载一个索引项,记载该消息的偏移量和在数据文件中的物理地址。当消费者必要查找某个偏移量的消息时,先通过偏移量索引文件举行二分查找,找到小于指定偏移量的最大偏移量及其对应的物理地址,然后从该物理地址开始在数据文件中顺序查找,即可找到目标消息 。


[*]数据清算策略:Kafka 提供了两种数据清算策略:删除(Delete)和压缩(Compact)。


[*]

[*]删除策略:按照一定的时间或巨细阈值删除过期或超出巨细限制的日志段。可以通过log.retention.hours(默认值为 168 小时,即一周)、log.retention.minutes(优先级高于log.retention.hours)和log.retention.ms(优先级高于前两者)等参数设置消息的保留时间,也可以通过log.retention.bytes参数设置分区全部日志段的总巨细限制。当日志段的保留时间超过设置的阈值,大概全部日志段的总巨细超过设置的字节数时,Kafka 会删除最早的日志段。比方,如果设置log.retention.hours为 24,那么 24 小时前的日志段会被删除。



[*]

[*]压缩策略:对于具有雷同键的消息,只保留最新的一条。压缩策略适用于必要保留最新状态的场景,如用户信息的更新、订单状态的变更等。Kafka 通过日志压缩算法,将具有雷同键的消息归并为一条,只保留最新的消息值,从而节省存储空间。在压缩过程中,Kafka 会标记必要保留的消息,然后删除那些被标记为可以删除的旧消息 。

4.4 消息消费流程

消费者从 Kafka 集群拉取消息的过程涉及多个关键环节,包罗分区分配、消息拉取和消费者状态管理等 。

[*]订阅主题:消费者起首必要订阅一个或多个感爱好的 Topic。比方:
List<String> topics = Arrays.asList("test_topic", "another_topic");
consumer.subscribe(topics);
这里消费者订阅了test_topic和another_topic两个主题。
2. 分区分配:当消费者以消费者组的形式存在时,Kafka 会将订阅的 Topic 的分区分配给消费者组中的各个消费者。Kafka 提供了多种分区分配策略,常见的有 Range、RoundRobin 和 Sticky。


[*]Range 分配策略:按照 Topic 分区的顺序,将分区依次分配给消费者。比方,假设有一个包含 4 个分区(分区 0、分区 1、分区 2、分区 3)的 Topic,一个消费者组中有 2 个消费者(消费者 A 和消费者 B)。利用 Range 分配策略时,可能会将分区 0 和分区 1 分配给消费者 A,分区 2 和分区 3 分配给消费者 B。这种策略的优点是简单直观,但在某些情况下可能会导致分区分配不匀称,如当分区数不能被消费者数整除时,可能会使部分消费者负担更多的分区。


[*]RoundRobin 分配策略:将全部订阅的 Topic 的分区按照顺序排列,然后依次轮询分配给消费者。继承以上述例子为例,利用 RoundRobin 分配策略时,可能会将分区 0 分配给消费者 A,分区 1 分配给消费者 B,分区 2 分配给消费者 A,分区 3 分配给消费者 B。这种策略可以实现更匀称的分区分配,但在订阅多个 Topic 时,可能会导致同一个消费者消费不同 Topic 的分区,增加了消费者处理逻辑的复杂性。


[*]Sticky 分配策略:这是 Kafka 0.11.0.0 版本引入的一种新的分区分配策略,它联合了 Range 和 RoundRobin 策略的优点。Sticky 分配策略在分配分区时,会只管保持现有分区分配的稳定性,即只管让消费者继承消费之前分配到的分区。只有在必要时,才会重新分配分区,并且在重新分配时,会只管匀称地分配分区。这种策略在包管分区分配稳定性的同时,也能实现较好的负载平衡 。

[*]消息拉取:消费者通过向 Kafka 集群发送拉取请求(Fetch Request)来获取消息。拉取请求中包含了消费者希望拉取的分区、偏移量、最大拉取字节数等信息。Kafka 集群接收到拉取请求后,会根据请求信息从对应的分区中读取消息,并返回给消费者。消费者接收到消息后,会根据业务逻辑举行处理。比方:
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<String, String> record : records) {
System.out.println("消费消息:" + record.value() + ",分区:" + record.partition() + ",偏移量:" + record.offset());
}
这里消费者利用poll方法从 Kafka 集群拉取消息,poll方法的参数表示拉取消息的超时时间,即如果在指定时间内没有拉取到消息,poll方法会返回空的ConsumerRecords。
4. 消费者状态管理:消费者在消费过程中,会维护本身的消费偏移量(offset),记载已经消费到的消息位置。消费者可以自动提交偏移量(通过设置enable.auto.commit为true,默认值为true),也可以手动提交偏移量(通过调用commitSync或commitAsync方法)。自动提交偏移量的方式简单方便,但可能会导致重复消费或消息丢失的问题,因为自动提交是按照一定的时间隔断(通过auto.commit.interval.ms参数设置,默认值为 5000 毫秒)举行的,在两次提交之间如果消费者发生故障,重启后会从上次提交的偏移量开始消费,可能会导致部分消息被重复消费。手动提交偏移量可以更精确地控制消费位置,但必要开辟者本身处理提交逻辑,增加了代码的复杂性 。
4.5 Zookeeper 在 Kafka 中的作用

在 Kafka 早期版本中,Zookeeper 是 Kafka 集群不可或缺的重要构成部分,它为 Kafka 提供了分布式协调和元数据管理等关键功能 。


[*]集群协调:Zookeeper 帮助 Kafka 集群中的 Broker 节点相互发现并维持心跳。每个 Broker 在启动时,会在 Zookeeper 上创建一个临时节点(Ephemeral Node),节点路径类似于/brokers/ids/{brokerId},此中{brokerId}是 Broker 的唯一标识。其他 Broker 可以通过监听这些节点的变化,实时感知集群中 Broker 的到场、离开和故障情况。比方,当一个新的 Broker 到场集群时,它会在 Zookeeper 上创建对应的临时节点,其他 Broker 监听到这个节点的创建变乱后,就知道有新的 Broker 到场了,从而可以更新本身的元数据信息,举行相应的负载平衡调整。


[*]元数据管理:Kafka 利用 Zookeeper 来恒久化和分发其关键的元数据信息。


[*]

[*]Topic 元数据:Zookeeper 存储了 Topic 的创建、删除及配置变更信息。比方,当创建一个新的 Topic 时,Kafka 会在 Zookeeper 上创建一个节点,路径为/brokers/topics/{topicName},并在该节点下存储 Topic 的分区信息、副本分布等元数据。当 Topic 的配置发生变更时,如增加分区、修改副本因子等,Kafka 会更新 Zookeeper 上相应的节点信息,其他组件(如生产者、消费者)可以通过监听这些节点的变化,获取最新的 Topic 元数据。



[*]

[*]Partition 元数据:Zookeeper 保存了每个 Partition 的分配情况,即哪个 Broker 是 Partition 的 Leader,以及有哪些 Follower。每个 Partition 在 Zookeeper 上都有对应的节点,路径类似于/brokers/topics/{topicName}/partitions/{partitionId}/state,节点数据中包含了该 Partition 的 Leader 和 Follower 列表。生产者和消费者在与 Kafka 集群交互时,会从 Zookeeper 获取 Partition 的元数据信息,以便确定消息的发送和消费目标 。



[*]

[*]Consumer Group 元数据:Zookeeper 存储了 Consumer Group 的相干信息,如消费进度(offsets)、订阅关系等。每个 Consumer Group 在 Zookeeper 上都有一个对应的节点,路径为/consumers/{groupName},在该节点下又包含了多个子节点,用于存储消费进度、成员列表等信息。消费者在消费过程中,会将本身的消费偏移量存储在 Zookeeper 上,当消费者发生故障或重新到场集群时,可以从 Zookeeper 获取之前的消费进度,继承消费。



[*]Leader 推举:对于 Kafka 分区的 Leader 推举,Zookeeper
五、Kafka 的特性

5.1 高吞吐量、低延迟

Kafka 具备杰出的高吞吐量和低延迟特性,这使其在处理大规模数据时表现出色。实在现原理主要基于以下几个关键技术:


[*]页缓存技术:Kafka 充分利用操作体系的页缓存(Page Cache),将数据写入操作先在内存中完成,由操作体系决定何时将缓存中的数据真正刷入磁盘。这种方式极大地提拔了数据写入性能,因为内存写入速度远远高于磁盘写入速度。比方,在一个日志收集体系中,大量的日志消息被快速写入页缓存,然后由操作体系异步刷盘,淘汰了磁盘 I/O 的直接操作,提高了整体的写入服从 。


[*]磁盘顺序写:Kafka 接纳磁盘顺序写的方式,将消息追加到日志文件的末了,而不是举行随机写操作。普通机器磁盘的随机写性能较差,但顺序写性能却与内存写入性能相近。通过顺序写,Kafka 大大提高了数据写入的吞吐量。以一个电商订单体系为例,订单数据按时间顺序依次写入 Kafka 的日志文件,避免了随机写带来的磁盘寻址开销,使得订单数据能够快速恒久化存储 。


[*]零拷贝技术:在数据读取阶段,Kafka 引入零拷贝技术,直接让操作体系缓存中的数据发送到网卡,传输给卑鄙消费者,跳过了从操作体系缓存到应用程序缓存,再到操作体系 Socket 缓存的两次拷贝过程,仅拷贝数据描述符,大大提拔了数据读取和传输的性能。在实时数据分析场景中,消费者能够快速从 Kafka 集群中读取数据举行分析,淘汰了数据传输的延迟,提高了分析的时效性 。
通过这些技术的联合,Kafka 在处理大规模数据时展现出了强大的性能优势。比方,在一些实际测试中,Kafka 集群每秒可以轻松处理数十万甚至数百万条消息,延迟最低可达到几毫秒。在一个拥有 10 个 Broker 节点的 Kafka 集群中,对一个包含 100 个分区的 Topic 举行性能测试,利用 100 个生产者同时发送消息,每个生产者每秒发送 1000 条消息,Kafka 集群能够稳定地接收和处理这些消息,吞吐量达到每秒 100 万条以上,而消息的平均延迟仅为 5 毫秒左右,充分证明了 Kafka 在高吞吐量和低延迟方面的杰出性能 。
5.2 可扩展性

Kafka 集群具有出色的可扩展性,能够轻松应对不断增长的数据处理需求,支持热扩展,即在集群运行期间可以动态添加新的 Broker 节点,而无需停机。
添加新 Broker 节点的步骤如下:

[*]预备新节点:确保新的 Broker 节点具备与现有节点相似或更好的硬件配置,包罗 CPU、内存、磁盘(发起利用 SSD 以提高 I/O 性能)和网络毗连等。

[*]安装 Kafka:在新节点上下载并安装与现有集群雷同版本的 Kafka,解压缩 Kafka 二进制文件,并配置相干参数。在server.properties配置文件中,必要设置以下关键参数:


[*]

[*]broker.id:每个 Broker 都必要一个唯一的 ID,新 Broker 的 ID 不能与集群中其他 Broker 的 ID 重复。比方,可以为新 Broker 分配一个未利用过的整数值作为其 ID。



[*]

[*]log.dirs:指定 Kafka 日志文件的存储路径,可以根据实际需求设置为一个磁盘空间充足的目录。



[*]

[*]listeners或advertised.listeners:配置 Broker 的监听地址和端口,用于客户端毗连。如果集群摆设在不同的网络环境中,可能必要利用advertised.listeners来指定对外袒露的地址。



[*]

[*]zookeeper.connect(早期版本):设置毗连 Zookeeper 集群的地址和端口,以便新 Broker 能够与集群中的其他节点举行协调和通信。在新版本中,如果利用 KRaft 机制,则不必要配置此参数 。


[*]启动新 Broker:完成配置后,通过执行 Kafka 提供的启动脚本(如bin/kafka-server-start.sh config/server.properties)启动新的 Broker 实例。新 Broker 启动后,会自动毗连到 Zookeeper 集群(或通过 KRaft 机制与集群举行通信),并向集群注册本身的信息 。

[*]重新分配分区(可选):新的 Broker 到场后,默认情况下它不会分担之前已经创建的 Topic 的负载。为了充分利用新 Broker 的资源,提拔整体性能和存储容量,可以利用 Kafka 自带的kafka-reassign-partitions.sh工具或第三方 Kafka 管理工具(如 Kafka Cruise Control)来重新分配分区和副本。重新分配分区时,必要谨慎操作,因为这涉及到数据的迁移,可能会对集群性能造成一定影响。通常发起在业务低峰时段举行此操作,并密切监控新老 Broker 的性能和稳定性 。
添加新 Broker 节点对集群的影响主要体如今以下几个方面:


[*]负载平衡:新 Broker 到场后,Kafka 集群会自动感知并调整分区和副本的分配,将部分分区迁移到新 Broker 上,实现负载平衡,提高集群的整体处理本领。


[*]存储容量增加:新 Broker 为集群带来了额外的存储资源,使得集群能够存储更多的数据,满足不断增长的数据量需求。


[*]性能提拔:通过合理分配分区和副本,新 Broker 的到场可以分担原有 Broker 的负载,降低单个 Broker 的压力,从而提拔整个集群的性能和响应速度 。
5.3 恒久性、可靠性

Kafka 通过将消息恒久化到磁盘以及数据备份机制,确保了消息的恒久性和可靠性。
Kafka 的消息恒久化到磁盘的机制如下:


[*]日志分段存储:Kafka 中的每个分区都由多个日志段(Log Segment)构成。当日志文件巨细达到一定阈值(可通过log.segment.bytes参数配置,默认值为 1GB),大概距离上一次日志段切换的时间达到一定时长(可通过log.roll.hours参数配置,默认值为 168 小时,即一周)时,Kafka 会创建一个新的日志段,将新消息写入新的日志段中。每个日志段包含一个数据文件(.log 文件)和两个索引文件(偏移量索引文件.index 和时间戳索引文件.timeindex)。这种日志分段存储的方式便于管理和维护,同时也提高了数据的读写服从。比方,当必要查找某个特定时间范围内的消息时,可以通过时间戳索引文件快速定位到对应的日志段,然后在数据文件中举行查找 。


[*]索引文件:偏移量索引文件用于创建消息偏移量与物理地址之间的映射关系,时间戳索引文件用于创建时间戳与偏移量的映射关系。索引文件接纳稀疏索引的方式构建,即不是为每个消息都创建索引,而是每隔一定命量的消息创建一个索引项。如许可以大大淘汰索引文件的巨细,提高查询服从。当消费者必要查找某个偏移量的消息时,先通过偏移量索引文件举行二分查找,找到小于指定偏移量的最大偏移量及其对应的物理地址,然后从该物理地址开始在数据文件中顺序查找,即可找到目标消息 。
Kafka 的数据备份机制主要通过副本(Replica)实现:


[*]副本机制:每个分区都有一个领导者副本(Leader Replica)和多个跟随者副本(Follower Replica),它们分布在不同的 Broker 上。领导者副本负责处理生产者和消费者的读写请求,跟随者副本则从领导者副本同步数据,保持与领导者副本的数据一致性。比方,在一个包含 3 个 Broker 的 Kafka 集群中,某个分区有 1 个领导者副本和 2 个跟随者副本,分别分布在不同的 Broker 上。当领导者副本地点的 Broker 发生故障时,Kafka 会从跟随者副本中推举出一个新的领导者副本,确保数据的可用性和一致性 。


[*]ISR 聚集:Kafka 利用同步副本聚集(In-Sync Replicas,ISR)来管理分区的容错性。ISR 是指那些和 Leader 副本保持同步的 Follower 副本聚集。只有在 ISR 中的副本才能被选为新的 Leader。Follower 副本会定期从 Leader 拉取数据,保持数据一致性。如果某个 Follower 副本长时间未能跟上 Leader 的进度,它将被踢出 ISR;当 Follower 副本重新赶上 Leader 时,它会被重新到场 ISR。这种机制确保了在发生故障时,Kafka 总能找到一个与 Leader 数据一致的副原来接替 Leader 的角色 。
虽然 Kafka 采取了多种措施保障数据可靠性,但在某些情况下仍可能出现数据丢失的场景:


[*]生产者发送失败:当生产者向 Kafka 集群发送消息时,如果网络故障或 Kafka 集群负载过高,可能导致消息发送失败。为了降低这种风险,可以合理设置生产者的重试次数(retries参数)和等候时间(linger.ms参数),并确保acks参数设置为符合的值(如acks=all,表示生产者等候全部 ISR 成员简直认,提供最高的可靠性) 。


[*]日志段文件过早删除:如果设置了较短的日志保留时间(log.retention.hours等参数),那么纵然有延迟消费的应用程序也可能错过读取这些记载的机会而最终遗失它们。因此,必要根据实际业务需求合理设置日志保留时间,避免因日志删除导致数据丢失 。


[*]ISR 列表成员不足:当 ISR 列表中的成员数量不足时,一旦主节点发生故障且别的备份无法及时接受工作负载,就可能发生不可逆的数据损失征象。为了应对这种情况,应该动态调节最小 ISR 阈值(min.insync.replicas),确保高可用级别始终处于理想范围内 。
5.4 容错性

Kafka 答应集群中节点失败,通过强大的容错机制包管体系的高可用性和数据的一致性。
Kafka 的容错机制主要依赖于副本机制和 Leader 推举过程:


[*]副本机制:如前所述,每个分区都有多个副本,包罗一个领导者副本和多个跟随者副本。领导者副本负责处理读写请求,跟随者副本从领导者副本同步数据。当领导者副本地点的 Broker 发生故障时,Kafka 可以从跟随者副本中推举出新的领导者副本,确保数据的可用性和一致性。在一个包含 5 个 Broker 的 Kafka 集群中,某个分区有 1 个领导者副本和 4 个跟随者副本。如果领导者副本地点的 Broker 出现故障,Kafka 会敏捷从其他 4 个跟随者副本中推举出一个新的领导者副本,继承处理生产者和消费者的请求,包管数据不会丢失或停止服务 。


[*]Leader 推举:Kafka 利用 Zookeeper(早期版本)或 KRaft(新版本)来协调和管理 Leader 推举过程。每个分区都维护了一个 ISR 列表,此中包含了与 Leader 保持同步的全部副本。当某个分区的 Leader 失效时,Controller(Kafka 集群中的一个特殊 Broker,负责管理集群状态)会从该分区的 ISR 列表中选择一个新的 Leader。通常情况下,会选择 ISR 列表中最前面的谁人副本作为新的 Leader,也可以根据配置选择拥有最新偏移量的副本等其他策略。一旦新的 Leader 被选定,Controller 会更新相应的元数据,并将这个变更广播给集群中的全部 Broker。比方,当一个分区的 Leader 副本地点的 Broker 出现网络故障时,Kafka 通过心跳机制检测到该故障,Controller 会立刻从 ISR 列表中推举出一个新的 Leader,关照其他 Broker 更新元数据,包管集群的正常运行 。
Kafka 的容错机制还包罗故障检测和规复:


[*]故障检测:Kafka 利用心跳机制来检测 Broker 是否存活。如果 Leader 在一段时间内没有收到 Follower 的心跳,则以为 Follower 已经失效;同样地,如果 Follower 发现无法毗连到 Leader,它也会触发 Leader 推举过程。Controller 会定期查抄分区状态,确保每个分区都有一个生动的 Leader 。


[*]数据规复:当一个 Follower 副本重新到场 ISR 后,必要举行数据同步以赶上 Leader 的进度。Kafka 通过以下步骤完成数据规复:起首,Follower 从 Leader 拉取缺失的数据;当 Follower 的日志比 Leader 的日志长时,必要截断多余的部分;最后,确保复制的数据与 Leader 保持一致。通过这些步骤,Kafka 包管了在节点故障规复后,数据的一致性和完整性 。
5.5 高并发

Kafka 支持数千个客户端同时读写,通过多种技术实现了高并发处理本领。
Kafka 支持高并发的技术实现主要包罗以下几个方面:


[*]分区机制:Kafka 的 Topic 可以划分为多个分区,每个分区可以独立处理消息的生产和消费。生产者可以将消息发送到不同的分区,消费者也可以从不同的分区拉取消息,从而实现并行处理,提高体系的并发处理本领。在一个电商订单体系中,将订单消息按照订单 ID 的哈希值分配到不同的分区,多个生产者可以同时向不同的分区发送订单消息,多个消费者也可以同时从不同的分区消费订单消息,大大提高了体系的并发处理本领 。


[*]生产者和消费者模型:Kafka 接纳异步的生产者和消费者模型。生产者通过异步方式将消息发送到 Kafka 集群,无需等候消息发送乐成简直认,即可继承发送下一条消息,提高了消息发送的服从。消费者通过轮询的方式从 Kafka 集群拉取消息,并且可以批量拉取消息,淘汰了网络请求的次数,提高了消费服从。在一个实时数据处理体系中,生产者每秒可以发送数万条消息到 Kafka 集群,消费者可以每秒从 Kafka 集群拉取并处理大量的消息,实现了高并发的数据处理 。


[*]内存和缓存优化:Kafka 充分利用操作体系的页缓存和内存优化技术,淘汰了磁盘 I/O 的操作,提高了数据读写的速度。同时,Kafka 在内存中缓存了常用的元数据信息,如 Topic 的分区信息、副本分布等,淘汰了元数据的查询时间,提高了体系的响应速度 。
在高并发场景下,Kafka 的性能表现十分出色。比方,在一个社交媒体平台中,大量的用户举动数据(如点赞、品评、分享等)必要实时处理。Kafka 作为数据收集和传输的中间件,能够支持数千个客户端(如用户设备、应用服务器等)同时向 Kafka 集群发送用户举动数据,并且能够快速将这些数据传输给卑鄙的实时数据分析体系举行处理。在实际测试中,当有 5000 个客户端同时向 Kafka 集群发送消息,每个客户端每秒发送 100 条消息时,Kafka 集群能够稳定地接收和处理这些消息,吞吐量达到每秒 50 万条以上,平均延迟保持在 10 毫秒以内,展现了 Kafka 在高并发场景下的杰出性能 。
六、Kafka 应用场景及案例分析

6.1 日志收集

在分布式体系中,各个组件和服务会产生大量的日志数据,这些日志数据对于体系的运维、故障排查、性能优化以及业务分析都具有重要价值。Kafka 在日志收集场景中扮演着至关重要的角色,它能够高效地收集、传输和存储这些日志数据,为后续的集中存储和分析提供结实的基础 。
以一个大型互联网公司的分布式体系为例,该体系包含多个微服务,如用户服务、订单服务、支付服务等,每个微服务都摆设在多个服务器节点上,每天会产生数以亿计的日志记载。为了实现对这些日志数据的有效管理,公司接纳了 Kafka 作为日志收集工具,具体实现步骤如下:

[*]日志生产者配置:在每个微服务的代码中,通过配置日志框架(如 Log4j、Logback 等),将日志消息发送到 Kafka 集群。以 Log4j 为例,在log4j.properties文件中添加如下配置:
log4j.appender.kafka=org.apache.kafka.log4jappender.KafkaLog4jAppender
log4j.appender.kafka.topic=log_topic
log4j.appender.kafka.bootstrap.servers=kafka1:9092,kafka2:9092,kafka3:9092
log4j.appender.kafka.layout=org.apache.log4j.PatternLayout
log4j.appender.kafka.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
如许,微服务产生的日志消息就会被发送到名为log_topic的 Kafka 主题中。
2. Kafka 集群接收日志:Kafka 集群中的 Broker 节点负责接收来自各个微服务的日志消息,并将其存储到对应的分区中。由于 Kafka 接纳了分区机制和顺序写磁盘的方式,能够高效地处理大量的日志数据写入,包管了日志收集的高吞吐量和低延迟 。
3. 日志消费者处理:为了实现日志的集中存储和分析,公司利用了 Flink 和 Elasticsearch。Flink 作为日志消费者,从 Kafka 的log_topic主题中拉取日志消息,并举行实时处理,如日志格式转换、非常检测、关键词过滤等。比方,Flink 可以通过正则表达式匹配日志中的非常信息,将其标记为非常日志,并发送到专门的非常日志主题中。然后,Flink 将处理后的日志消息发送到 Elasticsearch 举行存储,Elasticsearch 提供了强大的搜索和分析功能,运维人员和数据分析师可以通过 Kibana 等工具对日志数据举行实时查询和分析,快速定位体系故障、分析用户举动、优化体系性能 。
通过利用 Kafka 举行日志收集,该互联网公司实现了对分布式体系中日志数据的高效管理和分析,大大提高了体系的运维服从和业务决议的准确性。比方,在一次体系故障排查中,运维人员通过在 Elasticsearch 中查询 Kafka 收集的日志数据,敏捷定位到了故障发生的时间、位置和缘故起因,及时采取措施办理了问题,淘汰了故障对业务的影响。同时,数据分析师通过对日志数据的分析,发现了用户在某个特定时间段内的购买举动模式,为公司的精准营销提供了有力的数据支持 。
6.2 消息队列

在分布式体系中,不同的服务之间通常必要举行异步通信和解耦,以提高体系的可扩展性和机动性。Kafka 作为消息队列,具有高吞吐量、低延迟、可扩展性和可靠性等优势,非常得当用于实现分布式体系中的消息解耦和异步处理 。
Kafka 作为消息队列的优势主要体如今以下几个方面:


[*]高吞吐量:Kafka 接纳了分区、顺序写磁盘和零拷贝等技术,能够实现每秒数十万甚至数百万条消息的高吞吐量处理,适用于处理大量的消息数据。在一个电商促销活动期间,体系会产生海量的订单消息、支付消息和库存变更消息等,Kafka 能够快速接收和处理这些消息,确保体系的正常运行。


[*]低延迟:通过合理的配置和优化,Kafka 可以实现较低的消息处理延迟,满足对实时性要求较高的业务场景。在实时数据分析场景中,Kafka 能够快速将数据传输给分析体系,包管分析结果的及时性。


[*]可扩展性:Kafka 集群可以通过添加新的 Broker 节点来实现程度扩展,轻松应对不断增长的业务需求。当业务量增加时,只需添加新的 Broker 节点,Kafka 会自动将分区和副本分配到新节点上,实现负载平衡。


[*]可靠性:Kafka 通过副本机制和 ISR 聚集,确保了消息的可靠性和恒久性,纵然部分节点出现故障,也能包管消息不丢失。每个分区都有多个副本,分布在不同的 Broker 上,当领导者副本地点的 Broker 发生故障时,Kafka 会从跟随者副本中推举出新的领导者副本,继承处理消息 。
以一个电商订单处理体系为例,该体系包含订单服务、库存服务和支付服务等多个微服务。当用户下单时,订单服务会产生一条订单消息,并将其发送到 Kafka 的order_topic主题中。库存服务和支付服务作为消费者,订阅order_topic主题,接收订单消息并举行异步处理。具体实现如下:

[*]订单服务发送消息:订单服务在接收到用户的下单请求后,创建一个订单消息对象,并将其发送到 Kafka 的order_topic主题中。以 Java 代码为例:
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import java.util.Properties;
public class OrderProducer {
private static final String TOPIC = "order_topic";
private static final String BOOTSTRAP_SERVERS = "kafka1:9092,kafka2:9092,kafka3:9092";
public static void main(String[] args) {
Properties props = new Properties();
props.put("bootstrap.servers", BOOTSTRAP_SERVERS);
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
KafkaProducer<String, String> producer = new KafkaProducer<>(props);
String orderMessage = "{\"orderId\":\"123456\",\"userId\":\"user1\",\"productId\":\"product1\",\"quantity\":2}";
ProducerRecord<String, String> record = new ProducerRecord<>(TOPIC, orderMessage);
producer.send(record);
producer.close();
}
}

[*]库存服务消费消息:库存服务订阅order_topic主题,从 Kafka 中拉取订单消息,并根据订单消息中的商品数量举行库存扣减操作。以 Java 代码为例:
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import java.time.Duration;
import java.util.Collections;
import java.util.Properties;
public class InventoryConsumer {
private static final String TOPIC = "order_topic";
private static final String BOOTSTRAP_SERVERS = "kafka1:9092,kafka2:9092,kafka3:9092";
private static final String GROUP_ID = "inventory_group";
public static void main(String[] args) {
Properties props = new Properties();
props.put("bootstrap.servers", BOOTSTRAP_SERVERS);
props.put("group.id", GROUP_ID);
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Collections.singletonList(TOPIC));
while (true) {
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<String, String> record : records) {
String orderMessage = record.value();
// 解析订单消息,举行库存扣减操作
System.out.println("库存服务消费订单消息:" + orderMessage);
}
}
}
}

[*]支付服务消费消息:支付服务同样订阅order_topic主题,接收订单消息并举行支付处理。在支付乐成后,支付服务可以将支付结果消息发送到另一个 Kafka 主题,如payment_result_topic,以便其他服务(如订单服务)举行后续处理。
通过利用 Kafka 作为消息队列,电商订单处理体系实现了订单服务、库存服务和支付服务之间的解耦和异步处理。订单服务无需等候库存服务和支付服务的处理结果,即可返回用户下单乐成的响应,提高了体系的响应速度和用户体验。同时,各个服务可以独立扩展和维护,降低了体系的耦合度,提高了体系的可扩展性和机动性 。
6.3 实时数据流处理

在当今的数据驱动期间,实时获取和分析数据对于企业做出及时、准确的决议至关重要。Kafka 在实时数据流处理场景中发挥着关键作用,它能够高效地处理和传输大量的实时数据,为实时数据分析和处理提供可靠的数据源 。
Kafka 在实时数据流处理场景中的应用主要是作为数据管道,将实时产生的数据传输到流处理框架中举行处理。常见的流处理框架如 Apache Flink、Apache Spark Streaming 等,都与 Kafka 有着紧密的集成,能够方便地从 Kafka 中读取数据并举行实时分析和处理 。
以一个电商实时数据分析体系为例,该体系必要对用户在电商平台上的实时举动数据举行分析,如用户的欣赏、点击、购买等举动,以便及时相识用户需求,优化商品推荐和营销策略。体系架构如下:

[*]数据采集:通过在电商平台的前端页面和后端服务中埋点,收集用户的举动数据,如用户 ID、商品 ID、举动类型(欣赏、点击、购买等)、举动时间等信息。然后,将这些数据发送到 Kafka 的user_behavior_topic主题中 。

[*]Kafka 传输数据:Kafka 集群接收来自各个数据源的用户举动数据,并将其存储在user_behavior_topic主题的不同分区中。由于 Kafka 具有高吞吐量和低延迟的特性,能够快速处理大量的实时数据写入,确保数据的及时性 。

[*]Flink 实时处理:Apache Flink 作为流处理框架,从 Kafka 的user_behavior_topic主题中拉取用户举动数据,并举行实时分析和处理。比方,Flink 可以实现以下功能:


[*]

[*]实时统计用户生动度:通过对用户举动数据举行实时统计,计算每个用户在一定时间窗口内的举动次数,从而得出用户的生动度。比方,计算过去 1 小时内每个用户的欣赏次数、点击次数等,对于生动度较高的用户,可以提供个性化的推荐和优惠活动 。



[*]

[*]实时商品推荐:根据用户的实时举动数据和汗青购买记载,利用机器学习算法举行实时商品推荐。比方,当用户欣赏某个商品时,Flink 可以实时分析该用户的汗青举动数据,找出与该商品相干且用户可能感爱好的其他商品,并将这些商品推荐给用户 。



[*]

[*]实时非常检测:通过对用户举动数据的实时分析,检测非常举动,如恶意刷单、账号被盗用等。比方,当某个用户在短时间内出现大量非常的购买举动时,Flink 可以及时发出警报,关照相干人员举行处理 。


[*]结果存储与展示:Flink 将处理后的结果数据发送到其他存储体系中,如 HBase、Elasticsearch 等,以便举行后续的查询和分析。同时,将实时分析结果展示在监控仪表盘上,供业务人员实时查看和决议。比方,通过 Grafana 等工具,将用户生动度、商品销售趋势等数据以图表的形式展示出来,帮助业务人员直观地相识业务动态 。
通过联合 Kafka 和 Flink 举行实时数据流处理,电商实时数据分析体系能够实时获取和分析用户举动数据,为企业提供及时、准确的决议支持,提拔用户体验和业务竞争力。比方,通过实时商品推荐功能,某电商平台的商品转化率提高了 20%,销售额增长了 15%;通过实时非常检测功能,乐成辨认并制止了多起恶意刷单和账号被盗用变乱,保障了平台的安全和用户的权益 。
6.4 案例分析:某电商平台的 Kafka 应用实践

某着名电商平台在业务快速发展过程中,面临着数据量激增、体系复杂度提高以及对实时性要求越来越高的挑衅。为了应对这些挑衅,该电商平台引入了 Kafka 作为关键的数据处理组件,在订单处理、库存管理和用户举动分析等多个核心业务场景中发挥了重要作用 。
订单处理:在订单处理场景中,该电商平台每天会产生数百万的订单。在引入 Kafka 之前,订单处理体系接纳传统的同步调用方式,各个服务之间耦合度高,处理服从低。当订单量增加时,体系容易出现性能瓶颈,导致订单处理延迟,影响用户体验。引入 Kafka 后,订单创建、支付、发货等操作产生的消息被发送到 Kafka 的order_topic主题中。不同的订单处理服务(如订单入库、库存扣减、物流关照等)作为消费者,订阅order_topic主题,从 Kafka 中拉取订单消息并举行异步处理。通过这种方式,实现了订单处理体系的解耦和并行处理,大大提高了订单处理的服从和吞吐量。引入 Kafka 后,订单处理的平均响应时间从原来的 5 秒紧缩到了 1 秒以内,订单处理的吞吐量提高了 5 倍以上,有效提拔了用户体验和业务处理本领 。
库存管理:在库存管理方面,电商平台的库存数据必要实时更新,以包管商品的可售性和库存的准确性。在利用 Kafka 之前,库存更新操作通过数据库的变乱举行,当业务量增大时,数据库的压力剧增,库存更新的延迟导致商品超卖或库存积压的问题时有发生。引入 Kafka 后,库存变更消息(如商品入库、出库、盘货等)被发送到 Kafka 的inventory_topic主题中。库存管理体系作为消费者,从 Kafka 中实时获取库存变更消息,并举行相应的库存更新操作。同时,Kafka 的消息恒久化特性包管了库存变更消息不会丢失,确保了库存数据的准确性和一致性。引入 Kafka 后,库存更新的实时性得到了极大提拔,库存数据的准确性从原来的 90% 提高到了 99% 以上,有效淘汰了商品超卖和库存积压的情况,降低了库存成本 。
用户举动分析:该电商平台非常器重用户举动分析,以实现精准营销和个性化推荐。在引入 Kafka 之前,用户举动数据分散在各个业务体系中,难以举行同一的收集和分析,且数据的实时性较差,无法及时为业务决议提供支持。引入 Kafka 后,用户在电商平台上的各种举动数据(如欣赏、点击、搜索、购买等)被实时收集并发送到 Kafka 的user_behavior_topic主题中。通过与 Spark Streaming 和 Hive 等大数据处理工具集成,从 Kafka 中拉取用户举动数据举行实时分析和离线分析。实时分析可以实实际时的用户举动监控和预警,如发现某个用户的非常举动及时举行处理;离线分析则可以发掘用户的举动模式和偏好,为精准营销和个性化推荐提供数据支持。通过引入 Kafka 举行用户举动分析,该电商平台的用户转化率提高了 15%,用户留存率提高了 10%,有效提拔了用户粘性和业务收入 。
通过在订单处理、库存管理和用户举动分析等业务场景中应用 Kafka,该电商平台实现了业务指标的显著提拔,包罗订单处理服从、库存管理准确性和用户转化率等方面。Kafka 的高吞吐量、低延迟、可扩展性和可靠性等特性,为电商平台的业务发展提供了强大的技术支持,帮助其在激烈的市场竞争中保持领先地位 。
七、Kafka 与其他消息队列对比

在消息队列领域,Kafka 依附其独特的设计和强大的性能在大数据处理场景中占据重要地位。然而,不同的消息队列适用于不同的业务场景,为了更全面地相识 Kafka 的优势和适用范围,我们将 Kafka 与其他常见的消息队列举行对比分析。
7.1 Kafka 与 RabbitMQ 对比



[*]性能:Kafka 以高吞吐量著称,它接纳顺序写磁盘、零拷贝等技术,每秒能够处理数十万甚至数百万条消息,延迟可低至毫秒级。在日志收集场景中,Kafka 能够快速接收并存储大量的日志消息。而 RabbitMQ 在吞吐量方面相对较低,每秒大概处理几万条消息,但其延迟更低,适用于对延迟要求极高的场景,如金融交易体系中的实时交易关照 。


[*]功能:RabbitMQ 功能丰富,支持多种消息模型,如简单队列、工作队列、发布 / 订阅、路由和主题模式等,并且提供了消息存活时间(TTL)、延迟 / 预定消息、死信交换器(DLX)等高级功能,能满足复杂的业务逻辑。在电商订单体系中,可利用其 TTL 功能设置订单消息的过期时间。Kafka 功能相对较为单一,主要专注于高吞吐量的消息处理和恒久化存储,包管分区内消息的顺序性,但不包管跨分区的顺序,也没有内置的消息重试、死信队列等机制,必要在应用层实现 。


[*]应用场景:Kafka 适用于处理大规模的实时数据流,如日志收集、实时数据分析、物联网数据处理等场景,这些场景通常对消息的吞吐量要求较高,对消息的顺序性和可靠性有一定要求,但答应少量消息的重复或丢失。比方,在一个物联网平台中,大量的传感器数据必要实时收集和处理,Kafka 可以轻松应对每秒数百万条传感器数据的写入,并将数据传输给实时分析体系举行处理。RabbitMQ 适用于对可靠性要求极高、消息处理逻辑复杂、消息量相对较小的场景,如金融行业的交易体系、电商的订单处理体系等,这些场景必要确保消息的准确传递和严酷的顺序处理,不答应消息丢失或重复 。
7.2 Kafka 与 Redis 对比



[*]消息处理本领:Redis 作为内存数据库,读写性能极高,能够实现微秒级的响应时间,在简单的消息队列场景中,如秒杀活动中的短时间内大量消息的快速处理,Redis 可以快速接收和处理消息,满足低延迟的需求。Kafka 虽然性能也很出色,但由于数据存储在磁盘上,延迟通常高于 Redis,不过 Kafka 通过分区机制可以实现高吞吐量,能够处理大规模的消息流,适用于大数据量的实时处理场景,如电商平台的实时订单处理 。


[*]数据恒久化:Redis 支持数据恒久化到磁盘,但其设计目标主要是提供高性能和低延迟,在出现故障时,可能会丢失部分未恒久化到磁盘的消息。Kafka 则将消息恒久化到磁盘,并通过副本机制和 ISR 聚集包管数据的可靠性,纵然部分节点出现故障,也能确保消息不丢失 。


[*]应用场景:Redis 适用于简单的中小型项目,特殊是对延迟敏感且数据量不是特殊巨大的场景,如缓存、计数器、简单的消息队列等。在一个小型的电商网站中,可利用 Redis 作为缓存来存储热门商品信息,同时也可以利用 Redis 的列表数据结构实现简单的消息队列,用于处理用户的品评消息等。Kafka 适用于必要稳定保存消息、处理大规模数据流、对可靠性要求高的应用场合,如日志收集、实时数据流处理、大数据分析等场景 。
八、总结与展望

Kafka 作为大数据和分布式体系领域的关键技术,以其独特的设计和杰出的性能,在浩繁应用场景中发挥着重要作用。通过对 Kafka 的深入探讨,我们全面相识了其核心概念、架构原理、特性以及丰富的应用场景。
从核心概念来看,Topic 作为消息的逻辑分类单位,Partition 实现了消息的物理划分和并行处理,Producer 负责消息的生产和发送,Consumer 和 Consumer Group 则提供了机动的消息消费和负载平衡机制,Broker 作为集群的核心组件,负担着消息存储、转发和集群协调的重任。这些核心概念相互协作,构成了 Kafka 强大的功能基础。
在架构原理方面,Kafka 的整体架构设计精妙,通过生产者集群、Kafka 集群、Zookeeper 集群(早期版本)和消费者集群的协同工作,实现了高效的消息处理流程。从消息的生产、存储到消费,每一个环节都经过精心设计和优化,确保了体系的高吞吐量、低延迟、恒久性、可靠性、容错性和高并发处理本领 。
Kafka 的特性使其在浩繁消息队列和分布式体系中脱颖而出。高吞吐量和低延迟特性使其能够快速处理大规模的实时数据流;可扩展性支持集群的动态扩展,轻松应对业务增长带来的挑衅;恒久性和可靠性通过消息恒久化和数据备份机制,包管了消息的不丢失和一致性;容错性确保在节点故障时体系仍能稳定运行;高并发本领则满足了数千个客户端同时读写的需求 。
在应用场景上,Kafka 广泛应用于日志收集、消息队列、实时数据流处理等领域。在日志收集场景中,它能够高效地收集和传输分布式体系中的海量日志数据,为后续的分析和运维提供支持;作为消息队列,Kafka 实现了分布式体系中不同服务之间的异步通信和解耦,提高了体系的可扩展性和机动性;在实时数据流处理中,Kafka 与流处理框架的紧密集成,为企业提供了实时获取和分析数据的本领,帮助企业做出及时、准确的决议 。
通过某电商平台的 Kafka 应用实践案例,我们直观地看到了 Kafka 在实际业务中的强大作用和显著效果。在订单处理、库存管理和用户举动分析等核心业务场景中,Kafka 的应用使得电商平台在订单处理服从、库存管理准确性和用户转化率等关键业务指标上取得了显著提拔 。
与其他常见的消息队列如 RabbitMQ 和 Redis 相比,Kafka 在性能、功能和应用场景上各有优势和偏重点。RabbitMQ 功能丰富,适用于对可靠性和消息处理逻辑要求较高、消息量相对较小的场景;Redis 读写性能极高,适用于简单的中小型项目和对延迟敏感的场景;而 Kafka 则依附其高吞吐量、可扩展性和可靠性,在大数据处理和实时数据流处理场景中表现出色 。
展望未来,随着大数据和分布式体系技术的不断发展,Kafka 有望在以下几个方面取得进一步的突破和发展:


[*]加强流处理本领:Kafka Streams 和 KSQL 作为 Kafka 提供的流处理框架,未来将不断加强功能和优化性能,能够处理更加复杂的流处理任务,并支持更多的 SQL 特性,为实时数据处理提供更强大的工具 。


[*]云原生支持:随着 Kubernetes 等容器编排工具的普及,Kafka 在云原生环境中的摆设和管理将变得更加容易。未来,Kafka 将进一步优化对云原平生台的支持,包罗更简单的摆设方式、更高效的资源利用以及更强的弹性扩展本领,以满足企业在云环境下的应用需求 。


[*]多租户支持:为了支持多租户环境下的应用,Kafka 将继承加强其安全性和隔离性。通过更细粒度的访问控制和配额管理,确保不同租户之间的数据和资源隔离,并提供更好的审计和监控功能,保障多租户应用的稳定运行 。


[*]更好的运维和监控工具:运维和监控是 Kafka 利用中的重要方面。未来,Kafka 将不断提拔其运维和监控工具的本领,加强 Kafka Manager、Confluent Control Center 等工具的功能,并与 Prometheus、Grafana 等主流监控体系举行更好的集成,提供更全面的监控和报警机制,帮助运维人员更好地管理 Kafka 集群 。


[*]加强的存储引擎:Kafka 的存储引擎也在不断演进,分层存储(Tiered Storage)技术的应用将使数据能够分层存储到不同的存储介质上(如本地磁盘和云存储),以降低存储成本并提高存储服从,适应不同业务场景对数据存储的需求 。


[*]智能数据路由和处理:借助机器学习和人工智能技术,Kafka 未来将在智能数据路由方面做出更多的改进。通过动态调整数据路由策略,Kafka 能够更高效地处理和分发数据,进一步提拔体系的性能和智能化程度 。
Kafka 在大数据和分布式体系领域已经取得了显著的成就,并且在未来有着广阔的发展远景。无论是在现有应用场景的深化应用,照旧在新领域的拓展应用,Kafka 都将持续发挥重要作用,为企业的数据处理和业务发展提供强大的技术支持。作为开辟者和技术爱好者,我们必要持续关注 Kafka 的发展动态,不断学习和掌握其新特性和新应用,以更好地应对日益增长的数据处理需求和业务挑衅 。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 一文搞懂Kafka:原理、架构与实战案例全解析