1.概述

  平时在使用Kafka的时候,可能关注的更多的是Kafka系统层面的。今天来给大家剖析一下Kafka的控制器,了解一下Kafka控制器的选举流程。

2.内容

  Kafka控制器,其实就是一个Kafka系统的Broker。它除了具有一般Broker的功能之外,还具有选举主题分区Leader节点的功能。在启动Kafka系统时,其中一个Broker会被选举为控制器,负责管理主题分区和副本状态,还会执行分区重新分配的管理任务。

  如果在Kafka系统运行过程中,当前的控制器出现故障导致不可用,那么Kafka系统会从其他正常运行的Broker中重新选举出新的控制器。

2.1 控制器启动顺序

  在Kafka集群中,每个Broker在启动时会实例化一个KafkaController类。该类会执行一系列业务逻辑,选举出主题分区的Leader节点,步骤如下:

  • 第一个启动的代理节点,会在Zookeeper系统里面创建一个临时节点/controller,并写入该节点的注册信息,使该节点成为控制器;
  • 其他的代理节点陆续启动时,也会尝试在Zookeeper系统中创建/controller节点,但是由于/controller节点已经存在,所以会抛出“创建/controller节点失败异常”的信息。创建失败的代理节点会根据返回的结果,判断出在Kafka集群中已经有一个控制器被成功创建了,所以放弃创建/controller节点,这样就确保了Kafka集群控制器的唯一性;
  • 其他的代理节点,会在控制器上注册相应的监听器,各个监听器负责监听各自代理节点的状态变化。当监听到节点状态发生变化时,会触发相应的监听函数进行处理。

2.2 如何查看控制器优先级 ?

  控制器创建的优先级是按照Kafka系统代理节点成功启动的顺序来创建的。用户可以通过改变Kafka系统代理节点的启动顺序,来查看控制器的创建优先级。之后,可以在Zookeeper系统中查看/controller临时节点的内容,例如:

  1. # 进入Zookeeper集群
  2. [hadoop@dn1 bin]$ zkCli.sh -server dn1:
  3.  
  4. # 执行查看命令
  5. [zk: dn1:(CONNECTED) ] get /controller

  成功执行命令后,可以看到代理节点0(即dn1节点)上成功创建了控制器,如下图所示:

当前启动顺序为:dn1、dn2、dn3,修改启动顺序为:dn3、dn1、dn2。再次查看Zookeeper系统中执行“get /controller”命令,输出结果如下图所示:

2.3 切换控制器所属的代理节点

  当控制器被关闭或者与Zookeeper系统断开连接时,Zookeeper系统上的临时节点就会被清除。Kafka集群中的监听器会接收到变更通知,各个代理节点会尝试到Zookeeper系统中创建一个控制器的临时节点。第一个成功在Zookeeper系统中创建的代理节点,将会成为新的控制器。每个新选举出来的控制器,会在Zookeeper系统中获取一个递增的controller_epoch值。

3.主题分区Leader节点的选举过程

  选举控制器的核心思路是:各个代理节点公平竞争抢占Zookeeper系统中创建/controller临时节点,最先创建成功的代理节点会成为控制器,并拥有选举主题分区Leader节点的功能。选举流程如下图所示:

  当Kafka系统实例化KafkaController类时,主题分区Leader节点的选举流程便会开始。其中涉及的核心类包含KafkaController、ZookeeperLeaderElector、LeaderChangeListener、SessionExpirationListener。

  • KafkaController:在实例化ZookeeperLeaderElector类时,分别设置了两个关键的回调函数,即onControllerFailover和onControllerResignation;
  • ZookeeperLeaderElector:实现主题分区的Leader节点选举功能,但是它并不会处理“代理节点与Zookeeper系统之间出现的会话超时”这种情况,它主要负责创建元数据存储路径、实例化变更监听器等,并通过订阅数据变更监听器来实时监听数据的变化,进而开始执行选举Leader的逻辑;
  • LeaderChangeListener:如果节点数据发送变化,则Kafka系统中的其他代理节点可能已经成为Leader,接着Kafka控制器会调用onResigningAsLeader函数。当Kafka代理节点宕机或者被人为误删除时,则处于该节点上的Leader会被重新选举,通过调用onResigningAsLeader函数重新选择其他正常运行的代理节点成为新的Leader;
  • SessionExpirationListener:当Kafka系统的代理节点和Zookeeper系统建立连接后,SessionExpirationListener中的handleNewSession函数会被调用,对于Zookeeper系统中会话过期的连接,会先进行一次判断。

