kafka源码4-消息封装RecordAccumulator

本文深入探讨Kafka的RecordAccumulator如何封装消息为批次进行发送。通过分析RecordAccumulator的内部结构,包括创建队列、内存分配和数据写入批次的流程,揭示其在高并发场景下的设计理念和实现细节。
摘要由CSDN通过智能技术生成

kafka发送的消息是封装成批次发送的,这些操作都是在RecordAccumulator对象中操作的,下图是RecordAccumulator中的对象对应关系
在这里插入图片描述

首先看一下RecordAccumulator中的一些对应关系,生产者发送数据是分装在ProducerBatch中的,每个Partition对应一个Dequeue队列,这些队列组成批次batches,BufferPool是一个内存池,ProducerBatch对象的内存就是在内存池中申请的

封装批次流程
 public RecordAppendResult append(TopicPartition tp,
                                     long timestamp,
                                     byte[] key,
                                     byte[] value,
                                     Header[] headers,
                                     Callback callback,
                                     long maxTimeToBlock) throws InterruptedException {
   
        // We keep track of the number of appending thread to make sure we do not miss batches in
        // abortIncompleteBatches().
        appendsInProgress.incrementAndGet();
        ByteBuffer buffer = null;
        if (headers == null) headers = Record.EMPTY_HEADERS;
        try {
   
            // check if we have an in-progress batch
            /**
             * 1.根据分区获取对应的队列
             */
            Deque<ProducerBatch> dq = getOrCreateDeque(tp);
            synchronized (dq) {
   
                /**
                 * 2.尝试往队列中的最后一个批次写数据,如果还没有分配内存,则添加数据失败
                 */
                if (closed)
                    throw new KafkaException("Producer closed while send in progress");
                RecordAppendResult appendResult = tryAppend(timestamp, key, value, headers, callback, dq);
                if (appendResult != null)
                    return appendResult;
            }
            /**
             * 队列中没有批次,则创建批次
             */

            // we don't have an in-progress record batch try to allocate a new batch
            byte maxUsableMagic = apiVersions.maxUsableProduceMagic();
            /**
             * 3.计算一个批次的大小,默认16Kb
             * 消息的大小和批次的大小取最大值作为批次的大小,原因是消息的大小有可能比批次的大小还大
             * 如果发送数据的时候,消息的大小超过了批次的大小,那么消息会被一条一条发送出去,这样会影响性能
             */
            int size = Math.max(this.batchSize, AbstractRecords.estimateSizeInBytesUpperBound(maxUsableMagic, compression, key, value, headers));
            log.trace("Allocating a new {} byte message buffer for topic {} partition {}", size, tp.topic(), tp.partition());
            /**
             * 4.根据批次的大小分配内存
             */
            buffer = free.allocate(size, maxTimeToBlock);
            /**
             * 5.再次尝试把数据写入对应的批次,第一次执行时,是失败的,因为还没有批次
             */
            synchronized (dq) {
   
                // Need to check if producer is closed again after grabbing the dequeue lock.
                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值