Broker主要用于kafka储存数据,以及和Zookeeper之间的数据交互

Kafka Broker 工作流程

1. Zookeeper 储存的 Kafka 信息

  我们可以通过Zookeeper可视化工具 PrettyZoo 看看zookeeper里面的数据,如下图我们需要了解的信息。

kafka broker默认端口 kafka中broker_kafka broker默认端口


2. Kafka Broker 总体工作流程

kafka broker默认端口 kafka中broker_bootstrap_02

Kafka副本

  1. 副本基本信息

  • Kafka副本作用:提高数据可靠性
  • Kafka默认副本1个,生产环境一般配置2个,保证数据可靠性;太多的副本会增加磁盘存储空间,增加网络数据传输,降低效率
  • Kafka副本分为Leader和Follower。Kafka生产者只会把数据发往Leader,然后Follower找Leader进行同步
  • Kafka分区中的所有副本统称为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副本同步时,延迟过多的副本。

  2. Leader选举流程

  Kafka集群中有一个broker的Controller会被选举为Controller Leader,负责管理集群broker的上下线所有的topic的分区副本分配Leader选举等工作。Controller的信息同步工作主要依赖于Zookeeper。

kafka broker默认端口 kafka中broker_kafka_03


  接下来就来验证这个流程,首先我启动了三台kafka做集群,并且都注册到同一个zookeeper中

# 创建一个新的topic,有3个分区,3个副本
./kafka-topics.sh --bootstrap-server 192.168.0.119:9092 --create --topic testTopic --partitions 3 --replication-factor 3

# 查看这个主题分区和副本的情况
./kafka-topics.sh --bootstrap-server 192.168.0.119:9092 --describe --topic testTopic

kafka broker默认端口 kafka中broker_bootstrap_04


  现在我们停掉一个kafka,再来看看这个topic的信息

kafka broker默认端口 kafka中broker_kafka broker默认端口_05


  然后再将刚才停掉的kafka重新启动查看效果

kafka broker默认端口 kafka中broker_kafka broker默认端口_06


  接下来在吧另一个停掉看看效果

kafka broker默认端口 kafka中broker_kafka_07


  从上面的图发现,ISR只是保存在线的kafka,并将下线了的kafka去除掉,而Leader的选举顺序是从AR获得的

Leader 和 Follower 故障处理细节

  生产环境中,如果Leader 和 Follower 出现异常下线了它的处理流程,先来了解两个概念:

  LEO(Log End Offser) 每个副本的最后有一个offset,LEO就是最新的offset+1

  HW (Hight Watermark) 所有副本中最小的LEO

kafka broker默认端口 kafka中broker_数据_08


  Follower 发生故障后会被临时剔除ISR,这个期间Leader和Follower会继续接收数据,待该Follower恢复后,Follower会读取本地磁盘记录的上次的HW,并将log文件高于HW部分的截取掉,从HW开始向leader进行同步;等该Follower的LEO大于等于该Partition的HW即Follower追上Leader之后,就可以重新加入ISR了

kafka broker默认端口 kafka中broker_kafka_09


  当Leader发生故障后,会从ISR中选出一个新的Leader,为保证多个副本之间的数据一致性,其余的Follower会先将各自的log文件高于HW的不去截掉,然后从新的Leader同步数据

  注意:这只能保证副本之间的数据一致性,并不能保证数据不丢失或者不重复

kafka broker默认端口 kafka中broker_kafka broker默认端口_10

分区副本分配

  如果kafka服务器只有4个节点,那么设置kafka的分区数大于服务器台数,在kafka底层是如何分配储存副本的呢?
  1. 创建16个分区,3个副本数

# 创建topic
./kafka-topics.sh --bootstrap-server 192.168.0.120:9092 --create --topic second --partitions 16 --replication-factor 3

# 查看topic详情
./kafka-topics.sh --bootstrap-server 192.168.0.120:9092 --describe --topic second

kafka broker默认端口 kafka中broker_bootstrap_11


  从主题的详情看ISR列,kafka在分配Leader和Follower的是否是尽量错开分配的,均匀分布,同时有保证了可靠性,负载均衡

