3.kafka3.x Broker相关原理

broker在zookeeper中存储的信息

3.kafka3.x Broker相关原理_第1张图片

3.kafka3.x Broker相关原理_第2张图片

  1. /kafka/brokers/ids 记录了所有存活的broker服务器id

  2. /kafka/brokers/topics/topic_name/partition/0/state 保存了关于该partition的leader信息和ISR信息

    {
    “controller_epoch” : 11,
    “leader” : 0,
    “version” : 1,
    “leader_epoch” : 3,
    “isr” : [ 0, 1 ]
    }

  3. /kafka/controller 用于选举leader,谁先找到controller谁则竞选成功

broker工作流程

3.kafka3.x Broker相关原理_第3张图片

每个broker中都有controller ZK中也有/controller节点 作用在于leader选举和同步zk上注册的leader isr相关信息

  1. broker启动向ZK注册,写入/broker/ids [0,1,2…]

  2. /kafka/controller 选举leader 谁先注册到controller上就是leader

  3. 选举出来的Controller去监听brokers节点变化

  4. ZK中的controller决定leader选举

  5. controller将节点信息通知ZK /brokers/topics/xxx/partition/0/state 维护leader和isr信息

  6. broker其他controller从ZK同步相关信息

  7. 此时producer的与集群中的leader进行通信,leader与其余follower之间再进行信息同步

  8. 如出现Broker中的leader宕机

  9. 发起重新选举

    1. 首先在ISR中存活为前提
    2. 再按照AR中排在前面的优先
    3. 例如AR[1,0,2],ISR[1,0,2]那么leader会按照1,0,2顺序来轮询
  10. Controller监听节点的变化

  11. 重新获取ISR

  12. 选择新的leader(在ISR中存活为前提,按照AR中排在前面的优先)

  13. 更新leader和ISR

broker重要参数

参数名称 描述
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。一般不建 议修改,交给系统自己管理。

节点服役和退役

服役(添加节点)

  1. 查看当前topic的分区规则 kafka-topics.sh --bootstrap-server node1:9092 --topic test_topic --describe

  2. 新增node3节点

  3. 创建一个负载均衡主题 vim topics-to-move.json

    {
     "topics": [
     {"topic": "test_topic"}
     ],
     "version": 1
    }
    
  4. 生成负载均衡计划

    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"]}]}
    
    

在这里插入图片描述

  1. 复制重新生成分区计划 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"]}]}
    
  2. 执行负载均衡计划

    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
    
    
  3. 验证

    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
    
    
  4. 此时再查看topic的描述,此时副本和leader已经改变

在这里插入图片描述

退役(移除节点)

  1. 查看当前topic的分区规则 kafka-topics.sh --bootstrap-server node1:9092 --topic test_topic --describe

在这里插入图片描述

  1. 此时如果需要对node2节点进行下线

  2. 编写需要执行负载均衡的主题json文件

    {
     "topics": [
     {"topic": "test_topic"}
     ],
     "version": 1
    }
    
  3. 生成一个负载均衡计划 bash …/bin/kafka-reassign-partitions.sh --bootstrap-server node1:9092 --topics-to-move-json-file ./topics-move-plan.json --broker-list “0” --generate

在这里插入图片描述

  1. 此时异常表示因为目前broker只有1台机器 但是replication-factor是2 无法做到副本为2此时修改partition0,1的副本为1

  2. 生成副本修改计划 /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
                ]
            }
        ]
    }
    

在这里插入图片描述

  1. 再执行负载均衡计划 bash …/bin/kafka-reassign-partitions.sh --bootstrap-server node1:9092 --topics-to-move-json-file ./topics-move-plan.json --broker-list “0” --generate
    在这里插入图片描述

  2. 此时再查看topic的状态 bash …/bin/kafka-topics.sh --bootstrap-server node1:9092 --topic test_topic --describe

在这里插入图片描述

  1. leader replicas 和ISR 都变成了0

