Kafka实战《原理2》

Kafka Broker

工作流程

Zookeeper存储的Kafka信息
在这里插入图片描述
Kafka Broker总体工作流程
在t这里插入图片描述

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默认300s,检查Leader负载是否平衡的间隔时间
log.segment.byteskafka中的日志是分成一块块存储的,此配置是指log日志划分成块大小,默认值1g
log,index.interval,bytes默认4kb,kafka每当写入4kb大小的日志,然后就往index文件里面记录一个索引
log.retention.hourskafka中数据保存的时间,默认7天
log. retention.minuteskafka中数据保存的时间,分钟级别,默认关闭
log. retention.mskafka中数据保存的时间,毫秒级别,默认关闭
log.retention.check.interval.ms检查数据是否超时的间隔,默认是5分钟
log.cleanup.policy默认是delete,表示数据启用删除策略;如果设置为compact,表示所有的数据启用压缩策略
节点服役和退役
节点服役

新节点添加
1,启动新节点

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

2,执行负载均衡

  • 创建一个要均衡的主题 vim topics-to-move.json
{
	"topics":[
		{"topic":first}
	],
	"version": 1
}
  • 生成一个负载均衡的计划
bin/kafka-reassign-partitions.sh --bootstrap-server ah101:9092 --topics-to-move-json-file   topics-to-move.json --broker-list "1001,1002,1003" --generate
  • 创建副本负载计划 vim increase-replication-factor.json
{
    "partitions": [
        {
            "topic": "first",
            "partition": 0,
            "replicas": [
                1001,
                1002,
                1003
            ]
        },
        {
            "topic": "first",
            "partition": 1,
            "replicas": [
                1002,
                1001,
                1003
            ]
        },
        {
            "topic": "first",
            "partition": 2,
            "replicas": [
                1001,
                1002,
                1003
            ]
        },
        {
            "topic": "first",
            "partition": 3,
            "replicas": [
                1003,
                1002,
                1001
            ]
        },
        {
            "topic": "first",
            "partition": 4,
            "replicas": [
                1001,
                1002,
                1003
            ]
        },
        {
            "topic": "first",
            "partition": 5,
            "replicas": [
                1003,
                1001,
                1002
            ]
        },
        {
            "topic": "first",
            "partition": 6,
            "replicas": [
                1002,
                1001,
                1003
            ]
        },
        {
            "topic": "first",
            "partition": 7,
            "replicas": [
                1001,
                1003,
                1002
            ]
        }
    ],
    "version": 1
}
  • 执行副本存储计划
 ./kafka-reassign-partitions.sh --bootstrap-server ah101:9092  --reassignment-json-file increase-replication-factor.json --execute

在这里插入图片描述

  • 验证副本存储计划
./kafka-reassign-partitions.sh --bootstrap-server ah101:9092   --reassignment-json-file increase-replication-factor.json --verify

在这里插入图片描述

节点退出
  • 创建一个要均衡的主题 vim topics-to-move.json
{
	"topics":[
		{"topic":first}
	],
	"version": 1
}
  • 生成一个负载均衡的计划
bin/kafka-reassign-partitions.sh --bootstrap-server ah101:9092 --topics-to-move-json-file   topics-to-move.json --broker-list "1001,1002" --generate
  • 创建副本负载计划 vim remove-replication-factor.json
  • 执行副本存储计划
 ./kafka-reassign-partitions.sh --bootstrap-server ah101:9092  --reassignment-json-file remove-replication-factor.json --execute
    • 验证副本存储计划
./kafka-reassign-partitions.sh --bootstrap-server ah101:9092   --reassignment-json-file remove-replication-factor.json  --verify

Kafka副本

副本的基本信息

  1. 作用 :提高数据的可靠性
  2. 默认副本1个,生产环境一般配置为2个,保证数据的可靠性,太多副本会增加磁盘存储空间,增加网络上的数据传输,降低效率
  3. 副本分为 Leader和Follower 。kafka生产者只会将数据发送给leader,然后follower会从leader进行同步数据
  4. kafka分区所有的副本称为AR

