/kafka/brokers/ids 记录了所有存活的broker服务器id
/kafka/brokers/topics/topic_name/partition/0/state 保存了关于该partition的leader信息和ISR信息
{
“controller_epoch” : 11,
“leader” : 0,
“version” : 1,
“leader_epoch” : 3,
“isr” : [ 0, 1 ]
}
/kafka/controller 用于选举leader,谁先找到controller谁则竞选成功
每个broker中都有controller ZK中也有/controller节点 作用在于leader选举和同步zk上注册的leader isr相关信息
broker启动向ZK注册,写入/broker/ids [0,1,2…]
/kafka/controller 选举leader 谁先注册到controller上就是leader
选举出来的Controller去监听brokers节点变化
ZK中的controller决定leader选举
controller将节点信息通知ZK /brokers/topics/xxx/partition/0/state 维护leader和isr信息
broker其他controller从ZK同步相关信息
此时producer的与集群中的leader进行通信,leader与其余follower之间再进行信息同步
如出现Broker中的leader宕机
发起重新选举
Controller监听节点的变化
重新获取ISR
选择新的leader(在ISR中存活为前提,按照AR中排在前面的优先)
更新leader和ISR
参数名称 | 描述 |
---|---|
replica.lag.time.max.ms | ISR 中,如果 Follower 长时间未向 Leader 发送通 信请求或同步数据,则该 Follower 将被踢出 ISR。 该时间阈值,默认 30s。 |
auto.leader.rebalance.enable | 默认是 true。 自动 Leader Partition 平衡。 |
leader.imbalance.per.broker.percentage | 默认是 10%。每个 broker 允许的不平衡的 leader 的比率。如果每个 broker 超过了这个值,控制器 会触发 leader 的平衡。 |
leader.imbalance.check.interval.seconds | 默认值 300 秒。检查 leader 负载是否平衡的间隔时 间。 |
log.segment.bytes | Kafka 中 log 日志是分成一块块存储的,此配置是 指 log 日志划分 成块的大小,默认值 1G。 |
log.index.interval.bytes | 默认 4kb,kafka 里面每当写入了 4kb 大小的日志 (.log),然后就往 index 文件里面记录一个索引。 |
log.retention.hours | Kafka 中数据保存的时间,默认 7 天。 |
log.retention.minutes | Kafka 中数据保存的时间,分钟级别,默认关闭。 |
log.retention.ms | Kafka 中数据保存的时间,毫秒级别,默认关闭。 |
log.retention.check.interval.ms | 检查数据是否保存超时的间隔,默认是 5 分钟。 |
log.retention.bytes | 默认等于-1,表示无穷大。超过设置的所有日志总 大小,删除最早的 segment。 |
log.cleanup.policy | 默认是 delete,表示所有数据启用删除策略; 如果设置值为 compact,表示所有数据启用压缩策 略。 |
num.io.threads | 默认是 8。负责写磁盘的线程数。整个参数值要占 总核数的 50%。 |
num.replica.fetchers | 副本拉取线程数,这个参数占总核数的 50%的 1/3 |
num.network.threads | 默认是 3。数据传输线程数,这个参数占总核数的 50%的 2/3 。 |
log.flush.interval.messages | 强制页缓存刷写到磁盘的条数,默认是 long 的最 大值,9223372036854775807。一般不建议修改, 交给系统自己管理。 |
log.flush.interval.ms | 每隔多久,刷数据到磁盘,默认是 null。一般不建 议修改,交给系统自己管理。 |
服役(添加节点)
查看当前topic的分区规则 kafka-topics.sh --bootstrap-server node1:9092 --topic test_topic --describe
新增node3节点
创建一个负载均衡主题 vim topics-to-move.json
{
"topics": [
{"topic": "test_topic"}
],
"version": 1
}
生成负载均衡计划
bin/kafka-reassign-partitions.sh --bootstrap-server node1:9092 --topics-to-move-json-file topics-to-move.json --broker-list "0,1" --generate
# 之前的负载均衡计划 可以用于回滚
Current partition replica assignment
{"version":1,"partitions":[{"topic":"test_topic","partition":0,"replicas":[0],"log_dirs":["any"]},{"topic":"test_topic","partition":1,"replicas":[0],"log_dirs":["any"]}]}
# 重新生成分区的计划
Proposed partition reassignment configuration
{"version":1,"partitions":[{"topic":"test_topic","partition":0,"replicas":[0],"log_dirs":["any"]},{"topic":"test_topic","partition":1,"replicas":[1],"log_dirs":["any"]}]}
复制重新生成分区计划 vim increase-replication-factor.json
{"version":1,"partitions":[{"topic":"test_topic","partition":0,"replicas":[0],"log_dirs":["any"]},{"topic":"test_topic","partition":1,"replicas":[1],"log_dirs":["any"]}]}
执行负载均衡计划
bash ../bin/kafka-reassign-partitions.sh --bootstrap-server node1:9092 --reassignment-json-file ./increase-replication-factor.json --execute
# 之前分片计划 可以用于回滚
Current partition replica assignment
{"version":1,"partitions":[{"topic":"test_topic","partition":0,"replicas":[0],"log_dirs":["any"]},{"topic":"test_topic","partition":1,"replicas":[0],"log_dirs":["any"]}]}
Save this to use as the --reassignment-json-file option during rollback
Successfully started partition reassignments for test_topic-0,test_topic-1
验证
bash ../bin/kafka-reassign-partitions.sh --bootstrap-server node1:9092 --reassignment-json-file ./increase-replication-factor.json --verify
Status of partition reassignment:
Reassignment of partition test_topic-0 is complete.
Reassignment of partition test_topic-1 is complete.
Clearing broker-level throttles on brokers 0,1
Clearing topic-level throttles on topic test_topic
此时再查看topic的描述,此时副本和leader已经改变
退役(移除节点)
此时如果需要对node2节点进行下线
编写需要执行负载均衡的主题json文件
{
"topics": [
{"topic": "test_topic"}
],
"version": 1
}
生成一个负载均衡计划 bash …/bin/kafka-reassign-partitions.sh --bootstrap-server node1:9092 --topics-to-move-json-file ./topics-move-plan.json --broker-list “0” --generate
此时异常表示因为目前broker只有1台机器 但是replication-factor是2 无法做到副本为2此时修改partition0,1的副本为1
生成副本修改计划 /bin/kafka-reassign-partitions.sh --bootstrap-server node1:9092 --reassignment-json-file ./decrease-replication-factor.json --execute
{
"version": 1,
"partitions": [
{
"topic": "test_topic",
"partition": 1,
"replicas": [
0
]
},
{
"topic": "test_topic",
"partition": 0,
"replicas": [
0
]
}
]
}
再执行负载均衡计划 bash …/bin/kafka-reassign-partitions.sh --bootstrap-server node1:9092 --topics-to-move-json-file ./topics-move-plan.json --broker-list “0” --generate
此时再查看topic的状态 bash …/bin/kafka-topics.sh --bootstrap-server node1:9092 --topic test_topic --describe
kafka集群中有一个broker的controller会被选举成为controller leader,负责管理整个集群的broker的上下线,所有topic的分区副本分配和leader选举
LEO (Log End Offset): 每个副本的最后一个offset+1 即使最新的offset+1
HW (High Waterark): 所有副本中最小的LEO
leader故障
具体的生产环境可能因为每个服务器的配置和剩余资源不一样,如果全部根据kafka的默认规则进行负载均衡可能会造成资源的利用率不高,此时需要手动调整分区和副本的存储
创建副本存储计划 vim increase-replication-factor.json
{
"version":1,
"partitions":[{"topic":"test_topic","partition":0,"replicas":[0,1]},
{"topic":"test_topic","partition":1,"replicas":[0,1]}, # 修改分区的replicas即可
{"topic":"test_topic","partition":2,"replicas":[1,0]},
{"topic":"test_topic","partition":3,"replicas":[1,0]}]
}
执行修改副本存储计划
bash bin/kafka-reassign-partitions.sh --bootstrap-server node1:9092 --reassignment-json-file increase-replication-factor.json --execute
验证
bin/kafka-reassign-partitions.sh -- bootstrap-server node1:9092 --reassignment-json-file increase-replication-factor.json --verify
查看分区描述describe
bin/kafka-topics.sh --bootstrap-server node1:9092 --describe --topic test_topic
默认情况下,kafka会自动将Leader Partition均匀的分布到各个机器上,保证每一台的机器的读写吞吐量均匀,但是如果某一些broker宕机,会导致leader partition过于集中在少部分broker机器上,会导致部分broker压力过大,其他broker重启之后都是follower,导致读写请求很低,造成集群的负载不均衡
kafka通过三个参数来控制leader partition的负载均衡
auto.leader.rebalance.enable 是否开启 默认开启
leader.imbalance.per.broker.percentage 允许不平衡比例 默认10%
leader.imbalance.check.interval.seconds 检查leader负载均衡时间间隔 默认300s
leader.imbalance.per.broker.percentage计算规则
如下实例为例
Topic: test_topic Partition: 0 Leader: 0 Replicas: [3,0,2,1] Isr: [3,0,2,1]
Topic: test_topic Partition: 1 Leader: 1 Replicas: [1,2,3,0] Isr: [1,2,3,0]
Topic: test_topic Partition: 2 Leader: 2 Replicas: [0,3,1,2] Isr: [0,3,1,2]
Topic: test_topic Partition: 3 Leader: 3 Replicas: [2,1,0,3] Isr: [2,1,0,3]
如果此时broker0节点宕机为例,此时AR中优先副本是3,但3不是leader节点,所以不平衡+1,AR副本总数是4,计算出不平衡节点为 1/4 > 10% 需要再平衡
在生产环境下一般不开启自动平衡,因为触发leader partition的自动平衡会损耗性能,或者将自动触发平衡的leader.imbalance.per.broker.percentage 参数阈值调大,一般采用手动调整的模式
kafka的文件存储,topic是一个逻辑上的概念,而partition是物理上的概念.一个partition对应一个log文件,log文件存储了producer生产的数据,producer生产的数据会不断的 追加 到log文件的尾部,为了提高log文件定位效率,kafka采用了分片和索引的策略.每一个partition文件分割成多个segement,每一个segement包含了 .index .log .timeindex等文件位于同一个目录下,该目录命名规则为topic名称+分区序号如 test_topic-0
Log文件和Index文件详解
参数 | 描述 |
---|---|
log.segment.bytes | Kafka 中 log 日志是分成一块块存储的,此配置是指 log 日志划分 成块的大小,默认值 1G。 |
log.index.interval.bytes | 默认 4kb,kafka 里面每当写入了 4kb 大小的日志(.log),然后就 往 index 文件里面记录一个索引。 稀疏索引。 |
kafka默认日志保存时间为7天日志过期之后kafka提供了两种清理策略delete和compact两种
参数 | 描述 |
---|---|
log.retention.hours | 最低优先级小时,默认 7 天 |
log.retention.minutes | 分钟 优先级高于log.retention.hours |
log.retention.ms | 最高优先级毫秒 |
log.retention.check.interval.ms | 负责设置检查周期,默认 5 分钟 |
log.cleanup.policy | 日志清理策略 默认delete |
log.retention.bytes | 基于大小:默认关闭。超过设置的所有日志总大小,,默认等于-1,表示无穷大 |
基于时间以中segement所有记录中最大时间戳为该文件的时间戳
例如segement2最新的记录没有达到过期时间,这次该segement不会被清理
compact日志压缩原理
相同key的数据只保留最后一个版本,压缩之后的数据会导致offset不连续,该策略适合一些特殊的场景,比如key是用户id,value是用户信息,用户的信息是会 不断更新的,compact策略只保留最新数据