kafka副本

  1. 副本作用可以提高数据可靠性
  2. 生产环境一般配置为2,可以保证数据可靠性,太多的副本会增加磁盘占用,且在数据副本同步的时候会占用网络资源降低效率
  3. Kafka中的副本分为leader和follower,producer只会把数据发往leader然后follower找leader进行数据同步
  4. kafka分区中所有的副本统称AR(Assigned Replicas)
  5. AR = ISR + OSR
    1. ISR: 表示leader保持同步的follower集合.如果follower长时间未向leader发送同步通信请求或者同步数据,该follower会被踢出ISR,时间阈值由replica.lag.time.max.ms控制默认30s.当leader发生故障时候会从ISR中重新选举新的leader
    2. OSR: 表示follower和leader副本同步时,延迟过高的副本

leader选举流程

kafka集群中有一个broker的controller会被选举成为controller leader,负责管理整个集群的broker的上下线,所有topic的分区副本分配和leader选举

3.kafka3.x Broker相关原理_第4张图片

故障迁移细节

LEO (Log End Offset): 每个副本的最后一个offset+1 即使最新的offset+1

HW (High Waterark): 所有副本中最小的LEO

follower故障
3.kafka3.x Broker相关原理_第5张图片

  1. follower发生故障之后会被临时踢出ISR
  2. 期间leader和其他follower继续接受数据
  3. 待follower恢复之后,follower会读取本地磁盘记录中的上次的HW,并将log文件高于HW的部分截取掉,从HW开始向leader进行同步
  4. 等到follower的LEO>=该partition的HW,即使follower追上了leader此时重新加入ISR
  5. 如上图如果broker2 宕机,宕机瞬间follower的HW和LEO 分别是5和7,此时leader和follower继续接受数据HW和LEO后移,此时broker2恢复发现自己的HW是5,先将HW之后的6,7清除,重新与leader通信进行HW和LEO的同步

leader故障

3.kafka3.x Broker相关原理_第6张图片

  1. leader故障之后,会从ISR中选出新的leader
  2. 为了保证多副本之前的数据一致性,其他follower会先自己log文件高于HW的部分截掉,然后重新从leader同步数据
  3. 保证了各个副本之间的数据一致性,但是不能保证数据不丢失和不重复

手动调整副本数

具体的生产环境可能因为每个服务器的配置和剩余资源不一样,如果全部根据kafka的默认规则进行负载均衡可能会造成资源的利用率不高,此时需要手动调整分区和副本的存储

  1. 创建副本存储计划 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]}]
    }
    
  2. 执行修改副本存储计划

    bash bin/kafka-reassign-partitions.sh --bootstrap-server node1:9092 --reassignment-json-file increase-replication-factor.json --execute
    
  3. 验证

    bin/kafka-reassign-partitions.sh -- bootstrap-server node1:9092 --reassignment-json-file increase-replication-factor.json --verify
    
  4. 查看分区描述describe

    bin/kafka-topics.sh --bootstrap-server node1:9092 --describe --topic test_topic
    

Leader Partition 负载均衡

默认情况下,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

3.kafka3.x Broker相关原理_第7张图片

Log文件和Index文件详解

3.kafka3.x Broker相关原理_第8张图片

  1. 默认每写入4kb大小的日志log之后,就会往index记录一个索引(稀疏索引)
  2. index文件保存了offset是相对offset,确保了offset的值占用空间不会过大
  3. 根据offset定位到segment文件
  4. 找到小于等于目标offset的最大offset对应的索引
  5. 定位到log文件
  6. 向下遍历找到目标record
参数 描述
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所有记录中最大时间戳为该文件的时间戳

3.kafka3.x Broker相关原理_第9张图片

例如segement2最新的记录没有达到过期时间,这次该segement不会被清理

compact日志压缩原理

3.kafka3.x Broker相关原理_第10张图片

相同key的数据只保留最后一个版本,压缩之后的数据会导致offset不连续,该策略适合一些特殊的场景,比如key是用户id,value是用户信息,用户的信息是会 不断更新的,compact策略只保留最新数据

kafka的高效读写原理

  1. kafka本身是分布式集群,采用分区技术提高了并行度
  2. 读数据采用了稀疏索引可以快速定位消费的数据
  3. 顺序写
  4. 页缓存 + 零拷贝

你可能感兴趣的:(kafka,kafka,java,分布式)