AR=ISR+OSR
ISR: 表示和Leader保持同步的Follower的集合。如果Follower长时间未向Leader发送通信请求或者同步数据,则该数据会被踢出ISR列表,该时间阈值由replica.lag.time.max,ms参数设定,默认30s。Leader发生故障的时候,就会从ISR中选举新的Leader。
OSR:表示Follower与Leader副本同步的时候,延迟过多的副本。

Leader选举流程

Kafka集群中有一个broker 的Controller会被选举为Controller Leader,负责管理集群broker的上下线,所有的topic的分区副本分配和Leader选举等工作。
在这里插入图片描述

Follower故障处理细节

LEO(log end offset):每个副本的最后offset,LEO其实就是最新的offset+1
HW(high watermark): 所有副本中最小的LEO。

1)Follower故障

  • Follower发生故障后会被踢出ISR
  • 这个期间 Leader和Follower继续接受数据
  • 待该Follower恢复后,Follower会读取本地磁盘记录的上次HW,并将log文件高于HW部分截取掉,从HW开始向Leader进行同步
  • 等该Follwer的LEO大于等于该partitionde HW,则将Follower重新加入ISR

2)Leader故障

  • Leader发生故障的时候,会从ISR中选出一个新的Leader
  • 为保证多个副本之间数据一致性,其余的Follower会先将各自的log文件高于HW的部分裁掉,然后从新的Leader同步
    注意:这只能保证副本之间的数据一致性,并不能保证数据不丢失或者不重复

分区副本分配
如果一个topic 创建16个分区 3个副本
那么AR规律
在这里插入图片描述
特点:
1)第一列为每个broker id 的排序 比如0,1,2,3,比如 1001 1002,1003
2)根据broker的数量作为一组进行副本分配
比如如果是4个broker组成的集群 那么leader 是0,1,2,3 ,AR 和ISR的列表的第一个也必定的是0,1,2,3
3) 一把第一个是间隔为0 第2个间隔为1 ,第三个间隔为2,这个间隔数和副本设置的数量有关系的
比如设置副本数为3 那么最后的间隔最大数为2 (3-1)

手动调整分区副本存储

生产环境中,每台服务器的配置和性能不一致,但是kafka只会根据自己的代码规则创建对应的副本,就会导致个别服务器存储压力比较大。所以需要手动调整分区副本的存储。

需求: 创建一个新的topic (testTopic) ,4个分区,2个副本,。将该topic的所有副本都存储到broker0和broker1

步骤
1)创建topic

bin/kafka-topics.sh --bootstrap-server  ah101:9092 --create --partitions 4 --replication-factor 2 -topic testTopic
  1. 创建副本存储计划 (所有的副本存储在broker0 ,broker1)vim assign.json
{
"version":1,
"partitions":[{"topic":"testTopic","partition":0,"replicas":[0,1]},
{"topic":"testTopic","partition":1,"replicas":[0,1]},
{"topic":"testTopic","partition":2,"replicas":[1,0]},
{"topic":"testTopic","partition":3,"replicas":[1,0]}]
}

3) 执行副本存储计划

bin/kafka-reassign-partitions.sh --bootstrap-server ah101:9092 --reassignment-json-file assign.json --execute

4) 验证副本存储计划执行的情况

bin/kafka-reassign-partitions.sh --bootstrap-server ah101:9092 --reassignment-json-file assign.json --verify

5)查看副本存储情况

bin/kafka-topics.sh --bootstrap-server   ah101:9092 --describe --topic testTopic

Leader Partition 负载均衡

正常情况下,Kafka本身会自动把Leader Partition均匀的分散在各个机器上,来保证每台机器的读写和吞吐量都是均匀的。但是如果某些broker宕机,会导致leader partition过于集中在其他少部分的几台broker上,这会导致这几台的broker读写请求压力过高,其他宕机的broker重启只后都是follower,读写请求很低,造成集群负载不均衡

