Kafka生产者介绍(四):RecordBatch

RecordBatch对象中封装了一个MemoryRecords对象,还有很多控制信息和统计信息。如下:
 

public final class RecordBatch {
	// 保存Recrod的个数		
	public int recordCount = 0;
	// 最大Record的字节数
    public int maxRecordSize = 0;
	// 记录尝试发送当前RecordBatch的次数。
    public volatile int attempts = 0;
    public final long createdMs;
	// 耗费时间
    public long drainedMs;
	//最后一次尝试发送的时间戳
    public long lastAttemptMs;
	// 存储数据的MemoryRecords对象
    public final MemoryRecords records;
	// 当前 RecordBatch 缓存的消息都会发到这个topicPartition。
    public final TopicPartition topicPartition;
	// RecordBatch 状态的Future对象
    public final ProduceRequestResult produceFuture;
	// 最后一次向RecordBatch追加消息的时间戳	
    public long lastAppendTime;
	// Thunk对象集合,可以理解为消息回调对象队列。Thunk中的callback字段就指向对应消息的Callback对象
	    /**
         * A callback and the associated FutureRecordMetadata argument to pass to it.
		 *********
		final private static class Thunk {
			final Callback callback;
			final FutureRecordMetadata future;

			Thunk(Callback callback, FutureRecordMetadata future) {
				this.callback = callback;
				this.future = future;
			}
		}     
	*/	
    private final List<Thunk> thunks;
	// 记录消息在RecordBatch中的偏移量
    private long offsetCounter = 0L;
	// 是否正在重试
    private boolean retry;
}

RecordBatch最重要的方法是添加record到当前结果集,并返回FutureRecord元数据对象

public final class RecordBatch {
    public FutureRecordMetadata tryAppend(long timestamp, byte[] key, byte[] value, Callback callback, long now) {
		// 估算剩余空间不足,这个并不是一个准确值。
        if (!this.records.hasRoomFor(key, value)) {
            return null;
        } else {
			//向MemoryRecord中添加数据,offsetCounter是在RecordBatch中的偏移量。
            long checksum = this.records.append(offsetCounter++, timestamp, key, value);
			// 更新MemoryRecord中消息中最大的大小和加入时间戳
            this.maxRecordSize = Math.max(this.maxRecordSize, Record.recordSize(key, value));
            this.lastAppendTime = now;
			// FutureRecordMetadata实现了Futher类,在生产者已经收到了某条消息的响应时,
			// FutureRecordMetadata.get()会返回RecordMetadata,里面包含了消息的分区和偏移量,给用户callback调用。
            FutureRecordMetadata future = new FutureRecordMetadata(this.produceFuture, this.recordCount,
                                                                   timestamp, checksum,
                                                                   key == null ? -1 : key.length,
                                                                   value == null ? -1 : value.length);
			// 把用户自定义的callback加入thunk中。
            if (callback != null)
                thunks.add(new Thunk(callback, future));
            this.recordCount++;
            return future;
        }
    }
}

当RecordBatch成功收到响应的时候,正常、超时或者关闭生产者时候,都会调用RecordBatch的done方法,在done方法中回调所有的callback。
 

public final class RecordBatch {
    public void done(long baseOffset, long timestamp, RuntimeException exception) {
        log.trace("Produced messages to topic-partition {} with base offset offset {} and error: {}.",
                  topicPartition,
                  baseOffset,
                  exception);
        // 顺序执行每个消息的callback
        for (int i = 0; i < this.thunks.size(); i++) {
            try {
                Thunk thunk = this.thunks.get(i);
                if (exception == null) {
                    // 把服务端返回的信息如offset和timestamp,封装成RecordMetadata。
                    RecordMetadata metadata = new RecordMetadata(this.topicPartition,  baseOffset, thunk.future.relativeOffset(),
                                                                 timestamp == Record.NO_TIMESTAMP ? thunk.future.timestamp() : timestamp,
                                                                 thunk.future.checksum(),
                                                                 thunk.future.serializedKeySize(),
                                                                 thunk.future.serializedValueSize());
					 //调用消息的自定义callback
                    thunk.callback.onCompletion(metadata, null);
                } else {
					//发送失败则直接调用callback,入参为失败异常。
                    thunk.callback.onCompletion(null, exception);
                }
            } catch (Exception e) {
                log.error("Error executing user-provided callback on message for topic-partition {}:", topicPartition, e);
            }
        }
		//标记整个RecordBatch都处理完成。
        this.produceFuture.done(topicPartition, baseOffset, exception);
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值