Kafka04 - Broker(底层,难点)

Kafka Broker

一:Broker工作流程

1:Zookeeper存储的Kafka信息

高版本的Kafka已经可以不使用zookeeper

zookeeper存储了Kafka各种各样的相关信息:

  1. 记录了有哪些Kafka服务器:/kafka/brokers/ids
  2. 记录了这些服务器中谁是Leader:/kafka/borkers/topics/first/partiontions/0/state
  3. 记录了哪些服务可用:/kafka/borkers/topics/first/partiontions/0/state
  4. 记录了协调者contorller[谁去辅助选举Leader]:/kafka/controller

2:Kafka Broker总体工作流程

在这里插入图片描述

  1. broker在启动之后在zk中注册
  2. controller的确定:谁先在zookeeper中注册,谁作为主controller,谁说了算
  3. 由选举出来的Controller监听brokers节点的变化
  4. controller决定了Leader选举【选举的规则是:在isr中存活为前提,按照AR(All Reflica)中排在前面的优先】
  5. 将节点信息上传到ZK
  6. 其他controller从zk同步相关的信息
  7. 假设broker1中Leader挂了,Controller就会监听到节点的变化,然后获取ISR,选举新的Leader,最后更新Leader & ISR

在这里插入图片描述

拟Kafka上下线,Zookeeper中数据变化

# 查看/kafka/brokers/ids路径上的节点
ls /kafka/brokers/ids
[0, 1, 2]

# 查看/kafka/controller路径上的数据
{"version":1,"brokerid":0,"timestamp":"1637292471777"}

# 查看/kafka/brokers/topics/first/partitions/0/state路径上的数据
get /kafka/brokers/topics/first/partitions/0/state
{"controller_epoch":24,"leader":0,"version":1,"leader_epoch":18,"isr":[0,1,2]}

下线测试

# 停止hadoop104上的kafka
[hadoop104 kafka]$ bin/kafka-server-stop.sh
# 再次查看/kafka/brokers/ids路径上的节点
ls /kafka/brokers/ids
[0, 1]
# 再次查看/kafka/controller路径上的数据
get /kafka/controller
{"version":1,"brokerid":0,"timestamp":"1637292471777"}
# 再次查看/kafka/brokers/topics/first/partitions/0/state路径上的数据
get /kafka/brokers/topics/first/partitions/0/state
{"controller_epoch":24,"leader":0,"version":1,"leader_epoch":18,"isr":[0,1]}

3:Broker重要参数

参数名称描述
replica.lag.time.max.msISR中,如果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.bytesKafka中log日志是分成一块块存储的,此配置是指log日志划分 成块的大小,默认值1G。
log.index.interval.bytes默认4kb,kafka里面每当写入了4kb大小的日志(.log),然后就往index文件里面记录一个索引。
log.retention.hoursKafka中数据保存的时间,默认7天。
log.retention.minutesKafka中数据保存的时间,分钟级别,默认关闭。
log.retention.msKafka中数据保存的时间,毫秒级别,默认关闭。
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:新节点的服役

新节点的准备

关闭hadoop4,并且右键执行克隆操作,开启hadoop5,并修改ip地址

vim /etc/sysconfig/network-scripts/ifcfg-ens33

DEVICE=ens33
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=static
NAME="ens33"
IPADDR=192.168.10.105 # <-------- 注意修改这行
PREFIX=24
GATEWAY=192.168.10.2
DNS1=192.168.10.2

在hadoop105上,修改主机名称为hadoop105

vim /etc/hostname
hadoop105

重新启动hadoop104、hadoop105。 -> 修改haodoop105中kafka的broker.id为3。 -> 删除hadoop105中kafka下的datas和logs。

