Kafka源码阅读(二):Producer Metadata概述及源码分析

本文深入探讨Kafka Producer Metadata的含义、应用,重点解析LeastLoadedNode概念和Metadata更新流程。通过源码分析,揭示了当元数据需要更新时,如何通过Sender线程和NetworkClient协同工作来获取并确保数据一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇博文Kafka源码阅读(一):Kafka Producer整体架构概述和源码分析(一)介绍了Kafka 生产者发送消息的主要流程和计算分区等机制,接下来这篇博文将对Kafka更新Producer Metadata的机制进行讲解说明。

Metadata

什么是metadata

metadata指Kafka集群的元数据,包含了Kafka集群的各种信息,例如如:

  • 集群中有哪些节点;
  • 集群中有哪些topic,这些topic有哪些partition;
  • 每个partition的leader副本分配在哪个节点上,follower副本分配在哪些节点上;
  • 每个partition的AR有哪些副本,ISR有哪些副本;

metadata应用场景

metadata在Kafka中无疑是非常重要的,很多场景中都需要从metadata中获取数据或更新数据,例如:

  • KafkaProducer发送一条消息到指定的topic中,需要知道分区的数量,要发送的目标分区,目标分区的leader,leader所在的节点地址等,这些信息都要从metadata中获取。
  • 当Kafka集群中发生了leader选举,节点中partition或副本发生了变化等,这些场景都需要更新metadata中的数据。

LeastLoadedNode

判定leastLoadedNode
LeastLoadedNode指Kafka集群中所有node中负载最小的那一个node,它是由每个node再InFlightRequests中还未确定的请求数决定的,未确定的请求越少则负载越小。如上图所示,node1即为LeastLoadedNode

更新metadata

       当客户端中没有需要使用的元数据信息时,比如没有指定的主题信息或者超过了rnetadata .rnax.age.rns配置的时间还没有更新元数据就会进行元数据的强制更新。
        元数据的更新操作是在客户端内部进行的,对客户端的外部使用者不可见。当需要更新元数据时,会先挑选出LeastLoadedNode,然后向这个node发送MetadataRequest来获取具体的元数据信息。
        创建完成MetadataRequest后,该请求也会放入InFlightRequests中,因此更新元数据与发送消息一样都是由Sender线程负责的,但是主线程也会读取元数据信息,因此这些操作都会通过synchronizedfinal来保证数据一致性。


源码分析

       上一篇博文中KafkaProducer发送消息的doSend()方法中调用了waitOnMetadata()方法来等待更新元数据,那么Kafka是如何等待更新元数据的呢?接下来就让我们通过阅读源码来分析一下这其中的一些细节。在开始分析源码之前我们先看下Cluster对象和Metadata对象中的主要属性,以便更好的理解代码。

Metadata.java

// 该Metadata对象会被主线程和Sender线程共享, 当metadata不包含我们所需要的数据时会发送``MetadataRequest``来同步数据。
// ProducerMetadata继承了Metadata类
public class Metadata implements Closeable {
   
   
    private final Logger log;
    private final Map<String, Long> topics = new HashMap<>(); // topic和过期时间的对应关系
    private final long refreshBackoffMs;// retry.backoff.ms: 默认值为100ms,它用来设定两次重试之间的时间间隔,避免无效的频繁重试.
    private final long metadataExpireMs;// metadata.max.age.ms: 默认值为300000,如果在这个时间内元数据没有更新的话会被 强制更新.
    private int updateVersion;  // 更新版本号,每更新成功1次,version自增1,主要是用于判断metadata是否更新
    private int requestVersion; // 请求版本号,没发送一次请求,version自增1
    private long lastRefreshMs; // 上一次更新的时间(包含更新失败)
    private long lastSuccessfulRefreshMs; // 上一次更新成功的时间
    private KafkaException fatalException;
    private Set<String> invalidTopics; // 非法的topics
    private Set<String> unauthorizedTopics; // 未认证的topics
    private MetadataCache cache = MetadataCache.empty();
    private boolean needUpdate; 
    private final ClusterResourceListeners clusterResourceListeners; // 会收到metadata updates的Listener列表
    private boolean isClosed;
    private final Map<TopicPartition, Integer> lastSeenLeaderEpochs; // 存储Partition最近一次的leaderEpoch
}

Cluster.java

// 保存了Kafka集群中部分nodes、topics和partitions的信息
public final class Cluster {
   
   
    private final boolean isBootstrapConfigured;
    private final List<Node> nodes;
    private final Set<String> unauthorizedTopics; // 未认证的topics
    private final Set<String> invalidTopics; // 非法的topics
    private f
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值