kafka源码2-元数据

本文深入探讨了Kafka生产者如何更新元数据,包括元数据结构、本地缓存处理以及远程获取元数据的请求流程。在本地缓存缺失时,生产者通过向broker发送请求获取元数据,Sender线程和NetworkClient的poll方法在此过程中起到关键作用。
摘要由CSDN通过智能技术生成

从前面我们看到,生产者在发送数据时,首先是更新元数据,这次分析一下更新元数据的流程
,首先生产者是怎么保存元数据的

元数据结构

Metadata对象

public final class Metadata implements Closeable {

private static final Logger log = LoggerFactory.getLogger(Metadata.class);

public static final long TOPIC_EXPIRY_MS = 5 * 60 * 1000;
private static final long TOPIC_EXPIRY_NEEDS_UPDATE = -1L;
//元数据更新最小的时间间隔,默认100ms,减少网络压力
private final long refreshBackoffMs;
//元数据过期时间,5min
private final long metadataExpireMs;
//元数据版本号,每个元数据都有版本号
private int version;
//上一次更新元数据的时间
private long lastRefreshMs;
//上一次成功更新元数据的时间
private long lastSuccessfulRefreshMs;
private AuthenticationException authenticationException;
//kafka的集群信息
private Cluster cluster;
//是否需要更新元数据
private boolean needUpdate;
/* Topics with expiry time */
private final Map<String, Long> topics;
private final List<Listener> listeners;
private final ClusterResourceListeners clusterResourceListeners;
private boolean needMetadataForAllTopics;
private final boolean allowAutoTopicCreation;
private final boolean topicExpiryEnabled;
private boolean isClosed;
}
Cluster对象

```java
ublic final class Cluster {

    private final boolean isBootstrapConfigured;
    //kafka集群的节点信息
    private final List<Node> nodes;
    //未授权的topic
    private final Set<String> unauthorizedTopics;
    private final Set<String> internalTopics;
    private final Node controller;
    //topic分区信息
    private final Map<TopicPartition, PartitionInfo> partitionsByTopicPartition;
    //topic的副本信息
    private final Map<String, List<PartitionInfo>> partitionsByTopic;
    //topic 可用的Partition信息
    private final Map<String, List<PartitionInfo>> availablePartitionsByTopic;
    //服务器上有哪些副本
    private final Map<Integer, List<PartitionInfo>> partitionsByNode;
    //服务器编号与服务器对应的关系
    private final Map<Integer, Node> nodesById;
    private final ClusterResource clusterResource;
    }

Node对象

public class Node {
   

    private static final Node NO_NODE = new Node(-1, "", -1);
    //id编号,配置参数执行
    private final int id;
    private final String idString;
    //主机名
    private final String host;
    //端口号,默认9092
    private final int port;
    //机加
    private final String rack;
    }

PartitionInfo对象

public class PartitionInfo {
   
    //主题
    private final String topic;
    //分区编号
    private final int partition;
    //leader所在的节点
    private final Node leader;
    //副本所在的节点
    private final Node[] replicas;
    //ISR列表
    private final Node[] inSyncReplicas;
    //离线的副本
    private final Node[] offlineReplicas;
    }
元数据更新流程
private ClusterAndWaitTime waitOnMetadata(String topic, Integer partition, long maxWaitMs) throws InterruptedException {
   
        // add topic to metadata topic list if it is not there already and reset expiry
        metadata.add(topic);
        //在元数据中获取集群信息
        Cluster cluster = metadata.fetch();
        Integer partitionsCount = cluster.partitionCountForTopic(topic);
        // Return cached metadata if we have it, and if the record's partition is either undefined
        // or within the known partition range
        //集群中已经存在分区信息,则直接返回
        if (partitionsCount != null && (partition == null || partition < partitionsCount))
            return new ClusterAndWaitTime(cluster, 0);

        long begin = time.milliseconds();
        long remainingWaitMs = maxWaitMs;
        long elapsed;
        // Issue metadata requests until we have metadata for the topic or maxWaitTimeMs is exceeded.
        // In case we already have cached metadata for the topic, but the requested partition is greater
        // than expected, issue an update request only once. This is necessary in case the metadata
        // is stale and the number of partitions for this topic has increased in the meantime.
        do {
   
            log.trace("Requesting metadata update for topic {}.", topic);
            metadata.add(topic);
            /**
             * 是否需要更新元数据的标志更改为true
             * 获取当前的元数据版本
             */
            int version = metadata.requestUpdate();
            //唤醒sender线程拉取元数据
            sender.wakeup();
            try {
   
                // 等待元数据更新
                metadata.awaitUpdate(version, remainin
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值