ObsidianRepository/Kafka/4.Kafka高级原理篇.md

77 lines
6.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

### Kafka的文件存储原理
>kafka 是一个分布式的缓存队列,文件存储时 将topic流数据进行分区存储存放到多个broker节点这样起到负载均衡、分布式并行处理的作用因此具体存储的形式是 以`topic-partition` 形式命名的。
- 随着单文件的大小增大,检索效率降低,因此 参数 `log.segment.bytes` 设置 单文件最大为1G这意味着topic的一个分区也将分成多个segment每个segment最大为1G文件检索时效率更高。文件追加写入的策略是buffer满足4k将数据写入*.log并向*.index, *.timeindex写入索引
- kafka的写是追加写这会跳过文件的检索步骤kafka官网指出追加写入速率为`600MB/S` ,随机写速率为 `100KB/S` ,使得使用机械硬盘的性能不逊于固态硬盘。
- kafka的读当读取对应topic的相应分区时先通过segment来选择具体的读取文件然后通过 offset向*.index 查询物理偏移量,再去*.log读取数据。此外kafka实现零拷贝使得数据无需在用户缓存空间进行传递拷贝仅需要复制到内核缓冲区然后发送到网卡省去两次拷贝的开销
### 文件的清理
>kafka时一个分布式的缓存队列它的数据不像HDFS那样长期存储kafka默认会将存在7天的过期数据进行删除。
- `log.cleanup.policy`, 可选为 delete、compact默认是delete
- `log.retention.hours` 默认 167 7天时间过期
- `log.retention.bytes` 默认 -1 ,分区内的数据最大值,默认没有限制
- `log.segment.bytes`,默认1073741824 分区内的 `segment` 的最大值默认为1G
- `log.cleaner.interval.ms` ,默认为 30000 5 分钟,这个参数适用于所有日志清理策略,包括删除(`log.cleanup.policy=delete`)和压缩(`log.cleanup.policy=compact`)。
如果`log.cleanup.policy = compact` ,这不会删除过期数据,而是将重复建的记录进行合并,仅仅保留最新的记录,旧的记录将被清除。因此每个键在压缩后的日志中是唯一的最新值。需要配合使用下列参数
- `log.cleaner.enable=true` 启用日志压缩功能。
- `log.cleaner.min.cleanable.ratio` 定义清理的最低比例。即当未清理的数据量超过指定比例`(默认 0.5)`时Kafka 会触发压缩。
- `log.cleaner.backoff.ms`默认15000 当 Kafka 完成一次日志压缩后,等待指定时间后才会执行下一次压缩。
### kafka的监控
> [kafka-console-ui]([[https://drive.google.com/file/d/1-38QwSMsq3MvrpTofa8YeNLpp4KyE407/view?usp=drive_link]]) 下载
```bash
unzip kafka-console-ui.zip -d /usr/local/
cd /usr/local/kafka-console-ui bin/start.sh
bin/start.sh
```
访问localhost:7766点击最右边的运维添加集群信息
### Kafka集群动态添加节点
![](./assert/5.png)
### Kafka的选举机制
>`controller` 选举
各个`broker`节点会向`zookeper`的 注册`/controller`节点 ,如果注册了这个节点,这个`broker`就是 `controller`节点
当 controller broker 宕机时Zookeeper 会检测到 `/controller` 节点的会话过期,并自动删除该节点。
其他的 broker 都会监听该节点的变化,一旦监听到`/controller`节点被删除brokers 会竞相尝试创建新的 `/controller` 节点
![controller节点](./assert/6.png)
>`partition leader` 选举
`topic`存在多个分区,而这每个分区又存在副本,这些副本之间有主从关系,为主从分区。主分区负责处理读写请求,从分区从 Leader 副本同步数据,确保数据冗余和容错。
集群的`/controller`的`broker`节点有`controller`组件,他会进行主从分区的选取,形成一个`ISR`(动态副本集)
- 问题:如果`topic`的主分区所在节点宕机,需要从`ISR`中重新选举主分区这个选举是顺序性的最大程度保证和宕机的leader的最新数据是同步一致的。`controller`会协调这个选举过程一旦检测到leader没有heartbeat认为其宕机立即选取新leader并将zookeeper和broker的元数据进行更新保证`topic`分区可用
- **`unclean.leader.election.enable`**:当设置为 `true` 时,允许非 ISR 副本成为 Leader当设置为 `false` 时,仅允许 ISR 中的副本成为 Leader默认值为 `false`,即不启用非 ISR 选举)
### Kafka的数据同步
>上述说到了topic的主分区宕机之后的leader选举此时还需要进行分区数据的同步选举出新的leader分区将自己的数据完整地同步到follower分区
- 情况一就是当从分区正在同步主分区的数据但是此时leader宕机从分区的数据对于宕机leader的数据来说是不完整的那么只能从`ISR`中选择第一个,数据最新的从分区为新的主分区,然后进行数据的同步
- 情况二:就是宕机的是从分区`broker`节点,这不会影响集群的运行,会将从分区从`ISR`中去除,如果从分区的`broker`恢复过来,从分区会向主分区同步,并重新加入`ISR`
### Kafka的数据均衡
>Kafka的一些`broker`因为`leader`的频繁选举导致负载较重,此时可以进行分区再平衡,**Leader 分区转移为 Follower 分区**,从而减少该节点的压力。
我们可以选择关闭Kafka的leader平衡管理改为自动管理。
`auto.leader.rebalance.enable`,默认为true集群自动管理leader的切换选举
`leader.imbalance.check.interval.seconds`默认300集群检查是否选举切换leader的间隔时间
现在我们关闭集群的leader平衡管理使用手动管理
- 直接指定`topic`的leader
```bash
kafka-leader-election.sh --bootstrap-server nn1:9092 --topic topic_a --partition 1 --election-type preferred
```
- 也可以手动生成均衡计划
```bash
# 首先创建一个topic.json 输入如下内容 填写需要均衡的分区
{"topics":[{"topic":"topic_a"}],"version":1}
# 使用这个均衡优化命令生成优化计划
kafka-reassign-partitions.sh --bootstrap-server nn1:9092 --broker-list 0,1,2,3,4 --topics-to-move-json-file topic.json --generate
# 将上述命令生成的优化计划 编辑为 reassignment.json
kafka-reassign-partitions.sh --bootstrap-server nn1:9092 --execute --reassignment-json-file reassignment.json
# 验证是否重新分配成功
kafka-reassign-partitions.sh --bootstrap-server nn1:9092 --reassignment-json-file reassignment.json --verify
```