参数名称描述
auto.leader.rebalance.enable默认true,自动Leader partition平衡。生产环境中国,Leader重选举代价比较大,可能会带来性能影响,建议设置false关闭
leader.imbalance.per,broker,percentage默认10%,每个broker允许的不平衡的leader的比率。如果每个broker超过这个值,控制器会触发重平衡
leader.imbalance.check.interval.time默认值100,检查Leader负载是否平衡的间隔时间
文件存储

1)topic数据存储机制
topic是逻辑上的概念,而partition是物理上的概念。每个partition对应一个log文件,该log文件存储的就是Producer生产的数据。Producer生产的数据会被不断的追加到该log文件的末端。为防止log文件过大导致数据定位效率低下,kafka采取分片和索引机制,将每个partition分为多个segement。每个segment包括 “.index”,“.log”,".timeindex"等文件。该文件命名规则 topic名称+分区序号,列如first-0。

说明: index和log文件以当前segment第一条消息的offset命名

通过工具可以查看index和log文件信息

kafka-run-class.sh  kafka.tools.DumpLogSegments --file  ./000000000000000000000000.index

kafka-run-class.sh  kafka.tools.DumpLogSegments --file  ./000000000000000000000000.log

2)如何在log文件中定位到offset=100的record?

  • 根据目标offset定位segment文件
  • 找到小于等于目标offset的最大offset对应的索引项
  • 定位log文件
  • 向下遍历找到目标record记录

3) 文件清理策略
kafka的日志默认保存时间7天,可以通过调整参数修改保存时间。
log.retention.hours 最低优先级小时 ,默认7天
log.retention.check.interval.ms 负责设置检查周期,默认5分钟

4)日志一旦超过设置的时间,怎么处理?
kafka提供的日志清理策略有两种
delete和compact两种

  • log.clean.policy=delete 所有的数据启用删除策略
    (1)基于时间:默认打开,以segment中所有记录中最大的时间戳作为该文件的时间戳
    (2)基于大小:默认关闭。超过设置所有日志总大小,删除最早的segment。 log.retention.bytes 默认-1,表示无穷大
  • log.clean.policy=compact
    对于相同key 不同value值,只保留最后一个版本。
    压缩后offset数据不是连续的。
    这种策略只适合特殊场景,比如消息的key为用户id,value是用户资料,通过这中压缩策略,整个消息就保存所有用户的最新资料。

5)高效读写数据

  • kafka本身是分布式集群,采用分区技术,并行度高
  • 读数据采取稀疏索引,可以快速的定位要消费数据的位置
  • 顺序写磁盘(省去大量磁头寻址时间)
  • 页缓存+0拷贝技术
    PageCahe:kafka重度依赖底层操作系统提供的pagecahce功能。当上层有写操作的时候,操作系统只是将数据写入pagecache,当读操作发生的时候,先从pagecache中读取,如果找不到,在从磁盘中读取

Kafka 消费者

Kafka的消费方式

pull模式:
consumer采用从broker主动拉取数据

push模式:
broker推送数据到consumer

kafka采用的pull方式,因为由broker决定消息发送速率,很难适应所有的消费者的消费速率。
pull模式不足之处:如果kafka没有数据,消费者可能会陷入死循环中,一直返回空数据。

消费的工作流程

在这里插入图片描述
消费者组:由多个消费者组成。形成一个消费者组的条件,所有的消费者的groupid相同

  • 消费者组内每个消费者负责消费不同的分区数据,一个分区只能由一个组内消费者消费。
  • 消费者组之间互不影响。所有的消费者都属于某个消费者组。即消费者组是逻辑上一个订阅者
  • 如果消费者组中添加更多消费者,超过主题分区的数量,则有一部分消费者会闲置。不会接受任何消息

消费者组的初始化流程:

coordinator:辅助实现消费者组初始化和分区分配。
coordinator节点选择=groupId的hashcode值%50(__consumer_offsets的分区数量)

  • 每个consumer都发送给JoinGroup
  • 选出一个consumer作为leader
  • 把消费的topic情况发送给leader消费者
  • leader会负责指定消费方案
  • 把消费方案发给coodinator
  • Coodinator把消费方案发给各个consumer,
  • 每个消费者都会和coordinator保持心跳(3s),一旦超时(session.time.out=45s),该消费者会被移除,并触发再平衡,或者消费者处理消息时间过长(max.poll.interval.ms=5分钟),也会触发再平衡
