背景
Kafka 支持配置多块数据盘来提高吞吐,在线上运行过程中,我们发现,在磁盘更换后,新创建的topic分区都分不在了新磁盘上,很容易出现I/O热点。因此探究了下 Kafka 的选盘策略。
# Kafka的多块数据盘配置
log.dirs=/data01/kafka,/data02/kafka,/data03/kafka
磁盘维修的流程
- 修改Kafka配置文件,将故障盘对应的数据目录删除
- 重启Kafka进程
- 更换/维修故障盘
- 修改Kafka配置文件,加回修好的盘对应的数据目录
结论
选盘策略体现在 LogManager.getOrCreateLog 方法中,Kafka 在创建 topic 选择磁盘时,会选择分区数最少的磁盘,后续不会再移动分区。也不会根据大小或I/ O速率进行平衡。
源码追踪
得到了上述结论后,我们在串一下创建topic的整个流程。
- KafkaApis 收到创建topic的请求
handleCreateTopicsRequest 里,调用zk创建topic对应的Node
KafkaController 中,监听到 zookeeper 中 topic 对应的 node 发生变化
ControllerEventManager 收到所有zk数据变化的事件,放入queue
KafkaController 中统一处理这些事件
topic 创建会调用 onNewPartitionCreation 方法
执行创建topic的请求,最终会调用到「分区状态机」和「副本状态机」里的状态修改
分区状态机将状态变更的元数据信息,发送给每一个 broker
通知broker时,会发起 LeaderAndIsrRequest 请求,LeaderAndIsrRequest 请求的处理,又可以回到上面的 KafkaApis 的代码里。
LeaderAndIsrRequest 请求的处理,最终会调用到 LogManager.getOrCreateLog 方法,对新创建的topic创建一个log文件,期间会选择磁盘。
总结
基本上,到这里Kafka 的选盘策略流程就串起来了,涉及到了几个核心的组件和流程:
- 分区状态机、副本状态机
- LeaderAndIsrRequest 、UpdateMetadataRequests、StopReplicaRequests 请求的处理过程
这部分代码量比较多,先埋个坑,下次在分享。