kafka源码分析—Controller

概述

本文描述了kafka的controller的实现原理,并对其源代码的实现进行了讲解。

controller运行原理

在Kafka集群中,controller多个broker中的一个(也只有一个controller),它除了实现正常的broker的功能外,还负责选取分区(partition)的leader。
第一个启动的broker会成为一个controller,它会在Zookeeper上创建一个临时节点(ephemeral):/controller。其他后启动的broker也尝试去创建这样一个临时节点,但会报错,此时这些broker会在该zookeeper的/controller节点上创建一个监控(Watch),这样当该节点状态发生变化(比如:被删除)时,这些broker就会得到通知。此时,这些broker就可以在得到通知时,继续创建该节点。保证该集群一直都有一个controller节点。

当controller所在的broker节点宕机或断开和Zookeeper的连接,它在Zookeeper上创建的临时节点就会被自动删除。其他在该节点上都安装了监控的broker节点都会得到通知,此时,这些broker都会尝试去创建这样一个临时的/controller节点,但它们当中只有一个broker(最先创建的那个)能够创建成功,其他的broker会报错:node already exists,接收到该错误的broker节点会再次在该临时节点上安装一个watch来监控该节点状态的变化。每次当一个broker被选举时,将会赋予一个更大的数字(通过zookeeper的条件递增实现),这样其他节点就知道controller目前的数字。

当一个broker宕机而不在当前Kafka集群中时,controller将会得到通知(通过监控zookeeper的路径实现),若有些topic的主分区恰好在该broker上,此时controller将重新选择这些主分区。controller将会检查所有没有leader的分区,并决定新的leader是谁(简单的方法是:选择该分区的下一个副本分区),并给所有的broker发送请求。

每个分区的新leader指导,它将接收来自客户端的生产者和消费者的请求。同时follower也指导,应该从这个新的leader开始复制消息。
当一个新的broker节点加入集群时,controller将会检查,在该broker上是否存在分区副本。若存在,controller通知新的和存在的broker这个变化,该broker开始从leader处复制消息。

总的来说,Kafka会通过在Zookeeper上创建临时节点的方式来选举一个controller,但Kafka集群中有节点加入或退出时,该controller将会得到通知。Controller还负责在多个分区中选择主分区,负责当有节点加入集群时进行副本的复制。Controller通过递增数字(epoch number)来防止脑裂(split brain)的问题(脑裂是指:多个节点都选自己为Controller)。

实现分析

Controller的实现原理

Controller是通过事件处理机制来实现的。把broker的节点的变化,分区的变化,都封装成事件,发生事件时把事件放入到事件队列中,此时阻塞在事件队列的处理者即可开始处理这些事件。
这些事件类,都必须实现同一个接口。

启动

类KafkaServer中的startup()函数中启动Controller,代码如下:

def startup() {
    ...
    /* start kafka controller */
    kafkaController = new KafkaController(config, zkClient, time, metrics, brokerInfo, tokenManager, threadNamePrefix)
    // 启动kafka server的控制模块
    kafkaController.startup()
    ...
}

初始化工作

Kafka服务节点启动时Controller模块就会启动。但当Controller启动时,不会假设自己是controller,而是先注册回话超时的监听者(listener),然后开始controller的leader选举过程。

启动时,会把Startup事件控制实体,放入到事件队列中。在eventManager线程启动时,会在队列取出ControllerEvent类型的事件。并进行处理,此时取出的当然是刚刚放入的Startup事件,所以,开始执行Startup类的process函数。代码实现如下:

def startup() = {
    ... ...
    eventManager.put(Startup)
    eventManager.start()
  }
  • Startup事件控制实体
    在Controller模块启动时,该事件就被放入到事件队列中,所以,最开始处理该事件。执行的处理函数是下面定义的process()。代码的实现如下:
case object Startup extends ControllerEvent {
    def state = ControllerState.ControllerChange
    override def process(): Unit = {
      zkClient.registerZNodeChangeHandlerAndCheckExistence(controllerChangeHandler)
      elect()
    }

  }

Startup事件处理

private def elect(): Unit = {
    val timestamp = time.milliseconds
    activeControllerId = zkClient.getControllerId.getOrElse(-1)

    // 这里要判断一下controller是否已经选出来了,若是选出来了,就不需要再继续选举
    if (activeControllerId != -1) {
      debug(s"Broker $activeControllerId has been elected as the controller, so stopping the election process.")
      return
    }

    // 若controller还没有选出来,则进行选举
    try {
        // 若成功的选举成controller,继续进行后面的注册,否则抛出异常
      zkClient.checkedEphemeralCreate(ControllerZNode.path, ControllerZNode.encode(config.brokerId, timestamp))
      info(s"${config.brokerId} successfully elected as the controller")
      // 自己被选举成controller,进入onControllerFailover函数
      activeControllerId = config.brokerId
      onControllerFailover()
    } catch {
      case _: NodeExistsException =>
        // If someone else has written the path, then
        activeControllerId = zkClient.getControllerId.getOrElse(-1)

        ... ...
    }
  }

被选举成controller之后

当broker被选举成为controller后,继续执行后面的代码,此时进入onControllerFailover()函数。
该函数主要完成以下几件事:
* 注册controller epoch(controller id)变化的监听器
* 增加controller的id
* 初始化controller的context,该context保存了每个topic信息,和所有分区的leader信息。
* 开启controller的channel管理模块
* 开启副本状态机
* 开启分区状态机
* 当该发生任何的异常,会从新选择目前的controller的,这样让其他的broker节点也有可能成为controller。
* 注册zk上的broker状态变化,topic状态变化,topic删除,分区的zk目录等状态变化时的处理函数。

总结

本文总结了controller的运行原理,通过本文可以理解,controller的功能和选举过程。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kafka 0.9.0 是一个分布式流处理平台,用于高效地处理和传输大规模数据流。它采用了发布-订阅的消息队列模型,能够以高吞吐量、低延迟的方式处理数据。 在分析上,我可以给你一些大致的指导,但是详细的分析可能需要具体的问题或主题。以下是一些主要的模块和功能,你可以根据需要选择感兴趣的部分进行深入研究: 1. Broker:Kafka 的核心组件,负责接收、存储和转发消息。可以了解 Broker 的启动过程、消息存储机制和网络通信模块等。 2. Producer:负责向 Kafka 集群发送消息。可以了解 Producer 的消息发送流程、消息分区机制和消息确认机制等。 3. Consumer:负责从 Kafka 集群消费消息。可以了解 Consumer 的消息订阅机制、消费者组管理和消息位移管理等。 4. Topic 和 Partition:Kafka 将消息分为多个 Topic,并将每个 Topic 划分为多个 Partition。可以了解 Topic 和 Partition 的创建、分配和管理等。 5. Replica 和 Leader-Follower:Kafka 使用副本机制来保证数据的可靠性。可以了解 Replica 的同步和选举机制,以及 Leader-Follower 模型的实现细节。 6. ZooKeeper:Kafka 使用 ZooKeeper 来进行集群的协调和管理。可以了解 Kafka 对 ZooKeeper 的依赖和使用方式。 以上只是一些主要的模块和功能,Kafka码非常庞大和复杂,涉及到很多细节和算法。如果你有具体的问题或感兴趣的主题,我可以提供更详细的指导。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值