kafka数据如何存_深入理解Kafka服务端之Broker如何更新集群的元数据

一、场景分析在客户端初始化生产者对象时,需要配置 bootstrap.servers 参数,用于获取 Kafka 集群的元数据。这里只需要指定集群中任意一台节点即可,原因就是每个 Broker 均存储了集群的所有元数据信息。这篇主要分析 Controller 发送更新元数据请求的场景,以及 Broker更新集群元数据的流程。二、图示说明Controller 发送更新元数据请求,B...
摘要由CSDN通过智能技术生成
一、场景分析      在客户端初始化生产者对象时,需要配置 bootstrap.servers 参数,用于获取 Kafka 集群的元数据。这里只需要指定集群中 任意一台 节点即可,原因就是每个 Broker 均存储了集群的所有元数据信息。这篇主要分析 Controller 发送更新元数据请求的场景,以及 Broker更新集群元数据的流程。 二、图示说明

Controller 发送更新元数据请求,Broker 接收请求并更新元数据流程图解

dce04ab8954059fbedf1ba2b34247fa2.png

三、源码分析

1.Controller 发送更新元数据请求的场景

    在前面几篇关于 Controller 功能的介绍中,多次提到了 Controller 向集群的 Broker 发送更新元数据的请求,如:

①调用 onControllerFailover 方法执行成为 Controller 的逻辑时,向集群中所有运行中的 Broker 发送更新元数据的请求

//向集群中所有运行中的Broker发送更新元数据的请求sendUpdateMetadataRequest(controllerContext.liveOrShuttingDownBrokerIds.toSeq, Set.empty)

②调用 KafkaController.processBrokerChange 方法处理节点数量变更时:

if (newBrokerIds.nonEmpty) {
      controllerContext.addLiveBrokersAndEpochs(newBrokerAndEpochs)  //执行新加入节点启动的逻辑  onBrokerStartup(newBrokerIdsSorted)}

在 onBrokerStartup 方法中,分别向集群现有的所有 Broker 和新加入的 Broker 发送更新元数据的请求

// 第2步:给集群现有Broker发送元数据更新请求,令它们感知到新增加了BrokersendUpdateMetadataRequest(existingBrokers.toSeq, Set.empty)// 第3步:给新增Broker发送元数据更新请求,令它们同步集群当前的所有分区的元数据sendUpdateMetadataRequest(newBrokers, controllerContext.partitionLeadershipInfo.keySet)

③调用 KafkaController.processBrokerModification 方法处理节点信息变更时:

// 第3步:如果从zk获取到的和元数据中的不相等,说明Broker数据发生了变更// 那么,更新元数据缓存,以及执行onBrokerUpdate方法处理Broker更新的逻辑if (newMetadata.endPoints != oldMetadata.endPoints) {
        info(s"Updated broker metadata: $oldMetadata -> $newMetadata")    controllerContext.updateBrokerMetadata(oldMetadata, newMetadata)    onBrokerUpdate(brokerId)}

在 onBrokerUpdate 方法中,向集群的所有 Broker 发送更新元数据的请求

// 给集群所有Broker发送UpdateMetadataRequest,让它们去更新元数据sendUpdateMetadataRequest(controllerContext.liveOrShuttingDownBrokerIds.toSeq, Set.empty)

④调用 KafkaController.processTopicChange 方法处理新增主题时:

// 第9步:调整新增主题所有分区以及所属所有副本的运行状态为“在线”状态if (addedPartitionReplicaAssignment.nonEmpty)  onNewPartitionCreation(addedPartitionReplicaAssignment.keySet)

在 onNewPartitionCreation 方法中,分别使用分区状态机和副本状态机进行分区及副本状态的转换,调用的 handleStateChanges 方法中,都执行了如下代码:

//Controller控制类请求给对应的Broker,通知其状态变化controllerBrokerRequestBatch.sendRequestsToBrokers(controllerContext.epoch)

sendRequestsToBrokers:发送各种控制类请求

def sendRequestsToBrokers(controllerEpoch: Int): Unit = {
        try {
          val stateChangeLog = stateChangeLogger.withControllerEpoch(controllerEpoch)      //发送更新Leader副本和ISR列表的请求      sendLeaderAndIsrRequest(controllerEpoch, stateChangeLog)      //发送更新元数据的请求      sendUpdateMetadataRequests(controllerEpoch, stateChangeLog)      //发送副本下线的请求      sendStopReplicaRequests(controllerEpoch)    } catch {
      ...}

⑤调用 KafkaController.processTopicDeletion 方法处理删除主题时,待删除主题最后交给了 TopicDeletionManager 管理,其重启主题删除的方法  resumeDeletions 中,无论调用的 completeDeleteTopic 方法还是调用的 onTopicDeletion 方法,都会向集群的 Broker 发送更新元数据的请求:

    completeDeleteTopic:该方法通过调用副本状态机的 handleStateChanges 方法,向 Broker 发送更新元数据的请求,原理同上

//第3步:利用副本状态机将这些副本对象转换成NonExistentReplica状态。replicaStateMachine.handleStateChanges(replicasForDeletedTopic.toSeq, NonExistentReplica)

    onTopicDeletion:

//第四步:向集群Broker发送指定分区的元数据更新请求client.sendMetadataUpdate(partitions)

    综上:可以认为只要 Controller 修改了集群的元数据,就会向 Broker 发送更新元数据的请求。

2. Controller 发送更新元数据请求的流程     在《 深入理解Kafka服务端之Controller基于事件队列的处理流程 》中,分析过 ControllerChannelManager 组件,其管理了 Controller 和集群所有 Broker 之间的网络连接,并为每个 Broker 创建了一个请求队列和一个专属的发送线程,用来向 Broker 发送请求并接收响应。

    其实,在 Controller 和 ControllerChannelManager 之前还有一层,可以理解为请求批次对象。相关的类如下:

  • AbstractControllerBrokerRequestBatch:请求批次的抽象基类

  • ControllerBrokerRequestBatch:请求批次的具体实现类

c235f2fef40aacc58d75d75d4f16307a.png

AbstractControllerBrokerRequestBatch 的定义:

abstract class AbstractControllerBrokerRequestBatch(config: KafkaConfig,//配置类                                                    controllerContext: ControllerContext,//元数据类                                                    stateChangeLogger: StateChangeLogger//日志对象                                                   ) extends  Logging {
      //Controller 所在节点id  val controllerId: Int = config.brokerId  //存储LeaderAndIsrRequest请求的集合,key是目标Broker,value是一个map,value.key是主题分区,value.value是待更新的分区信息  val leaderAndIsrRequestMap = mutable.Map.empty[Int, mutable.Map[TopicPartition, LeaderAndIsrRequest.PartitionState]]  //存储StopReplicaRequest请求的集合,key是目标Broker,value是待停止副本的信息  val stopReplicaRequestMap = mutable.Map.empty[Int, ListBuffer[StopReplicaRequestInfo]]  //存储UpdateMetadataRequest请求的目标节点  val updateMetadataRequestBrokerSet = mutable.Set.empty[Int]  //存
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值