Kafka:分布式消息系统的核心原理与安装部署-CSDN博客
自定义 Kafka 脚本 kf-use.sh 的解析与功能与应用示例-CSDN博客
Kafka 生产者全面解析:从基础原理到高级实践-CSDN博客
Kafka 工作流程解析:从 Broker 工作原理、节点的服役、退役、副本的生成到数据存储与读写优化-CSDN博客
Kafka 消费者全面解析:原理、消费者 API 与Offset 位移-CSDN博客
Kafka 分区分配及再平衡策略深度解析与消费者事务和数据积压的简单介绍-CSDN博客
Kafka 核心要点解析_kafka mirrok-CSDN博客
Kafka 核心问题深度解析:全面理解分布式消息队列的关键要点_kafka队列日志-CSDN博客
目录
[一、Kafka Broker 工作流程](#一、Kafka Broker 工作流程)
[(一)Zookeeper 存储的 Kafka 信息](#(一)Zookeeper 存储的 Kafka 信息)
[(二)Kafka Broker 总体工作流程](#(二)Kafka Broker 总体工作流程)
[二、生产经验 ------ 节点服役和退役](#二、生产经验 —— 节点服役和退役)
[三、Kafka 副本](#三、Kafka 副本)
[(二)Leader 选举流程](#(二)Leader 选举流程)
[(三)Leader 和 Follower 故障处理细节](#(三)Leader 和 Follower 故障处理细节)
[(五)生产经验 ------ 手动调整分区副本的存储](#(五)生产经验 —— 手动调整分区副本的存储)
[(六)生产经验 ------Leader Partition 负载平衡](#(六)生产经验 ——Leader Partition 负载平衡)
[(七)生产经验 ------ 增加副本因子](#(七)生产经验 —— 增加副本因子)
[Topic 数据存储](#Topic 数据存储)
[delete 日志删除](#delete 日志删除)
[compact 日志压缩](#compact 日志压缩)
[页缓存 + 零拷贝技术](#页缓存 + 零拷贝技术)
在大数据处理领域,Kafka 作为一款高性能的分布式消息队列系统,扮演着至关重要的角色。它能够高效地处理大规模的实时数据,为众多大数据应用提供了可靠的数据传输和存储基础。本文将深入探讨 Kafka 的核心组件 ------Kafka Broker,包括其工作流程、副本机制、文件存储以及高效读写数据的原理,并分享一些生产环境中的实用经验。
一、Kafka Broker 工作流程
(一)Zookeeper 存储的 Kafka 信息

Kafka 与 Zookeeper 紧密协作,Zookeeper 存储了许多关键的 Kafka 信息。启动 Zookeeper 客户端后,通过ls /kafka
命令可以查看相关信息。其中,consumers
节点在老版本(0.9 版本之前)存放消费者的偏移量,而在新版本中,偏移量直接存储在集群中。我们还可以借助工具如 "漂亮的 zoo" 通过图形化界面更直观地查看 Zookeeper 中的信息。
通过网盘分享的文件:prettyZoo-win.msi

(二)Kafka Broker 总体工作流程

注册与选举
每一个 Broker 上线时,会在 Zookeeper 中进行注册。每个 Broker 中都有一个 Controller,它们会争先抢占 Zookeeper 中controller
节点的注册权,率先抢到的 Broker 中的 Controller 将在选举等事务中拥有决策权。
选举规则以在 ISR(与 Leader 保持同步的 Follower 集合)中存活为前提,按照 AR(分区中的所有副本集合)中排在前面的优先。例如,对于ar[1,0,2]
,isr[1,0,2]
,Leader 会按照1,0,2
的顺序进行轮询选举。选举出来的新节点会注册到 Zookeeper 中,并将信息记录下来,其他 Controller 则同步 Zookeeper 中的信息,假定broker中的leader挂掉了,会进行重新的选举。
数据处理
客户端发送消息给 Leader,Leader 负责记录数据并落盘形成 Log。Log 底层采用 Segment 机制,每一个 Segment 大小为 1G,为了实现数据的快速查找,在 1G 内的数据又分成了log
和index
两个文件。
二、生产经验 ------ 节点服役和退役
(一)服役新节点
新节点准备
(1)关闭 bigdata03,进行一个快照,并右键执行克隆操作。
(2)开启 bigdata04,并修改 IP 地址。
bash
vi /etc/sysconfig/network-scripts/ifcfg-ens33
修改完记得重启网卡:
systemctl restart network
(3)在 bigdata04 上,修改主机名称为 bigdata04。
bash
hostname bigdata04 # 临时修改
root@bigdata04 \~\]# vim /etc/hostname bigdata04 还要记得修改 /etc/hosts文件,并进行同步 ```bash 修改bigdata01的hosts 文件,修改完之后,记得同步一下 192.168.52.11 bigdata01 192.168.52.12 bigdata03 192.168.52.13 bigdata02 192.168.52.14 bigdata04 xsync.sh /etc/hosts scp -r /etc/hosts root@bigdata04:/etc/ ``` (4)重新启动 bigdata03、bigdata04。 (5)修改 bigdata04 中 kafka 的 broker.id 为 3。 ```bash 进入bigdata04的kafka中,修改里面的配置文件 config/server.properties ``` (6)删除 bigdata04 中 kafka 下的 datas 和 logs。 ```bash rm -rf datas/* logs/* ``` (7)启动 bigdata01、bigdata02、bigdata03 上的 kafka 集群。 先启动zk集群 ```bash xcall.sh zkServer.sh stop xcall.sh zkServer.sh start ``` 启动kafka集群(只能启动三台) ```bash kf.sh start ``` (8)单独启动 bigdata04 中的 kafka。 ```bash bin/kafka-server-start.sh -daemon ./config/server.properties ``` 查看kafka集群first主题的详情: > > ```bash > bin/kafka-topics.sh --bootstrap-server bigdata01:9092 --topic first --describe > ``` > > 发现副本数并没有增加。 > > 由于我之前创建first这个主题的时候只有一个副本,不是三个副本,所以呢,演示效果不佳。 > > ```bash > kafka-topics.sh --bootstrap-server bigdata01:9092 --topic third --create --partitions 3 --replication-factor 3 > ```  #### **执行负载均衡操作** (1)在kafka下创建一个要均衡的主题 ```bash 创建一个文件:vi topics-to-move.json 写上如下代码,如果多个topic 可以使用,分隔 { "topics": [ {"topic": "third"} ], "version": 1 } ``` (2)生成一个负载均衡的计划 在创建的时候,记得启动bigdata04节点,否则计划中还是没有bigdata04 ```bash bin/kafka-reassign-partitions.sh --bootstrap-server bigdata01:9092 --topics-to-move-json-file topics-to-move.json --broker-list "0,1,2,3" --generate ```  未来的分区策略拷贝一份: ```bash {"version":1,"partitions":[{"topic":"abc","partition":0,"replicas":[2,0,1],"log_dirs":["any","any","any"]},{"topic":"abc","partition":1,"replicas":[3,1,2],"log_dirs":["any","any","any"]},{"topic":"abc","partition":2,"replicas":[0,2,3],"log_dirs":["any","any","any"]}]} ``` (3)创建副本存储计划(所有副本存储在 broker0、broker1、broker2、broker3 中)。 vi increase-replication-factor.json ```bash {"version":1,"partitions":[{"topic":"first","partition":0,"replicas":[3,2,0],"log_dirs":["any","any","any"]},{"topic":"first","partition":1,"replicas":[0,3,1],"log_dirs":["any","any","any"]},{"topic":"first","partition":2,"replicas":[1,0,2],"log_dirs":["any","any","any"]}]} 以上这个内容来自于第二步的执行计划。 ``` (4)执行副本存储计划。 ```bash bin/kafka-reassign-partitions.sh --bootstrap-server bigdata01:9092 --reassignment-json-file increase-replication-factor.json --execute ``` (5)验证副本存储计划。 ```bash bin/kafka-reassign-partitions.sh --bootstrap-server bigdata01:9092 --reassignment-json-file increase-replication-factor.json --verify ``` 如果不相信添加成功,可以查看first节点的详情:  ### (二)退役旧节点 #### **执行负载均衡操作** 先按照退役一台节点,生成执行计划,然后按照服役时操作流程执行负载均衡。 (1)创建一个要均衡的主题 ```bash kafka下添加文件:vim topics-to-move.json 添加如下内容: { "topics": [ {"topic": "abc"} ], "version": 1 } ``` (2)创建执行计划。 ```bash bin/kafka-reassign-partitions.sh --bootstrap-server bigdata01:9092 --topics-to-move-json-file topics-to-move.json --broker-list "0,1,2" --generate ``` (3)创建副本存储计划(所有副本存储在 broker0、broker1、broker2 中)。 ```bash 添加文件: vi increase-replication-factor.json 添加如下代码: {"version":1,"partitions":[{"topic":"first","partition":0,"replicas":[0,2,1],"log_dirs":["any","any","any"]},{"topic":"first","partition":1,"replicas":[1,0,2],"log_dirs":["any","any","any"]},{"topic":"first","partition":2,"replicas":[2,1,0],"log_dirs":["any","any","any"]}]} ``` (4)执行副本存储计划 ```bash bin/kafka-reassign-partitions.sh --bootstrap-server hadoop11:9092 --reassignment-json-file increase-replication-factor.json --execute ``` (5)验证副本存储计划。 ```bash bin/kafka-reassign-partitions.sh --bootstrap-server hadoop11:9092 --reassignment-json-file increase-replication-factor.json --verify ```  #### **执行停止命令** 在要退役的节点(如`bigdata04`)上执行`bin/kafka-server-stop.sh`命令停止 Kafka 服务。 ## 三、Kafka 副本 ### (一)副本基本信息 (1)Kafka 副本作用:提高数据可靠性。 (2)Kafka 默认副本 1 个,生产环境一般配置为 2 个,保证数据可靠性;太多副本会增加磁盘存储空间,增加网络上数据传输,降低效率。 (3)Kafka 中副本分为:Leader 和 Follower。Kafka 生产者只会把数据发往 Leader, 然后 Follower 找 Leader 进行同步数据。 (4)Kafka 分区中的所有副本(包含Leader)统称为 **AR**(Assigned Repllicas)。 AR = ISR + OSR **ISR** ,表示和 Leader 保持同步的 Follower 集合。如果 Follower 长时间未向 Leader 发送通信请求或同步数据,则该 Follower 将被踢出 ISR。该时间阈值由 **replica.lag.time.max.ms** 参数设定,默认 **30s**。Leader 发生故障之后,就会从 ISR 中选举新的 Leader。 **OSR,**表示 Follower 与 Leader 副本同步时,延迟过多的副本. ### (二)Leader 选举流程  Kafka 集群中有一个 Broker 的 Controller 会被选举为 Controller Leader,负责管理集群 Broker 的上下线、所有 topic 的分区副本分配和 Leader 选举等工作,其信息同步依赖于 Zookeeper。例如,创建一个新的 topic(如`bigdata2401`),设置 4 个分区和 4 个副本,通过停止某些节点上的 Kafka 进程,可以观察到 Leader 的选举是按照 AR 进行的,而不是 ISR。 (1)创建一个新的 topic,4 个分区,4 个副本 ```bash bin/kafka-topics.sh --bootstrap-server hadoop11:9092 --create --topic bigdata2401 --partitions 4 --replication-factor 4 ``` (2)查看 Leader 分布情况  (3)停止掉 hadoop13 的 kafka 进程,并查看 Leader 分区情况 ```bash bin/kafka-server-stop.sh bin/kafka-topics.sh --bootstrap-server bigdata01:9092 --describe --topic bigdata2305 ```  (4)停止掉 hadoop14 的 kafka 进程,并查看 Leader 分区情况  通过以上演示,大家可以发现,选举是按照AR(跟Replicas一样)进行的,而不是ISR  ### (三)Leader 和 Follower 故障处理细节 LEO演示-- 每一个副本最后的偏移量offset + 1  HW(高水位线 High Water) 演示:所有副本中,最小的LEO   由于数据同步的时候先进入Leader,随后同步给Follower,假如Follower挂掉了,Leader和其他的Follower 继续往前存储数据,挂掉的节点从ISR集合中剔除,此时挂掉的Follower又重启了,它会先从上一次挂掉的节点的HW开始同步数据,直到追上最后一个Follower为止,此时会重新回归ISR。  ### (四)分区副本分配 如果 Kafka 服务器只有有限的节点数,在创建 topic 时,分区数和副本数的设置需要合理。例如,创建 16 分区、3 个副本的`second`主题,Kafka 在初始化时会按照特定算法选举第一 Leader,保障 Leader 不在一个 Broker 里面。 1)创建 16 分区,3 个副本 (1)创建一个新的 topic,名称为 second。 ```bash bin/kafka-topics.sh --bootstrap-server hadoop11:9092 --create --partitions 16 --replication-factor 3 --topic second ```  > bin/kafka-topics.sh --bootstrap-server bigdata01:9092 --create --topic bigdata230801 --partitions 3 --replication-factor 4 > > > 假如你有3个broker ,却创建4个副本,报错!! > > Error while executing topic command : Replication factor: 4 larger than available brokers: 3. > > \[2023-09-13 18:43:47,458\] ERROR > > org.apache.kafka.common.errors.InvalidReplicationFactorException: Replication factor: 4 larger than available brokers: 3 > > bin/kafka-topics.sh --bootstrap-server bigdata01:9092 --create --topic bigdata23 --partitions 4 --replication-factor 2 > > > 假如你有3个broker ,却创建4个分区,是可以的。 以上错误的意思是,目前只有2台服务器,却要创建3个副本,创建不了。 (2)查看分区和副本情况 ```bash bin/kafka-topics.sh --bootstrap-server hadoop102:9092 --describe --topic second ```   kafka在进行初始化的时候,选举谁当第一Leader,是有一定的算法的。算法保障了Leader不在一个broker里面。 ### (五)生产经验 ------ 手动调整分区副本的存储 在生产环境中,由于服务器配置和性能差异,可能需要手动调整分区副本的存储。例如,创建`three`主题,4 个分区、2 个副本,并将其所有副本存储到`broker0`和`broker1`两台服务器上。通过创建副本存储计划并执行`kafka-reassign-partitions.sh`命令来实现。  (1)创建一个新的 topic,名称为 three。 bin/kafka-topics.sh --bootstrap-server bigdata01:9092 --create --partitions 4 --replication-factor 2 --topic three (2)查看分区副本存储情况。 bin/kafka-topics.sh --bootstrap-server bigdata01:9092 --describe --topic three (3)创建副本存储计划(所有副本都指定存储在 broker0、broker1 中)。 vi increase-replication-factor.json 输入如下内容: ```bash { "version":1, "partitions":[{"topic":"three","partition":0,"replicas":[0,1]}, {"topic":"three","partition":1,"replicas":[0,1]}, {"topic":"three","partition":2,"replicas":[1,0]}, {"topic":"three","partition":3,"replicas":[1,0]}] } ``` (4)执行副本存储计划。 ```bash bin/kafka-reassign-partitions.sh --bootstrap-server bigdata01:9092 --reassignment-json-file increase-replication-factor.json --execute ``` (5)验证副本存储计划。 ```bash bin/kafka-reassign-partitions.sh -- bootstrap-server bigdata01:9092 --reassignment-json-file increase-replication-factor.json --verify ``` (6)查看分区副本存储情况 ```bash bin/kafka-topics.sh --bootstrap-server bigdata01:9092 --describe --topic three ```  ### (六)生产经验 ------Leader Partition 负载平衡 Kafka 通常会自动将 Leader Partition 均匀分散在各个机器上,但在某些 Broker 宕机后可能导致负载不均衡。相关参数如`auto.leader.rebalance.enable`(默认是`true`)、`leader.imbalance.per.broker.percentage`(默认是 10%)和`leader.imbalance.check.interval.seconds`(默认值 300 秒)控制着 Leader Partition 的平衡机制。在生产环境中,`auto.leader.rebalance.enable`常被修改为`false`以避免资源浪费。  ### (七)生产经验 ------ 增加副本因子 在生产环境中,若某个主题重要性提升,可能需要增加副本。例如创建`four`主题,初始副本数为 1,之后通过手动创建副本存储计划并执行`kafka-reassign-partitions.sh`命令来增加副本。需要注意的是,副本创建后不能直接通过命令修改,只能通过这种手动计划的方式增加。 1)创建 topic ```bash bin/kafka-topics.sh --bootstrap-server bigdata01:9092 --create --partitions 3 --replication-factor 1 --topic four ``` 通过命令行修改副本是否成功? 分区是可以通过语句修改的,只能改多,不能改少,副本创建以后就不能直接修改了。 ```bash bin/kafka-topics.sh --bootstrap-server bigdata01:9092 --alter --partitions 3 --replication-factor 3 --topic four 没办法使用命令修改的。 ``` 2)手动增加副本存储 通过命令查看副本情况 (1)创建副本存储计划(所有副本都指定存储在 broker0、broker1、broker2 中)。 ```bash vi increase-replication-factor.json ``` 添加如下内容: ```bash {"version":1,"partitions":[{"topic":"four","partition":0,"replicas":[0,1,2]},{"topic":"four","partition":1,"replicas":[0,1,2]},{"topic":"four","partition":2,"replicas":[0,1,2]}]} ``` (2)执行副本存储计划。 ```bash bin/kafka-reassign-partitions.sh --bootstrap-server hadoop11:9092 --reassignment-json-file increase-replication-factor.json --execute ``` 查看副本情况:  ## 四、文件存储 ### (一)文件存储机制 #### **Topic 数据存储** Topic 是逻辑概念,partition 是物理概念,每个 partition 对应一个`log`文件,Producer 生产的数据追加到`log`文件末端。为防止`log`文件过大导致数据定位效率低下,Kafka 采用分片和索引机制,将每个 partition 分为多个 segment,每个 segment 包括`.index`文件、`.log`文件和`.timeindex`等文件,这些文件位于以`topic名称+分区序号`命名的文件夹下,如`first - 0`。  #### **数据位置查找** 启动生产者发送消息后,可以在`/opt/installs/kafka3/datas/`下对应主题分区文件夹中查看相关文件。直接查看`log`日志可能是乱码,可通过`kafka-run-class.sh kafka.tools.DumpLogSegments`命令查看`index`和`log`信息。Kafka 使用稀疏索引,这使得数据读取速度较快。   ### (二)文件清理策略 #### **delete 日志删除** Kafka 中默认的日志(即 Segment)保存时间为 7 天,可通过`log.retention.hours`(最低优先级小时,默认 7 天)、`log.retention.minutes`(分钟,设置后小时设置不起作用)、`log.retention.ms`(最高优先级毫秒,设置后分钟设置不起作用)等参数修改保存时间。`log.retention.check.interval.ms`负责设置检查周期,默认 5 分钟。 delete 日志删除策略有基于时间(默认打开,以 segment 中所有记录中的最大时间戳作为该文件时间戳)和基于大小(默认关闭,超过设置的所有日志总大小,删除最早的 segment,`log.retention.bytes`默认等于 - 1,表示无穷大)两种方式。若一个 segment 中有部分数据过期,部分未过期,基于时间的删除策略会根据最大时间戳判断整个 segment 是否过期。  #### **compact 日志压缩** `log.cleanup.policy = compact`启用压缩策略,对于相同 key 的不同 value 值,只保留最后一个版本。压缩后的 offset 可能不连续,这种策略适用于特殊场景,如消息的 key 是用户 ID,value 是用户资料等。  ## 五、高效读写数据 #### **分区技术与并行度** Kafka 本身是分布式集群,采用分区技术,提高了并行度,能够同时处理多个分区的数据,从而提升整体性能。 #### **稀疏索引与快速定位** 读数据采用稀疏索引,可以快速定位要消费的数据。与 MySQL 中索引过多会影响写入速度不同,Kafka 的稀疏索引在保证快速定位数据的同时,不会对写入性能造成过大影响。 #### **顺序写磁盘** Kafka 的 Producer 生产数据时,写入`log`文件的过程是顺序写,即一直追加到文件末端。由于磁盘的机械结构特点,顺序写能大幅提高写入速度,官网数据表明,同样的磁盘,顺序写能达到 600M/s,而随机写只有 100K/s。 #### **页缓存 + 零拷贝技术** 零拷贝技术使得 Kafka 的数据加工处理操作交由生产者和消费者处理,Kafka Broker 应用层不关心存储的数据,无需经过应用层,提高了传输效率。 PageCache 页缓存功能被 Kafka 重度依赖。当有写操作时,操作系统将数据写入 PageCache;读操作时,先从 PageCache 中查找,找不到再从磁盘读取。这相当于将空闲内存作为磁盘缓存使用,进一步提升了读写性能。  ## 六、总结 本文全面深入地探讨了 Kafka Broker 的各个方面,包括其工作流程、节点管理、副本机制、文件存储以及高效读写数据的原理和生产环境中的应用经验。理解这些知识对于在大数据项目中正确使用和优化 Kafka 具有极为重要的意义。无论是在构建实时数据处理管道还是大规模数据存储系统时,Kafka 的这些特性都能为我们提供可靠、高效的解决方案。在实际应用中,我们需要根据具体的业务需求和硬件环境,合理配置 Kafka 的各项参数,以充分发挥其优势,应对复杂的数据处理挑战。