4.注册分区和副本状态机

  Kafka系统的控制器主要负责管理主题、分区和副本。 Kafka系统在操作主题、分区和副本时,控制器会在Zookeeper系统的/brokers/topics节点,以及其子节点路径上注册一系列的监听器。 使用Kafka应用接口或者是Kafka系统脚本创建一个主题时,服务端会将创建后的结果返回给客户端。当客户端收到创建成功的提示时,其实服务端并没有实际创建主题,而只是在Zookeeper系统的/brokers/topics节点中创建了该主题对应的子节点名称。

  代理节点调用onBecomingLeader()函数实际上调用的是onControllerFailover()函数,所以在控制器调用onControllerFailover()函数时,会在初始化阶段分别创建分区状态机和副本状态机。代码如下所示:

  1. def onControllerFailover() {
  2. if(isRunning) {
  3. info("Broker %d starting become controller state
  4. transition".format(config.brokerId))
  5. readControllerEpochFromZookeeper()
  6. incrementControllerEpoch(zkUtils.zkClient)
  7.  
  8. // 在/brokers/topics节点注册监听器
  9. registerReassignedPartitionsListener()
  10. registerIsrChangeNotificationListener()
  11. registerPreferredReplicaElectionListener()
  12. partitionStateMachine.registerListeners() // 注册分区状态机
  13. replicaStateMachine.registerListeners() // 注册副本状态机
  14.  
  15. initializeControllerContext()
  16.  
  17. // 在控制器初始化之后,在状态机启动之前,需要发送更新元数据请求
  18. sendUpdateMetadataRequest(controllerContext.liveOrShuttingDownBrokerIds.toSeq)
  19.  
  20. replicaStateMachine.startup() // 启动副本状态机
  21. partitionStateMachine.startup() // 启动分区状态机
  22.  
  23. // 在自动故障转移中为所有主题注册分区更改监听器
  24. controllerContext.allTopics.foreach(topic => partitionStateMachine.
  25. registerPartitionChangeListener(topic))
  26. info("Broker %d is ready to serve as the new controller with epoch %d".
  27. format(config.brokerId, epoch))
  28. maybeTriggerPartitionReassignment()
  29. maybeTriggerPreferredReplicaElection()
  30. if (config.autoLeaderRebalanceEnable) {
  31. info("starting the partition rebalance scheduler")
  32. autoRebalanceScheduler.startup()
  33. autoRebalanceScheduler.schedule("partition-rebalance-thread",
  34. checkAndTriggerPartitionRebalance,
  35. 5,
  36. config.leaderImbalanceCheckIntervalSeconds.toLong,
  37. TimeUnit.SECONDS)
  38. }
  39. deleteTopicManager.start()
  40. }
  41. else
  42. info("Controller has been shut down, aborting startup/failover")
  43. }

  主题的分区状态机通过registerListeners()函数,在Zookeeper系统中的/brokers/topics节点上注册了TopicChangeListener和DeleteTopicListener两个监听器。创建一个主题时,主题信息、主题分区和副本会被写到Zookeeper系统的/brokers/topics节点中,这就会触发分区和副本状态机注册监听器。

5.总结

  Kafka系统整体来说,调试还算方便。下载Kafka源代码,导入到IDE中,就可以启动整个Kafka系统了,可以通过DEBUG的方式来亲自了解控制器的执行流程。

6.结束语

  这篇博客就和大家分享到这里,如果大家在研究学习的过程当中有什么问题,可以加群进行讨论或发送邮件给我,我会尽我所能为您解答,与君共勉!

  另外,博主出书了《Hadoop大数据挖掘从入门到进阶实战》,喜欢的朋友或同学, 可以在公告栏那里点击购买链接购买博主的书进行学习,在此感谢大家的支持。

Kafka控制器选举流程剖析的更多相关文章

  1. Kafka控制器事件处理全流程分析

    前言 大家好,我是 yes. 这是Kafka源码分析第四篇文章,今天来说说 Kafka控制器,即 Kafka Controller. 源码类的文章在手机上看其实效果很差,这篇文章我分为两部分,第一部分 ...

  2. Kafka网络模型和通信流程剖析

    1.概述 最近有同学在学习Kafka的网络通信这块内容时遇到一些疑问,关于网络模型和通信流程的相关内容,这里笔者将通过这篇博客为大家来剖析一下这部分内容. 2.内容 Kafka系统作为一个Messag ...

  3. Laravel教程 二:路由,视图,控制器工作流程

    Laravel教程 二:路由,视图,控制器工作流程 此文章为原创文章,未经同意,禁止转载. View Controller 上一篇教程我们走了那么长的路,终于把Laravel安装好了,这一篇教程我们就 ...

  4. twemproxy代理主干流程——剖析twemproxy代码正编

    在twemproxy的发送和接收流程剖析中,我们已经完全弄清楚twemproxy如何将客户端以及服务端发来的包切分成msg,获得一个独立的msg后twemproxy应该如何处理?这是本文这次需要重点介 ...

  5. kafka知识体系-kafka设计和原理分析-kafka leader选举

    kafka leader选举 一条消息只有被ISR中的所有follower都从leader复制过去才会被认为已提交.这样就避免了部分数据被写进了leader,还没来得及被任何follower复制就宕机 ...

  6. Spring Security Oauth2 单点登录案例实现和执行流程剖析

    Spring Security Oauth2 OAuth是一个关于授权的开放网络标准,在全世界得到的广泛的应用,目前是2.0的版本.OAuth2在“客户端”与“服务提供商”之间,设置了一个授权层(au ...

  7. Jedis cluster命令执行流程剖析

    Jedis cluster命令执行流程剖析 在Redis Cluster集群模式下,由于key分布在各个节点上,会造成无法直接实现mget.sInter等功能.因此,无论我们使用什么客户端来操作Red ...

  8. ASP.NET MVC不可或缺的部分——DI(IOC)容器及控制器重构的剖析

    ASP.NET MVC不可或缺的部分——DI(IOC)容器及控制器重构的剖析   IoC框架最本质的东西:反射或者EMIT来实例化对象.然后我们可以加上缓存,或者一些策略来控制对象的生命周期,比如是否 ...

  9. 源码分析 Kafka 消息发送流程(文末附流程图)

    温馨提示:本文基于 Kafka 2.2.1 版本.本文主要是以源码的手段一步一步探究消息发送流程,如果对源码不感兴趣,可以直接跳到文末查看消息发送流程图与消息发送本地缓存存储结构. 从上文 初识 Ka ...

随机推荐

  1. vue-nuxtjs

    1.创建项目:npm create-nuxt-app projectName 2.npm i sass-loader node-sass

  2. 在虚拟机中安装Centos系统

    1.首先下载VMware 2.然后可以去http://mirrors.aliyun.com下载映像ISO 3.打开VM,点击创建新的虚拟机 4.选择典型模式 5.稍后安装操作系统 6.选择你所要安装的 ...

  3. 无法在Application Designer中打开PeopleTools对象

    PeopleSoft开发人员经常使用PeopleSoft Application Designer来查看/修改PeopleTools对象,例如字段,记录,页面,组件等.开发人员对Application ...

  4. Nginx的gzip

    webpack  compression-webpack-plugin => .gz CompressionPlugin = require("compression-webpack- ...

  5. 微信小程序开发---各代码文件简介

    根据上一文,已建立QuickStart 项目,该项目系本人毕设部分内容,所以记录以便以后查阅 开发小程序就必须了解小程序项目目录结构和文件作用,接下来就根据我现在自学得到的知识把这些记录下来. 一.目 ...

  6. 关于 js中replace 特殊符号 ‘.’ 的问题

    问题: 字符串转数组,但是分割点在‘.’ ,需要保留每个后缀的 ‘.’ + 类型 解决: let videoType = '.avi.rmvb.rm.asf.divx.mpg.mpeg.mpe.wmv ...

  7. idea注册码

     2019 idea  注册码:   N757JE0KCT-eyJsaWNlbnNlSWQiOiJONzU3SkUwS0NUIiwibGljZW5zZWVOYW1lIjoid3UgYW5qdW4iLC ...

  8. TCPDF解决保存中文文件名的方法

    PHP使用TCPDF生成PDF文件时,如果文件名是中文会被直接过滤掉,以下是TCPDF不能保存中文文件名的解决方法: 打开tcpdf.php文件,找到output函数,大约在8467行 或(7554) ...

  9. Java ActiveMQ 讲解(二)Spring ActiveMQ整合+注解消息监听

    对于ActiveMQ消息的发送,原声的api操作繁琐,而且如果不进行二次封装,打开关闭会话以及各种创建操作也是够够的了.那么,Spring提供了一个很方便的去收发消息的框架,spring jms.整合 ...

  10. Android OpenSL ES 开发:OpenSL ES利用SoundTouch实现PCM音频的变速和变调

    缘由 OpenSL ES 学习到现在已经知道 OpenSL ES 不仅能播放和录制PCM音频数据,还能改变声音大小.设置左声道或右声道播放.还能变速播放,可谓是播放音频的王者.但是变速有一点不好的就是 ...