Leader Partition 负载均衡

  正常情况下,Kafka本身会自动吧Leader Partition均匀分布在几个机器上,来保证每台机器的读写吞吐量都是均匀的。但是如果某些broker宕机,会导致Leader Partition过于集中在其他少数部分几台broker上,这会导致少数几台broker的读写请求压力过高,其他宕机的broker重启后都是follower partition,读写请求很低,造成集群负载不均衡
  为了解决这种现象,kafka也提供了几个参数:

参数

描述

auto.leader.rebalance.enable

默认为true,kafka会自动负载均衡,让每个节点均匀分布

leader.imbalance.per.broker.percentage

默认10%,每个broker允许的不平衡的leader的几率,如果每个broker超过这个阈值,控制器会触发leader的平衡

leader.imbalance.check.interval.seconds

默认值30S,检查leader负载是否均衡的间隔时间

  kafka在触发再平衡时,会消耗大量的性能,因为需要等待leader均匀分布后才能进行生产消费,会影响kafka的性能。所以一般情况的不建议开启此功能。如果非要开启这个功能,建议将不平衡几率调大,不要频繁触发平衡操作

文件存储

1. 文件储存机制

  Topic是逻辑上的概念,Partition是物理上的概念,每个Partition对应一个log文件,该log文件中存储的就是Producer生产的数据。Producer生产的数据会被不断的追加到该log文件的末端,为防止log文件过大导致数据定位效率低下,kafka采用分片索引机制,将每个partition分为多个segment,每个segment包括:.index文件、.log文件、.timeindex文件。这些文件位于一个文件夹下,该文件夹的命名规则:topic名称 + 分区序号,例如:first-0

kafka broker默认端口 kafka中broker_kafka_12


  接下来就来验证这个机制

  • 启动一个生产者并发送消息,例如我给first这个主题发送一个消息
# 启动一个生产者并发送消息
[root@localhost bin]# ./kafka-console-producer.sh --bootstrap-server 192.168.0.118:9092 --topic first
>hello world  # 发送消息
  • 在日志文件路径下查看
  • 这个时候我们直接查看日志文件发现是乱码的,我们可以通过通过kafka提供的工具进行查看index和log文件的信息
kafka-run-class.sh kafka.tools.DumpLogSegments --files ./00000000000000000000.index

kafka broker默认端口 kafka中broker_bootstrap_13


注意:

 1. index为稀疏索引,大约每往log文件写入4kb数据,会往index文件中写入一条索引。参数 log.index.interval.bytes 默认4kb

 2. index文件中保存的offset为相对offset,这样能确保offset的值所占空间不会过大,因此能将offset的值控制在固定大小

2. 文件清理策略
  kafka中**默认的日志保存时间为7天,**可以通过以下参数进行调整

  • log.retention.hours 最低优先级小时,默认7天
  • log.retention.minutes 分钟
  • log.retention.ms 最高优先级毫秒
  • log.retention.checkinterval.ms 设置检查周期,默认5分钟
      kafka中提供了两种清除策略:delete、compact,使用参数:log.cleanup.policy
    1). delete 日志删除:将过期数据删除,它有两种方式:
      a. 基于时间进行删除,默认打开,以segment中所有记录中的最大时间戳作为该文件的时间戳
      b. 基于大小进行删除,默认关闭,超过设置的所有日志总大小,删除最早的segment。可以通过log.retention.bytes设置,默认-1表示无穷大
    2). compact日志压缩:对于相同的key的不同的值,只保留最后一个版本,如下图:

      但是需要注意:压缩后的offset可能不是连续的,例如上图的k6,这种策略只适合特殊场景,如消息中的key是用户ID,value是用户的资料,通过这种压缩策略,整个消息集里就保存了所有用户最新的资料
Kafka 高效读写数据
  • Kafka本身是分布式集群,可以采用分区技术,并行度高
  • 读数据采用稀疏索引,可以快速定位要消费的数据
  • 顺序写磁盘
      Kafka的producer生产数据,要写到log文件中,写的过程是一直追加到文件末端,为顺序写
  • 页缓存 + 零拷贝技术
      零拷贝:Kafka的数据加工处理操作交由kafka生产者和消费者处理,kafka broker应用层不关心储存的数据,所以不用走应用层,传输效率高
      pageCache 页缓存:kafka重度依赖底层操作系统提供的pageCache功能,当上层有写操作时,操作系统只是把数据写入pageCache,当读操作发生时,现从pageCache中查找,如果找不到,再去磁盘中读取,实际上pageCache是把尽可能多的空闲内存都当做磁盘缓存来使用