消费者重要参数
参数名称描述
bootstrap.servers向kafka集群建立初始连接用到的host/port列表
key.deserializer value.deserializer指定接受消息的key和value的反序列化类型,一定要写全类名
group.id标记消费者所属的消费者组
enable.auto.commit默认为true,消费者会自动周期性的向服务器提交偏移量
auto.commit.interval.ms如果设置了 enable.auto.commit=true,则该值定义了消费者偏移量向kafka提交的频率 默认5s
auto.offset.reset当kafka中没有初始偏移量或者当前偏移量再服务器中不存在,该如何处理?earlist:自动重置偏移量到最早的偏移量;latest:默认,自动重置偏移量为最新的偏移量。none:如果消费者组原来偏移量不存在,则向消费者抛异常,anything:向消费者抛异常
offsets.topic.num.patitions_consumer_offsets的分区数,默认50
hearbeat.inteval.mskafka消费者与coordinator之间的心跳时间,默认3s,该值必须夏鸥session.out.time
session.time.outkafka消费者与coordinator之间的心跳时间,默认45s
max.pooll.interval.ms消费者处理消息的最大时长,默认5min
fetch.min.bytes默认一字节,消费者获取服务端一批消息最小字节
featch.max,wait,ms默认500ms,如果没有从服务器端获取到一批数据最小字节,时间到了,仍然返回数据
featch.max.bytes默认 50m,消费者获取服务器端一批消息最大的字节数。
max.poll.records一次poll拉取数据返回的消息的最大条数,默认500s
分区平衡以及再平衡

一个消费者组有多个消费者,一个topic有多个分区,那么问题是到底由哪个消费者来消费哪个分区的数据

kafka有四种主流分区分配策略: Range,RoundRobin,Sticky,CooperativeSticky
可以通过参数partition.assignment.strategy修改分区策略。默认策略是Range+CooperativeSticky

Range
Range是对每一个topic而言的

首先对同一个topic里面的分区按照序号进行排序,并对消费者按照字母顺序排序。
假如有7个分区,3个消费者,排序后将会是0,1,2,3,4,5,6。消费者是c0,c1,c2。
通过partition/consumers来决定每个消费者消费几个分区,如果除不尽,那么前面的几个消费者将会多消费1个分区。

例如: 7/3=2余1 那么 c0将会多消费一个消费者

在这里插入图片描述
注意
如果只是针对一个topic而言,c0消费者多消费一个分区影响不大,但是如果有多个topic,那么针对每个topic消费者c0都会将多消费一个分区,topic越多,c0消费的分区就会越多,容易产生数据倾斜

RoundRobin
RoundRobin针对集群中所有的topic而言

RoundRobin轮询分区策略,是把所有的partition和所有的consumer都列出来,然后按照hashcode进行排序,最后通过轮询算法来分发patition给到各个消费者。
在这里插入图片描述
Sticky
粘性分区: 在执行一次新的分配前,考虑上次分配的结果,尽量减少分配调动,可以节省大量的开销。
kafka0.11.x引入这种分配策略。首先会尽量均衡的放置分区掉消费上面,在出现统一消费组内消费者出现问题的时候,会尽量保持原有的分配的分区不变化
在这里插入图片描述

Offset位移

offset的默认维护位置
从0.9开始 ,consumer默认将offset保存在kafka一个内置topic中,该topic为_consumer_offsets。
0.9以前,consumer默认将offset保存在zookeeper。

_consumer_offsets 主题采用key value的形式存储数据。key是groupid+topic+分区号,value是当前offset的值。每隔一段时间内,kafka内部会对这个topic进行compact,也就是每个groupid+topic+分区号就保留最新的数据。

配置文件 config/consumer.properties,添加配置exclude.internal.topics=false,默认true,表示不能消费该系统主题,为了查看该系统主题数据,可以将参数修改为false

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大道至简@EveryDay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值