kafka文件存储机制
- Kafka文件存储机制
Topic是逻辑上的概念,而partition是物理上的概念,每个partition对应于一个log文件,该log文件中存储的就是Producer生产的数
据。Producer生产的数据会被不断追加到该log文件末端,为防止log文件过大导致数据定位效率低下,Kafka采取了分片和索引机制,
将每个partition分为多个segment(每个1G)。每个segment包括:“.index”文件、“.log”文件和.timeindex等文件。这些文件位于一个文件夹下,该
文件夹的命名规则为:topic名称+分区序号,例如:first-0。
1、一个topic分为多个partition,一个partition分为多个segment,一个segment包含:.log 日志文件、.index 偏移量索引文件、.timeindex 时间戳索引文件
.timeindex 时间戳索引文件,每个segment文件大小是1个G
说明: index和log文件以当前segment的第一条消息的offset命名。
- index与log文件的详解
如何在log文件中定位找到offset=600的记录呢?
1、根据目标的offset定位到segment文件,因为segment文件的命名是以第一条消息的offset命名
2、找到小于等于目标的offset(也就是绝对offset<600的index记录)的索引项
3、定位到log文件记录位置
4、向下遍历找到目标的record,然后返回
注意:
1、index为稀疏所以,大约每往log文件写入4KB数据,会往index文件写入一条索引,参数log.index.interval.bytes默认4kb
2、index文件中保存的offset为相对offset,这样能确保offset的值所占用空间不会过大,因此能将offset的值控制在固定的大小
整体流程图
kafka高效读写数据
1、Kafka 本身是分布式集群,可以采用分区技术,并行度高
2、读数据采用稀疏索引,可以快速定位要消费的数据**
3、顺序写磁盘,顺序写能到 600M/s
4、页缓存** + 零拷贝技术
kafka文件清理策略
Kafka 中默认的日志保存时间为 7 天,可以通过调整如下参数修改保存时间。
⚫ log.retention.hours,最低优先级小时,默认 7 天。
⚫ log.retention.minutes,分钟。
⚫ log.retention.ms,最高优先级毫秒。
⚫ log.retention.check.interval.ms,负责设置检查周期,默认 5 分钟。
那么日志一旦超过了设置的时间,怎么处理呢?
Kafka 中提供的日志清理策略有 delete 和 compact 两种。
1)delete 日志删除:将过期数据删除
⚫ log.cleanup.policy = delete 所有数据启用删除策略
(1)基于时间:默认打开。以 segment 中所有记录中的最大时间戳作为该文件时间戳。
(2)基于大小:默认关闭。超过设置的所有日志总大小,删除最早的 segment。
log.retention.bytes,默认等于-1,表示无穷大。
思考: 如果一个 segment 中有一部分数据过期,一部分没有过期,怎么处理?
2)compact 日志压缩
compact日志压缩:对于相同key的不同value值,只保留最后一个版本
Kafka消费方式
➢ pull (拉)模 式:
consumer采用从broker中主动拉取数据。 pull模式不足之处是,如 果Kafka没有数据,消费者可能会陷入循环中,一直返回空数据。
Kafka 默认采用这种方式。
➢ push (推)模式:
Kafka没有采用这种方式,因为由broker决定消息发送速率,很难适应所有消费者的消费速率。例如推送的速度是50m/s,
Consumer1、Consumer2就来不及处理消息。
Kafka消费者组初始化流程
1、coordinator:辅助实现消费者组的初始化和分区的分配。每个broker都有一个coordinator
消费者组要选择哪个coordinator作为他辅助呢?
coordinator节点选择 = groupid的hashcode值 % 50( __consumer_offsets的分区数量)
例如: groupid的hashcode值 = 1,1% 50 = 1,那么__consumer_offsets 主题的1号分区,在哪个broker上,就选择这个节点的coordinator
作为这个消费者组的老大。消费者组下的所有的消费者提交offset的时候就往这个分区去提交offset。
筛选出coordinator之后
1)每个consumer都发送JoinGroup请求到coordinator中,首要加入到这个group中
2)对应的coordinator会随机通过消费者id,来选出一个leade作为老大
3)对应的coordinator收集到各个consumer之后,把要消费的topic情况发送给leader 消费者
4)leader会负责制定消费方案,制定各个消费者消费哪个分区(分区分配策略 rang、roundRobin、sticky、cooperativeSticky)
5)leader把制定后的消费方案发给对应的coordinator
6)对应的coordinator就把消费方案下发给各个consumer
7)每个消费者都会和coordinator保持心跳(默认3s),一旦超时(session.timeout.ms=45s),该消费者会被移除,并触发再平衡;或者消费者处理消息的时间过长(max.poll.interval.ms5分钟),也会触发再平衡
kafka消费者分区的分配以及再平衡
1、一个consumer group中有多个consumer组成,一个 topic有多个partition组成,现在的问题是,到底由哪个consumer来消费哪个 partition的数据(请阅读kafka消费者初始化过程)。
2、Kafka有四种主流的分区分配策略: Range、RoundRobin、Sticky、CooperativeSticky。
可以通过配置参数partition.assignment.strategy,修改分区的分配策略。默认策略是Range + CooperativeSticky。Kafka可以同时使用
多个分区分配策略。
1)每个consumer都发送JoinGroup请求到coordinator中,首要加入到这个group中
2)对应的coordinator会随机通过消费者id,来选出一个leade作为老大
3)对应的coordinator收集到各个consumer之后,把要消费的topic情况发送给leader 消费者
4)leader会负责制定消费方案,制定各个消费者消费哪个分区(分区分配策略 rang、roundRobin、sticky、cooperativeSticky)
5)leader把制定后的消费方案发给对应的coordinator
6)对应的coordinator就把消费方案下发给各个consumer
7)每个消费者都会和coordinator保持心跳(默认3s),一旦超时(session.timeout.ms=45s),该消费者会被移除,并触发再平衡;或者消费者处理消息的时间过长(max.poll.interval.ms5分钟),也会触发再平衡
| 参数名称 | 描述 | |
|---|---|---|
| heartbeat.interval.ms | Kafka 消费者和 coordinator 之间的心跳时间,默认 3s。 该条目的值必须小于 session.timeout.ms,也不应该高于 session.timeout.ms 的 1/3。 | |
| session.timeout.ms | Kafka 消费者和 coordinator 之间连接超时时间,默认 45s。超 过该值,该消费者被移除,消费者组执行再平衡。session.timeout.ms 的 1/3。 | |
| max.poll.interval.ms | 消费者处理消息的最大时长,默认是 5 分钟。超过该值,该 消费者被移除,消费者组执行再平衡。 | |
| partition.assignment.strategy | 消 费 者 分 区 分 配 策 略 , 默 认 策 略 是 Range + CooperativeSticky。Kafka 可以同时使用多个分区分配策略。 可 以 选 择 的 策 略 包 括 : Range 、 RoundRobin 、 Sticky 、CooperativeSticky | |
Range 以及再平衡
- Range 分区策略原理
Range 是对每个 topic 而言的。
首先对同一个 topic 里面的分区按照序号进行排序,并
对消费者按照字母顺序进行排序。
假如现在有 7 个分区,3 个消费者,排序后的分区将会
是0,1,2,3,4,5,6;消费者排序完之后将会是C0,C1,C2。
例如,7/3 = 2 余 1 ,除不尽,那么 消费者 C0 便会多
消费 1 个分区。 8/3=2余2,除不尽,那么C0和C1分别多
消费一个。
通过 partitions数/consumer数 来决定每个消费者应该
消费几个分区。如果除不尽,那么前面几个消费者将会多
消费 1 个分区。
分区分配策略之Range
注意:如果只是针对 1 个 topic 而言,C0消费者多消费1
个分区影响不是很大。但是如果有 N 多个 topic,那么针对每
个 topic,消费者 C0都将多消费 1 个分区,topic越多,C0消
费的分区会比其他消费者明显多消费 N 个分区。
- Range 分区分配再平衡案例
(1)停止掉 0 号消费者,快速重新发送消息观看结果(45s 以内,越快越好)。
1 号消费者:消费到 3、4 号分区数据。
2 号消费者:消费到 5、6 号分区数据。
0 号消费者的任务会整体被分配到 1 号消费者或者 2 号消费者。
说明:0 号消费者挂掉后,消费者组需要按照超时时间 45s 来判断它是否退出,所以需
要等待,时间到了 45s 后,判断它真的退出就会把任务分配给其他 broker 执行。
(2)再次重新发送消息观看结果(45s 以后)。
1 号消费者:消费到 0、1、2、3 号分区数据。
2 号消费者:消费到 4、5、6 号分区数据。
说明:消费者 0 已经被踢出消费者组,所以重新按照 range 方式分配。
RoundRobin 以及再平衡
- RoundRobin分区策略原理
RoundRobin 针对集群中所有Topic而言。
RoundRobin 轮询分区策略,是把所有的 partition 和所有的
consumer 都列出来,然后按照 hashcode 进行排序,最后
通过轮询算法来分配 partition 给到各个消费者。
- RoundRobin 分区分配再平衡案例
(1)停止掉 0 号消费者,快速重新发送消息观看结果(45s 以内,越快越好)。
1 号消费者:消费到 2、5 号分区数据
2 号消费者:消费到 4、1 号分区数据
0 号消费者的任务会按照 RoundRobin 的方式,把数据轮询分成 0 、6 和 3 号分区数据,
分别由 1 号消费者或者 2 号消费者消费。
说明:0 号消费者挂掉后,消费者组需要按照超时时间 45s 来判断它是否退出,所以需
要等待,时间到了 45s 后,判断它真的退出就会把任务分配给其他 broker 执行。
(2)再次重新发送消息观看结果(45s 以后)。
1 号消费者:消费到 0、2、4、6 号分区数据
2 号消费者:消费到 1、3、5 号分区数据
说明:消费者 0 已经被踢出消费者组,所以重新按照 RoundRobin 方式分配。
##Sticky以及再平衡
- 粘性分区定义
粘性分区定义: 可以理解为分配的结果带有“粘性的”。即在执行一次新的分配之前,
考虑上一次分配的结果,尽量少的调整分配的变动,可以节省大量的开销。
粘性分区是 Kafka 从 0.11.x 版本开始引入这种分配策略,首先会尽量均衡的放置分区
到消费者上面,在出现同一消费者组内消费者出现问题的时候,会尽量保持原有分配的分
区不变化
- Sticky 分区分配再平衡案
停止掉 0 号消费者,快速重新发送消息观看结果(45s 以内,越快越好)。
1 号消费者:消费到 2、5、3 号分区数据。
2 号消费者:消费到 4、6 号分区数据。
0 号消费者的任务会按照粘性规则,尽可能均衡的随机分成 0 和 1 号分区数据,分别
由 1 号消费者或者 2 号消费者消费。
说明:0 号消费者挂掉后,消费者组需要按照超时时间 45s 来判断它是否退出,所以需
要等待,时间到了 45s 后,判断它真的退出就会把任务分配给其他 broker 执行。
(2)再次重新发送消息观看结果(45s 以后)。
1 号消费者:消费到 2、3、5 号分区数据。
2 号消费者:消费到 0、1、4、6 号分区数据。
说明:消费者 0 已经被踢出消费者组,所以重新按照粘性方式分配。
kafka—数据积压(消费者如何提高吞吐量)
1)如果是Kafka消费能力不足,则可以考虑增加Topic的分区数,并且同时提升消费组的消费者数量,消费者数 = 分区数。(两者缺一不可)
2)如果是下游的数据处理不及时:提高每批次拉取的数量。批次拉取数据过少(拉取数据/处理时间 < 生产速度),使处理的数据小于生产的数据,也会造成数据积压。
| 参数名称 | 描述 | |
|---|---|---|
| fetch.max.bytes | 默认 Default: 52428800(50 m)。消费者获取服务器端一批消息最大的字节数。如果服务器端一批次的数据大于该值(50m)仍然可以拉取回来这批数据,因此,这不是一个绝对最大值。一批次的大小受 message.max.bytes (broker config)or max.message.bytes (topic config)影响。 | |
| max.poll.records | 一次 poll 拉取数据返回消息的最大条数,默认是 500 条 |