Kafka-原理解析
1、基础知识
1.1、存储结构图
1.2、topic结构
1.2.1、语法
/brokers/topics/[topic]
1.2.2、topic结构
[zk: 192.168.10.30:2181(CONNECTED) 2] ls /brokers [ids, seqid, topics] [zk: 192.168.10.30:2181(CONNECTED) 1] ls /brokers/topics [__consumer_offsets, kafkatest] [zk: 192.168.10.30:2181(CONNECTED) 3] get /brokers/topics/kafkatest {"partitions":{"0":[1,3,2],"1":[2,1,3],"2":[3,2,1]},"topic_id":"dpeV7n3fSyehh-ebygbwaQ","adding_replicas":{},"removing_replicas":{},"version":3} # 属性解析 version: 当前的版本号 partitions: 分区的信息
1.3、partition结构
1.3.1、语法
/brokers/topics/[topic]/partitions/[partitionId]/state
1.3.2、partition结构
[zk: 192.168.10.30:2181(CONNECTED) 4] ls /brokers/topics/kafkatest [partitions] [zk: 192.168.10.30:2181(CONNECTED) 5] ls /brokers/topics/kafkatest/partitions [0, 1, 2] [zk: 192.168.10.30:2181(CONNECTED) 6] get /brokers/topics/kafkatest/partitions/0 null [zk: 192.168.10.30:2181(CONNECTED) 7] get /brokers/topics/kafkatest/partitions/0/state {"controller_epoch":14,"leader":1,"version":1,"leader_epoch":0,"isr":[1,3,2]} # 属性解析 controller_epoch: 表示kafka集群中的中央控制器选举次数, leader: 表示该partition选举leader的brokerId, version: 版本编号默认为1, leader_epoch: 该partition leader选举次数, isr: [同步副本组brokerId列表]
1.4、broker信息
1.4.1、语法
/brokers/ids/[0...N]
1.4.2、broker结构
[zk: 192.168.10.30:2181(CONNECTED) 8] ls /brokers [ids, seqid, topics] [zk: 192.168.10.30:2181(CONNECTED) 9] ls /brokers/ids [1, 2, 3] [zk: 192.168.10.30:2181(CONNECTED) 10] get /brokers/ids/1 {"features":{},"listener_security_protocol_map":{"PLAINTEXT":"PLAINTEXT"},"endpoints":["PLAINTEXT://192.168.10.30:9092"],"jmx_port":-1,"port":9092,"host":"192.168.10.30","version":5,"timestamp":"1685678338970"} [zk: 192.168.10.30:2181(CONNECTED) 11] get /brokers/ids/2 {"features":{},"listener_security_protocol_map":{"PLAINTEXT":"PLAINTEXT"},"endpoints":["PLAINTEXT://192.168.10.31:9092"],"jmx_port":-1,"port":9092,"host":"192.168.10.31","version":5,"timestamp":"1685678356448"} [zk: 192.168.10.30:2181(CONNECTED) 12] get /brokers/ids/3 {"features":{},"listener_security_protocol_map":{"PLAINTEXT":"PLAINTEXT"},"endpoints":["PLAINTEXT://192.168.10.32:9092"],"jmx_port":-1,"port":9092,"host":"192.168.10.32","version":5,"timestamp":"1685678358975"} # 属性解析: jmx_port: jmx端口号, timestamp: kafka broker初始启动时的时间戳, host: 主机名或ip地址, version: 版本编号默认为1, port: kafka broker的服务端端口号,由server.properties中参数port确定
1.5、控制器
1.5.1、语法
/controller # 存储center controller中央控制器所在kafka broker的信息
1.5.2、控制器结构
[zk: 192.168.10.30:2181(CONNECTED) 13] ls /controller [] [zk: 192.168.10.30:2181(CONNECTED) 14] get /controller {"version":2,"brokerid":1,"timestamp":"1685678339168","kraftControllerEpoch":-1} # 属性解析 version: 版本编号默认为1, brokerid: kafka集群中broker唯一编号, timestamp: kafka broker中央控制器变更时的时间戳
1.6、控制策略
1.6.1、语法
/controller_epoch # 此值为一个数字,每次center controller变更controller_epoch值就会 + 1
1.6.2、控制策略结构
[zk: 192.168.10.30:2181(CONNECTED) 15] ls /controller_epoch []
[zk: 192.168.10.30:2181(CONNECTED) 16] get /controller_epoch 14
1.7、消费者
# 消费者信息: /consumers/[groupId]/ids/[consumerIdString] # 每个consumer都有一个唯一的ID,此id用来标记消费者信息消费者管理者: /consumers/[groupId]/owners/[topic]/[partitionId]
2、流程梳理
2.1、发布消息
2.1.1、基本逻辑
producer 采用 push 模式将消息发布到 broker,broker接收到消息,会根据分区算法选择将其存储到哪一个 partition,然后消息都被 append 到指定的 patition 中。
2.1.2、细节逻辑
producer 先从 zookeeper 的 "/brokers/.../state" 节点找到该 partition 的 leader producer 将消息发送给该 leader leader 将消息写入本地 log followers 从 leader pull 消息,写入本地 log 后 leader 发送 ACK leader 收到所有 ISR 中的 replica 的 ACK 后,更新 commit 并向 producer 发送 ACK
2.2、broker保存消息
2.2.1、基本逻辑
默认情况下,一个 topic 分成一个或多个 patition(num.partitions),每个 patition 就是一个文件夹,保存了所有消息和索引文件。 这些数据不会无限制的存储下去,会在某个时候自动清空,这是由以下两种配置决定的。 基于时间:log.retention.hours=168 基于大小:log.retention.bytes=1073741824
2.2.2、查询保存的目录
# ll /usr/local/kafka/logs/ | grep kafkatest drwxr-xr-x 2 root root 4096 Jun 2 12:49 kafkatest-0/ drwxr-xr-x 2 root root 4096 Jun 2 12:49 kafkatest-1/ drwxr-xr-x 2 root root 4096 Jun 2 14:40 kafkatest-2/
# tree /usr/local/kafka/logs/kafkatest-0/ /usr/local/kafka/logs/kafkatest-0/ ├── 00000000000000000000.index ├── 00000000000000000000.log ├── 00000000000000000000.timeindex ├── leader-epoch-checkpoint └── partition.metadata
2.3、topic逻辑
2.3.1、新增逻辑
controller 在 ZK 的 /brokers/topics 节点上注册 watcher - 当 topic 被创建,则 controller 会通过 watch 得到该 topic 的partition/replica 分配。 controller从 /brokers/ids 读取当前所有可用的 broker 列表,对于 set_p 中的每一个partition: - 从分配给该 partition 的所有 replica中任选一个可用的 broker 作为新的 leader,并将AR设置为新的 ISR - 将新的 leader 和 ISR 写入/brokers/topics/[topic]/partitions/[partition]/state
controller 通过 RPC 向相关的 broker 发送 LeaderAndISRRequest。
2.3.2、删除逻辑
controller 在 ZK 的 /brokers/topics 节点上注册 watcher, - 当 topic 被删除,则 controller 会通过 watch 得到该 topic 的partition/replica 分配。
若 delete.topic.enable=false,结束 - 否则 controller 注册在 /admin/delete_topics 上的 watch 被 fire,controller 通过回调向对应的 broker 发送 StopReplicaRequest。
2.4、broker故障
2.4.1、逻辑流程
controller 在 zookeeper 的 /brokers/ids/[brokerId] 节点注册 Watcher,当 broker 宕机时 zookeeper 会 fire watch controller 从 /brokers/ids 节点读取可用broker controller决定set_p,该集合包含宕机 broker 上的所有 partition 对 set_p 中的每一个 partition - 从/brokers/topics/[topic]/partitions/[partition]/state 节点读取 ISR - 决定新 leader - 将新 leader、ISR、controller_epoch 和 leader_epoch 等信息写入 state 节点 通过 RPC 向相关 broker 发送 leaderAndISRRequest 命令
2.4.2、查看节点状态
tail -f /usr/local/kafka/logs/controller.log # kafka-topics.sh --describe --bootstrap-server 192.168.10.30:9092,192.168.10.31:9092,192.168.10.32:9092 kafkatest ... Topic: kafkatest TopicId: dpeV7n3fSyehh-ebygbwaQ PartitionCount: 3 ReplicationFactor: 3 Configs: Topic: kafkatest Partition: 0 Leader: 1 Replicas: 1,3,2 Isr: 1,3,2 Topic: kafkatest Partition: 1 Leader: 2 Replicas: 2,1,3 Isr: 2,1,3 Topic: kafkatest Partition: 2 Leader: 3 Replicas: 3,2,1 Isr: 3,2,1