1.Controller 发送集群元数据更新请求
集群 Controller 负责元数据的管理,保存有一个 event 事件队列,如果 event 事件是通知其他节点更新集群元数据的话就会广播元数据更新请求出去。在创建主题、副本主从切换等等都会触发这个过程。
ControllerEventManager.doWork() 从事件队列queue中获取到事件:QueuedEvent(event=LeaderAndIsrResponseReceived()
ControllerChannelManager.RequestSendThread.doWork() 轮训到队列中待发送请求 ApiKeys=UPDATE_METADATA
NetworkClient.doSend() 发送集群内部请求 ApiKey=UPDATE_METADATA (org.apache.kafka.clients.NetworkClient)
2.其他Broker处理元数据更新
KafkaApis.handle() => 处理客户端请求:UPDATE_METADATA
KafkaApis.handleUpdateMetadataRequest() => 更新元数据
Kafkaapis.isBrokerEpochStale() => 校验epoch
ReplicaManager.maybeUpdateMetadataCache() => 更新元数据
MetadataCache.updateMetadata() => 更新元数据
MetaCache.addOrUpdatePartitionInfo => 更新元数据
最终元数据保存在每个 boker 的缓存 metadataSnapshot 属性中。
def updateMetadata(correlationId: Int, updateMetadataRequest: UpdateMetadataRequest): Seq[TopicPartition] = {
inWriteLock(partitionMetadataLock) {
updateMetadataRequest.liveBrokers.forEach { broker =>
// ..
// 这里替换内存中的缓存
metadataSnapshot = MetadataSnapshot(partitionStates, topicIds.toMap, controllerIdOpt, aliveBrokers, aliveNodes)
}
}
}
3.元数据本地缓存获取
每个节点都会创建一个 ZkMetadataCache 缓存对象如果是 Raft协议的话就是使用的 RaftMetadataCache 缓存,里面有个 metadataSnapshot 属性就缓存了集群所有元数据,并提供各个 get() 方法来获取主题、分区等等信息。
class ZkMetadataCache(brokerId: Int) extends MetadataCache with Logging {
// 集群元数据缓存结构
private var metadataSnapshot: MetadataSnapshot;
getPartitionMetadata();
getTopicMetadata();
getAllTopics();
getAllPartitions();
getPartitionInfo();
getPartitionLeaderEndpoint();
getControllerId();
getClusterMetadata();
}
其中分区信息定义:
public static class UpdateMetadataPartitionState implements Message {
String topicName; // 主题
int partitionIndex; // 分区编号
int controllerEpoch; // Controller 的 epoch 任期
int leader; // 主副本所在 brokerId
int leaderEpoch; // 主副本所在 broker 的 epoch 任期
List<Integer> isr; // ISR列表,也就是保持 FETCH 同步的所有 broker 节点
int zkVersion;
List<Integer> replicas; // 副本列表
List<Integer> offlineReplicas; // 离线副本列表
private List<RawTaggedField> _unknownTaggedFields;
}
4.处理 METADATA 请求
获取集群元数据,客户端发送 METADATA 请求获取结果:
KafkaApis.handle() => 处理客户端请求:METADATA
KafkaApis.handleTopicMetadataRequest() => 获取集群元数据
响应结果:
MetadataResponseData(
throttleTimeMs=0,
brokers=[
MetadataResponseBroker(nodeId=2, host='localhost', port=29092, rack=null),
MetadataResponseBroker(nodeId=1, host='localhost', port=19092, rack=null)],
clusterId='ZNcsoJSfQQSMHXX92InNhA',
controllerId=1,
topics=[
MetadataResponseTopic(
errorCode=0,
name='flinkin-01',
topicId=4I1Ms6FqSBWRkJMPI6BdcA,
isInternal=false,
partitions=[
MetadataResponsePartition(errorCode=0, partitionIndex=0, leaderId=2, leaderEpoch=7, replicaNodes=[1, 2], isrNodes=[2, 1], offlineReplicas=[])
],
topicAuthorizedOperations=-2147483648
)
],
clusterAuthorizedOperations=-2147483648
)
文章详细阐述了Kafka集群中Controller如何发送元数据更新请求,其他Broker如何处理这些更新,以及元数据在本地缓存的管理和获取。元数据更新涉及到创建主题、副本主从切换等操作,而MetadataCache则存储集群的元数据信息,提供不同方法获取主题、分区等信息。
8670

被折叠的 条评论
为什么被折叠?



