Kafka源码分析之ProducerBatch

本文深入分析Kafka的ProducerBatch,探讨其内部结构,包括Thunk/FutureRecordMetadata、ProducerRequestResult、RecordMetadata和MemoryRecordsBuilder。ProducerBatch用于存储待发送消息,其内部类Thunk表示消息块,与FutureRecordMetadata结合处理发送结果。同时,文章还讨论了ProducerRequestResult的完成逻辑和RecordMetadata的元数据信息。

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

在前面的Sender源码阅读中,发现在kafka发送消息过程中,先获取消息,同时还检查了集群的信息,然后通过KafkaClient来完成发送。这一篇中将对kafka的消息组织结构,包括TopicPartition、ProducerBatch、Metadata等进行分析。

1.TopicPartition

TopicPartition的实现比较简单,将topic的名称以及对应的分区号进行了封装。只包含了以下几个变量,并重写了hashCode和equals方法。

 private int hash = 0;
 private final int partition;
 private final String topic;

2.ProducerBatch

ProducerBatch用于存储一系列要发送的消息,其相关的数据组织结构如下所示。
在这里插入图片描述

2.1 Thunk/FutureRecordMetadata

Thunk是ProducerBatch的内部类,表示一个消息块。它包含了一个FutureRecordMetadata对象,表示发送记录后返回的结果。
FutureRecordMetadata实现了Future接口。包含了以下三个重要的方法

 @Override
    public RecordMetadata get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
   
        // Handle overflow.
        long now = time.milliseconds();
        long timeoutMillis = unit.toMillis(timeout);
        long deadline = Long.MAX_VALUE - timeoutMillis < now ? Long.MAX_VALUE : now + timeoutMillis;
        boolean occurred = this.result.await(timeout, unit);
        if (!occurred)
            throw new TimeoutException("Timeout after waiting for " + timeoutMillis + " ms.");
        if (nextRecordMetadata != null)
            return nextRecordMetadata.get(deadline - time.milliseconds(), TimeUnit.MILLISECONDS);
        return valueOrError();
    }

get方法中,通过result.await来等待直到有请求结果返回。

RecordMetadata value() {
   
        if (nextRecordMetadata != null)
            return nextRecordMetadata.value();
        return new RecordMetadata(result.topicPartition(
### Spring Boot Kafka集成源码分析教程 #### 了解Spring Boot与Kafka的整合机制 Spring Boot通过`spring-kafka`库简化了与Apache Kafka消息系统的交互过程[^1]。此库提供了生产者和消费者配置自动化的支持,使得开发者可以更专注于业务逻辑而非框架细节。 对于希望深入理解两者如何协同工作的开发人员来说,研究官方GitHub仓库中的测试案例是一个很好的起点。这些例子展示了不同场景下发送和接收消息的方法实现方式。此外,在`org.springframework.kafka.listener`包内包含了监听器容器的核心组件定义;而消息转换则主要发生在`org.springframework.kafka.support.converter`命名空间下的类里。 #### 关键接口解析 - **ProducerFactory**: 负责创建`KafkaTemplate`使用的`Producer`实例对象。 - **ConsumerFactory**: 构建用于订阅主题并处理传入记录流的对象。 - **KafkaListenerContainerFactory**: 提供给定配置参数构建监听器容器的能力。 - **DefaultKafkaProducerFactory & DefaultKafkaConsumerFactory**: 实现上述两个工厂的具体子类。 - **ConcurrentMessageListenerContainer**: 支持并发操作的消息监听器容器,默认情况下会为每个分区分配一个线程来执行消费任务。 ```java // 创建生产者的简单示例 @Bean public ProducerFactory<String, String> producerFactory() { Map<String, Object> configProps = new HashMap<>(); configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class); return new DefaultKafkaProducerFactory<>(configProps); } // 定义消费者属性 @Bean public ConsumerFactory<String, String> consumerFactory() { Map<String, Object> props = new HashMap<>(); props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); props.put(ConsumerConfig.GROUP_ID_CONFIG, "test-group"); props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); return new DefaultKafkaConsumerFactory<>(props); } ``` #### 深度探索:事务管理 当涉及到可靠性的需求时——比如确保消息不会丢失也不会重复处理——就需要考虑启用事务功能。这可以通过设置`enable.idempotence=true`以及指定合适的隔离级别(`read_committed`)来达成目的。此时,所有的写入都将被标记为幂等(idempotent),从而防止因网络错误等原因造成的重试过程中产生的重复数据条目。 #### 性能优化建议 为了提高吞吐量,应该调整诸如批量大小(batch.size)、压缩类型(compression.type)这样的高级选项。同时也要注意合理规划消费者的数量以匹配集群规模,并适当增加心跳检测间隔时间(session.timeout.ms)以便更好地适应高延迟环境。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值