设计原理
# 核心总控制器Controller
- Kafka集群中会有一个或者多个broker,其中有一个broker会被选举为控制器(Kafka Controller),它负责管理整个集群中所有分区和副本的状态。
- 当某个分区的leader副本出现故障时,由控制器负责为该分区选举新的leader副本
- 当检测到某个分区的ISR集合发生变化时,由控制器负责通知所有broker更新其元数据信息。
- 当使用kafka-topics.sh脚本为某个topic增加分区数量时,同样还是由控制器负责让新分区被其他节点感知到。
# Controller选举机制
- 集群中每个broker都会尝试在zookeeper上创建一个 /controller 临时节点,zookeeper会保证有且仅有一个broker能创建成功。
- 当这个controller角色的broker宕机了,此时zookeeper临时节点会消失,集群里其他broker会一直监听这个临时节点,发现临时节点消失了,就竞争再次创建临时节点。
# Controller职责
- 监听broker相关的变化。
- 监听topic相关的变化
- 从Zookeeper中读取获取当前所有与topic、partition以及broker有关的信息并进行相应的管理
- 更新集群的元数据信息,同步到其他普通的broker节点中
# Partition副本选举Leader机制
- controller感知到分区leader所在的broker挂了,controller会从ISR列表里挑第一个broker作为leader(第一个broker最先放进ISR列表,可能是同步数据最多的副本)
# 副本进入ISR列表条件
- 副本节点不能产生分区,必须能与zookeeper保持会话以及跟leader副本网络连通
- 副本能复制leader上的所有写操作,并且不能落后太多(与leader副本同步滞后的副本,是由 replica.lag.time.max.ms 配置决定的,超过这个时间都没有跟leader同步过的一次的副本会被移出ISR列表)
# 消费者消费消息的offset记录机制
每个consumer会定期将自己消费分区的offset提交给kafka内部topic:__consumer_offsets,提交过去的时候,key是consumerGroupId+topic+分区号,value就是当前offset的值。
# 消费者Rebalance机制
# 定义
- rebalance就是说如果消费组里的消费者数量有变化或消费的分区数有变化,kafka会重新分配消费者消费分区的关系。
# 触发情况
- 消费组里的consumer增加或减少了
- 动态给topic增加了分区
- 消费组订阅了更多的topic
# 产生问题
rebalance过程中,消费者无法从kafka消费消息,对kafka的TPS有影响
# 注意
rebalance只针对subscribe这种不指定分区消费的情况,如果通过assign这种消费方式指定了分区,kafka不会进行rebanlance。
但是assign指定分区,他是效率不高的。
# 消费者Rebalance分区分配策略
# range策略
按照分区序号排序
# round-robin策略
轮询分配
# sticky策略
初始时分配策略与round-robin类似,但是在rebalance的时候,需要保证如下两个原则:1)分区的分配要尽可能均匀 。2)分区的分配尽可能与上次分配的保持相同。
# Rebalance过程
- 选择组协调器
- 加入消费组JOIN GROUP
- SYNC GROUP
# producer发布消息机制剖析
# 写入方式
采用 push 模式将消息发布到 broker,每条消息都被 append 到 patition 中,属于顺序写磁盘(顺序写磁盘效率比随机写内存要高,保障 kafka 吞吐率)
# 消息路由
producer 发送消息到 broker 时,会根据分区算法选择将其存储到哪一个 partition。
其路由机制为:
- 指定了 patition,则直接使用;
- 未指定 patition 但指定 key,通过对 key 的 value 进行hash 选出一个 patition
- patition 和 key 都未指定,使用轮询选出一个 patition。
# 日志分段存储
- 一个分区的消息数据对应存储在一个文件夹下,以topic名称+分区号命名,消息在分区内是分段(segment)存储,每个段的消息都存储在不一样的log文件里,这种特性方便old segment file快速被删除,kafka规定了一个段位的 log 文件最大为 1G,做这个限制目的是为了方便把 log 文件加载到内存去操作
- 一个日志段文件满了,就自动开一个新的日志段文件来写入,避免单个文件过大,影响文件的读写性能,这个过程叫做 log rolling,正在被写入的那个日志段文件,叫做 active log segment。
# kafka zookeeper 节点 (opens new window)
编辑 (opens new window)
上次更新: 2023/01/24, 15:21:15