Kafka 系列 系统架构

深入理解Kafka

Posted by lichao modified on September 10, 2020

Kafka 是分布式的消息引擎系统,也是一个分布式流处理平台(Distributed Streaming Platform)。它的主要功能是提供一套完备的消息发布与订阅解决方案。Kafka 是一个多分区、多副本且基于 Zookeeper 协调的分布式消息系统。

Topic 是承载真实数据的逻辑容器,而在主题之下还分为若干个分区。

系统架构

系统架构

  • Zookeeper 负责集群元数据的管理、控制器的选举等操作。
  • Broker(服务代理节点),可视为一个独立的 Kafka 服务节点或 Kafka 服务实例。
  • 分区
  • 多副本机制,leader 副本负责处理读写请求,follower 副本只负责与 leader 副本的消息同步
  • 消费者:消费端会记录消费位点 offset

控制器

在 Kafka 集群中会有一个或多个 broker,其中有一个 broker 会被选举为控制器(Kafka Controller),它负责管理整个集群中所有分区和副本的状态。当某个分区的 leader 副本出现故障时,由控制器负责为该分区选举新的 leader 副本。当检测到某个分区的 ISR 集合发生变化时,由控制器负责通知所有 broker 更新其元数据信息。当使用 kafka-topics.sh 脚本为某个 topic 增加分区数量时,同样还是由控制器负责分区的重新分配。

生产者

生产者架构

整个生产者客户端由两个线程协调运行,这两个线程分别是主线程和 Sender线程。在主线程中由 KafkaProducer 创建消息,然后通过可能的拦截器、序列化器和分区器的作用之后缓存到消息收集器中。Sender负责从消息累计器中获取消息并批量发送到 Kafka 中。

在消息收集器中,为每个分区都维护了一个双端队列,

发送消息主要有三种模式:

  • 发后即忘
  • 同步
  • 异步

默认分区器

在默认分区器 DefaultPartitioner 的实现中,逻辑是如果 key 不为 null,那么默认的分区器会对 key 进行哈希(采用MurmurHash2 算法),最终根据得到的哈希值来计算分区号,拥有相同 key 的消息会被写入同一个分区。如果 key 为 null, 那么消息将会以轮询的方式发往主题内的各个可用分区。

在不改变分区数量的情况下, key 与分区之间的映射可以保持不变。不过,一旦主题中增加了分区,那么就难以保证 key 与分区之间的映射关系了。

如果 key 不为空,那么计算得到的分区号会是所有分区中的任意一个。如果key为null,那么计算得到的分区号仅为可用分区中的任意一个。

生产者拦截器

  • 发送消息前: 在将消息序列化和计算分区之前
  • 发送回调逻辑前:在消息被应答之前或消息发送失败时。这个方法运行在I/O线程,需代码逻辑简单。

在拦截链中,如果某个拦截器执行失败,那么下一个拦截器会接着从上一个执行成功的拦截器继续执行。

消费者

Kafka 中的消费基于拉模式的。 消费者与消费组这种模型可以让整体的消费能力具备横向伸缩性,可以增加(或减少)消费者的个数来提高(或降低〕整体的消费能力。

位移提交

消费者在消费的过程中需要记录自己消费了多少数据,即消费位置信息。在 Kafka 中,这个位置信息有个专门的术语:位移(Offset)。

Kafka 默认的提交方式是定期提交,这个定期的周期默认为5秒。

指定位移消费

当消费者查找不到所记录的消费位移时,默认从分区末尾开始消费消息。

再平衡

Rebalance 本质上是一种协议,规定了一个 Consumer Group 下的所有 Consumer 如何达成一致,来分配订阅 Topic 的每个分区。Rebalance 的触发条件有 3 个。

  • 组成员数发生变更。比如有新的 Consumer 实例加入组或者离开组,抑或是有 Consumer 实例崩溃被“踢出”组。
  • 订阅主题数发生变更。Consumer Group 可以使用正则表达式的方式订阅主题,比如 consumer.subscribe(Pattern.compile(“t.*c”)) 就表明该 Group 订阅所有以字母 t 开头、字母 c 结尾的主题。在 Consumer Group 的运行过程中,新创建了一个满足这样条件的主题,那么该 Group 就会发生 Rebalance。
  • 订阅主题的分区数发生变更。Kafka 当前只能允许增加一个主题的分区数。当分区数增加时,就会触发订阅该主题的所有 Group 开启 Rebalance。

在 Rebalance 过程中,所有 Consumer 实例都会停止消费,等待 Rebalance 完成。

当一个 Consumer Group 订阅 多个 Topic 时,所有的 Topic 共同分配 分区。

问题

  1. 分区和 Broker 之间有什么关系: 没有关系
  2. follower 副本和 leader 副本间的同步方式: 消息会先发送给 leader 副本,然后 follower 副本才能从 leader 副本中拉取消息进行同步。leader 副本负责维护和跟踪 ISR 集合中所有 follower 副本的滞后状态。

  3. 在异步复制方式下,如何避免主从不一致的影响? 同步复制要求所有能工作的 follower 副本都复制完,这条消息才会被确认为已成功提交。
  4. kafka 为什么高效?如何支持 Producer 端将多个小消息合并?

参考文献

深度解读:Kafka 放弃 ZooKeeper,消息系统兴起二次革命