rm -rf datas/* logs/*

启动hadoop102、hadoop103、hadoop104上的kafka集群

zk.sh start
kf.sh start

单独启动hadoop105中的kafka

bin/kafka-server-start.sh -daemon ./config/server.properties

执行负载均衡操作

创建一个要均衡的主题

vim topics-to-move.json 
{
    "topics": [
        {"topic": "first"}

    ],
    "version": 1
}

生成一个负载均衡的计划

# 生成负载均衡的计划
[hadoop102 kafka]$ bin/kafka-reassign-partitions.sh --bootstrap-server hadoop102:9092  
    --topics-to-move-json-file topics-to-move.json 
    --broker-list "0,1,2,3" 
    --generate

Current partition replica assignment
{"version":1,"partitions":[{"topic":"first","partition":0,"replicas":[0,2,1],"log_dirs":["any","any","any"]},{"topic":"first","partition":1,"replicas":[2,1,0],"log_dirs":["any","any","any"]},{"topic":"first","partition":2,"replicas":[1,0,2],"log_dirs":["any","any","any"]}]}

Proposed partition reassignment configuration
{"version":1,"partitions":[{"topic":"first","partition":0,"replicas":[2,3,0],"log_dirs":["any","any","any"]},{"topic":"first","partition":1,"replicas":[3,0,1],"log_dirs":["any","any","any"]},{"topic":"first","partition":2,"replicas":[0,1,2],"log_dirs":["any","any","any"]}]}

创建副本存储计划(所有副本存储在broker0、broker1、broker2、broker3中)

vim increase-replication-factor.json

# 输入下面的内容
{
	"version":1,
	"partitions":[
		{
			"topic":"first",
			"partition":0,
			"replicas":[2,3,0],
			"log_dirs":["any","any","any"]
		},
		{
			"topic":"first",
			"partition":1,
			"replicas":[3,0,1],
			"log_dirs":["any","any","any"]
		},
		{
			"topic":"first",
			"partition":2,
			"replicas":[0,1,2],
			"log_dirs":["any","any","any"]
		}
	]
}

执行副本存储计划

bin/kafka-reassign-partitions.sh --bootstrap-server hadoop102:9092 
    --reassignment-json-file increase-replication-factor.json 
    --execute

验证副本存储计划

bin/kafka-reassign-partitions.sh --bootstrap-server hadoop102:9092 
    --reassignment-json-file increase-replication-factor.json 
    --verify

2:旧节点的退役

执行负载均衡操作

先按照退役一台节点,生成执行计划,然后按照服役时操作流程执行负载均衡。

创建一个要均衡的主题

[hadoop102 kafka]$ vim topics-to-move.json 

{
    "topics": [
        {"topic": "first"}
    ],
    "version": 1
}

创建执行计划

bin/kafka-reassign-partitions.sh --bootstrap-server hadoop102:9092  
    --topics-to-move-json-file topics-to-move.json 
    --broker-list "0,1,2" 
    --generate

Current partition replica assignment
{"version":1,"partitions":[{"topic":"first","partition":0,"replicas":[2,0,1],"log_dirs":["any","any","any"]},{"topic":"first","partition":1,"replicas":[3,1,2],"log_dirs":["any","any","any"]},{"topic":"first","partition":2,"replicas":[0,2,3],"log_dirs":["any","any","any"]}]}

Proposed partition reassignment configuration
{"version":1,"partitions":[{"topic":"first","partition":0,"replicas":[2,0,1],"log_dirs":["any","any","any"]},{"topic":"first","partition":1,"replicas":[0,1,2],"log_dirs":["any","any","any"]},{"topic":"first","partition":2,"replicas":[1,2,0],"log_dirs":["any","any","any"]}]}

创建副本存储计划(所有副本存储在broker0、broker1、broker2中)

vim increase-replication-factor.json

# 输入下面的内容
{
	"version":1,
	"partitions":[
		{
			"topic":"first",
			"partition":0,
			"replicas":[2,0,1],
			"log_dirs":["any","any","any"]
		},
		{
			"topic":"first",
			"partition":1,
			"replicas":[0,1,2],
			"log_dirs":["any","any","any"]
		},
		{
			"topic":"first",
			"partition":2,
			"replicas":[1,2,0],
			"log_dirs":["any","any","any"]
		}
	]
}

执行副本存储计划

bin/kafka-reassign-partitions.sh --bootstrap-server hadoop102:9092 
    --reassignment-json-file increase-replication-factor.json 
    --execute

验证副本存储计划

bin/kafka-reassign-partitions.sh --bootstrap-server hadoop102:9092 
    --reassignment-json-file increase-replication-factor.json 
    --verify

Status of partition reassignment:
Reassignment of partition first-0 is complete.
Reassignment of partition first-1 is complete.
Reassignment of partition first-2 is complete.

Clearing broker-level throttles on brokers 0,1,2,3
Clearing topic-level throttles on topic first

执行停止命令

bin/kafka-server-stop.sh 

三:Kafka 分区副本(重点,面试点)

1:主题,分区和副本

一个非常大的topic可以分布到多个broker(即服务器)上

一个topic可以分为多个partition,每个partition是一个有序的队列

一个topic的每个分区partition都有若干个副本replica,一个Leader和若干个Follower。

在这里插入图片描述

  • Leader:每个分区多个副本的“主”,生产者发送数据的对象,以及消费者消费数据的对象都是Leader
  • Follower:每个分区多个副本中的“从”,实时从Leader中同步数据,保持和Leader数据的同步。Leader发生故障时,某个Follower会成为新的Leader。

2:副本基本信息

副本的作用:提高数据的可靠性(冗余 -> 提高可靠性,常见架构手段)

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副本同步时,延迟过多的副本。

还有两个重要的offset点名词需要记住:

  • LEO(Log End Offset)每一个副本最后的一个offset,LEO = 最新的Offset + 1
  • HW (High Watermark) 所有副本的最小的LEO

在这里插入图片描述

3:Leader选举流程(面)

Kafka集群中有一个broker的Controller会被选举为Controller Leader

Controller Leader负责管理集群broker的上下线,所有topic的分区副本分配Leader选举等工作。

Controller的信息同步工作是依赖于Zookeeper的。【前面已经说过了,详见Kafka Broker总体工作流程】

在这里插入图片描述
创建一个新的topic,4个分区,4个副本

bin/kafka-topics.sh --bootstrap-server hadoop102:9092 
	--create --topic test  # 创建一个topic叫做test
	--partitions 4 # 4个分区
	--replication-factor 4 # 4个副本
Created topic test.

查看Leader分布情况

bin/kafka-topics.sh --bootstrap-server hadoop102:9092 
	--describe 
	--topic test
	
Topic: test	TopicId: awpgX_7WR-OX3Vl6HE8sVg	PartitionCount: 4	ReplicationFactor: 4	Configs: segment.bytes=1073741824
	Topic: test	Partition: 0	Leader: 3	Replicas: 3,0,2,1	Isr: 3,0,2,1
	Topic: test	Partition: 1	Leader: 1	Replicas: 1,2,3,0	Isr: 1,2,3,0
	Topic: test	Partition: 2	Leader: 0	Replicas: 0,3,1,2	Isr: 0,3,1,2
	Topic: test	Partition: 3	Leader: 2	Replicas: 2,1,0,3	Isr: 2,1,0,3

停止掉hadoop105的kafka进程,并查看Leader分区情况

[hadoop105 kafka]$ bin/kafka-server-stop.sh

[hadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server hadoop102:9092 
	--describe 
	--topic test 
	
Topic: test	TopicId: awpgX_7WR-OX3Vl6HE8sVg	PartitionCount: 4	ReplicationFactor: 4	Configs: segment.bytes=1073741824
	Topic: test	Partition: 0	Leader: 0	Replicas: 3,0,2,1	Isr: 0,2,1
	Topic: test	Partition: 1	Leader: 1	Replicas: 1,2,3,0	Isr: 1,2,0
	Topic: test	Partition: 2	Leader: 0	Replicas: 0,3,1,2	Isr: 0,1,2
	Topic: test	Partition: 3	Leader: 2	Replicas: 2,1,0,3	Isr: 2,1,0

停止掉hadoop104的kafka进程,并查看Leader分区情况

[hadoop104 kafka]$ bin/kafka-server-stop.sh

[hadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server hadoop102:9092 
	--describe 
	--topic test 
	
Topic: test	TopicId: awpgX_7WR-OX3Vl6HE8sVg	PartitionCount: 4	ReplicationFactor: 4	Configs: segment.bytes=1073741824
	Topic: test	Partition: 0	Leader: 0	Replicas: 3,0,2,1	Isr: 0,1
	Topic: test	Partition: 1	Leader: 1	Replicas: 1,2,3,0	Isr: 1,0
	Topic: test	Partition: 2	Leader: 0	Replicas: 0,3,1,2	Isr: 0,1
	Topic: test	Partition: 3	Leader: 1	Replicas: 2,1,0,3	Isr: 1,0

启动hadoop105的kafka进程,并查看Leader分区情况

[hadoop105 kafka]$ bin/kafka-server-start.sh -daemon config/server.properties

[hadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server hadoop102:9092 
	--describe 
	--topic test 
Topic: test	TopicId: awpgX_7WR-OX3Vl6HE8sVg	PartitionCount: 4	ReplicationFactor: 4	Configs: segment.bytes=1073741824
	Topic: test	Partition: 0	Leader: 0	Replicas: 3,0,2,1	Isr: 0,1,3
	Topic: test	Partition: 1	Leader: 1	Replicas: 1,2,3,0	Isr: 1,0,3
	Topic: test	Partition: 2	Leader: 0	Replicas: 0,3,1,2	Isr: 0,1,3
	Topic: test	Partition: 3	Leader: 1	Replicas: 2,1,0,3	Isr: 1,0,3

4:故障处理细节(重点)

4.1:Follower故障
  1. 被临时的踢出ISR,这个期间,其他的Leader & Follower正常接收数据
  2. 该Follower恢复之后,会读取自己上一次记录的HW【高水位】,然后将Log中高于HW的全部截取掉,从HW开始同步
  3. 等LEO >= 这个分区的HW,也就表名了Follower追上了Leader,此时就可以将这个Follwer重新加入回到ISR

在这里插入图片描述

4.2:Leader故障
  • 从ISR中选出新的Leader
  • 为了保证数据的一致性,其余的没有竞选成功的Follower会选择将各自的高于HW的部分截掉,然后从新的Leader同步数据
  • 这种方式只能保证数据一致性,不能保证数据不丢失或者不重复

在这里插入图片描述

分区副本的分配

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

创建16分区,3个副本:

(1)创建一个新的topic,名称为second

[hadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server hadoop102:9092 
    --create --partitions 16 
    --replication-factor 3 
    --topic second

(2)查看分区和副本情况

bin/kafka-topics.sh --bootstrap-server hadoop102:9092 
    --describe 
    --topic second

Topic: second4	Partition: 0	Leader: 0	Replicas: 0,1,2	Isr: 0,1,2
Topic: second4	Partition: 1	Leader: 1	Replicas: 1,2,3	Isr: 1,2,3
Topic: second4	Partition: 2	Leader: 2	Replicas: 2,3,0	Isr: 2,3,0
Topic: second4	Partition: 3	Leader: 3	Replicas: 3,0,1	Isr: 3,0,1

Topic: second4	Partition: 4	Leader: 0	Replicas: 0,2,3	Isr: 0,2,3
Topic: second4	Partition: 5	Leader: 1	Replicas: 1,3,0	Isr: 1,3,0
Topic: second4	Partition: 6	Leader: 2	Replicas: 2,0,1	Isr: 2,0,1
Topic: second4	Partition: 7	Leader: 3	Replicas: 3,1,2	Isr: 3,1,2

Topic: second4	Partition: 8	Leader: 0	Replicas: 0,3,1	Isr: 0,3,1
Topic: second4	Partition: 9	Leader: 1	Replicas: 1,0,2	Isr: 1,0,2
Topic: second4	Partition: 10	Leader: 2	Replicas: 2,1,3	Isr: 2,1,3
Topic: second4	Partition: 11	Leader: 3	Replicas: 3,2,0	Isr: 3,2,0

Topic: second4	Partition: 12	Leader: 0	Replicas: 0,1,2	Isr: 0,1,2
Topic: second4	Partition: 13	Leader: 1	Replicas: 1,2,3	Isr: 1,2,3
Topic: second4	Partition: 14	Leader: 2	Replicas: 2,3,0	Isr: 2,3,0
Topic: second4	Partition: 15	Leader: 3	Replicas: 3,0,1	Isr: 3,0,1

在这里插入图片描述

5:副本生产经验

5.1:手动调整分区副本存储

在这里插入图片描述

手动调整分区副本存储的步骤如下:

  1. 创建一个新的topic,名称为three
bin/kafka-topics.sh --bootstrap-server hadoop102:9092 
	--create 
	--partitions 4 
	--replication-factor 2 
	--topic three
  1. 查看分区副本存储情况
bin/kafka-topics.sh --bootstrap-server hadoop102:9092 
    --describe 
    --topic three
  1. 创建副本存储计划(所有副本都指定存储在broker0、broker1中)
vim increase-replication-factor.json
{
	"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]}
    ]
}
  1. 执行副本存储计划
bin/kafka-reassign-partitions.sh --bootstrap-server hadoop102:9092 
    --reassignment-json-file increase-replication-factor.json # 指定存储计划文件
    --execute # 执行存储计划
  1. 验证副本存储计划
bin/kafka-reassign-partitions.sh --bootstrap-server hadoop102:9092 
	--reassignment-json-file increase-replication-factor.json 
	--verify # 验证存储计划
  1. 查看分区副本存储情况
bin/kafka-topics.sh --bootstrap-server hadoop102:9092 
    --describe 
    --topic three
5.2:Leader Partition负载平衡

在这里插入图片描述

参数名称描述
auto.leader.rebalance.enable默认是true。 自动Leader Partition 平衡。生产环境中,leader重选举的代价比较大,可能会带来性能影响,建议设置为false关闭。
leader.imbalance.per.broker.percentage默认是10%。每个broker允许的不平衡的leader的比率。如果每个broker超过了这个值,控制器会触发leader的平衡。
leader.imbalance.check.interval.seconds默认值300秒。检查leader负载是否平衡的间隔时间。
5.3:增加副本因子

在生产环境当中,由于某个主题的重要等级需要提升,我们考虑增加副本。

副本数的增加需要先制定计划,然后根据计划执行

vim increase-replication-factor.json
{
    "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]}
    ]
}

四:文件存储

1:文件存储机制

1.1:Topic数据的存储机制

在这里插入图片描述

1.2:index文件和log文件详解

在这里插入图片描述
说明:日志存储参数配置

参数描述
log.segment.bytesKafka中log日志是分成一块块存储的,此配置是指log日志划分 成块的大小,默认值1G。
log.index.interval.bytes默认4kb,kafka里面每当写入了4kb大小的日志(.log),然后就往index文件里面记录一个索引。
稀疏索引。

2:文件清理策略

Kafka中默认的日志保存时间为7天,可以通过调整如下参数修改保存时间。

  • log.retention.hours,最低优先级小时,默认7天。
  • log.retention.minutes,分钟。
  • log.retention.ms,最高优先级毫秒。
  • log.retention.check.interval.ms,负责设置检查周期,默认5分钟。

那么日志一旦超过了设置的时间,怎么处理呢?

Kafka中提供的日志清理策略有delete和compact两种。

  • delete日志删除:将过期数据删除
    • log.cleanup.policy = delete 所有数据启用删除策略
    • 基于时间:默认打开。以segment中所有记录中的最大时间戳作为该文件时间戳。
    • 基于大小:默认关闭。超过设置的所有日志总大小,删除最早的segment -> log.retention.bytes,默认等于-1,表示无穷大。
  • compact日志压缩

在这里插入图片描述

五:高效读写数据

  • Kafka本身是分布式集群,可以采用分区技术,并行度高
  • 读数据采用稀疏索引,可以快速定位要消费的数据
  • 顺序写磁盘

Kafka的producer生产数据,要写入到log文件中,写的过程是一直追加到文件末端,为顺序写。

官网有数据表明,同样的磁盘,顺序写能到600M/s,而随机写只有100K/s。

这与磁盘的机械机构有关,顺序写之所以快,是因为其省去了大量磁头寻址的时间。

在这里插入图片描述

页缓存 + 零拷贝技术

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值