Kafka生产者介绍(三):MemoryRecords

RecordAccumulator中最终存放消息的对象MemoryRecords。MemoryRecords表示的是多个消息的集合,其中封装了Java NIO ByteBuffer类,MemoryRecords主要字段有:

public class MemoryRecords implements Records {

    private final static int WRITE_LIMIT_FOR_READABLE_ONLY = -1;

    // 压缩器,支持GZIP,SNAPPY,LZ4三种压缩方式
    // Compressor有ByteBufferOutputStream bufferStream字段,集成了java.io.OutputStream,封装了ByteBuffer,会进行自动扩容。
    // 扩容后,Compressor里ByteBufferOutputStream会指向一个新的Bytebuffer对象,会与MemoryRecords.buffer不一样。
    private final Compressor compressor;

    // buffer中最多可以写入多少个字节的数据
    private final int writeLimit;

    // buffer大小
    private final int initialCapacity;

    // 用来保存消息的java.nio.ByteBuffer
    private ByteBuffer buffer;

    // 此MemoryRecords是只读模式,还是可写模式。在MemoryRecords发送前时,会设置成只读模式
    private boolean writable;
    //判断MemoryRecords是否为可写模式,然后调用Compressor.put(java.nio.ByteBuffer)方法把消息写到ByteBuffer中
    public void append(long offset, Record record) 
    //根据Compressor估计已经写的字节数,只是个估计,可能会导致ByteBuffer扩容情况。
    public boolean hasRoomFor(byte[] key, byte[] value)
    // Close this batch for no more appends
    // 当出现ByteBuffer扩容的情况,MemoryRecords.buffer和ByteBufferOutputStream.buffer指向的已经不是不是一个ButeBuffer对象。
    // close方法会把MemoryRecords.buffer指向扩容后的ByteBuffer对象
    public void close()
    // 对于可读的MemoryRecords,返回的是MemoryRecords.buffer.limit,对于可写的,返回ByteBufferOutputStream.buffer字段的大小。
    public int sizeInBytes()
}

看MemoryRecords的构造函数:

public class MemoryRecords implements Records {
   // Construct a writable memory records
    private MemoryRecords(ByteBuffer buffer, CompressionType type, boolean writable, int writeLimit) {
    	// 根据入参赋值writable、writeLimit
    	this.writable = writable;
        this.writeLimit = writeLimit;
        
        // Java NIO中ByteBuffer的capacity
        this.initialCapacity = buffer.capacity();
        
        if (this.writable) {// 如果writable为true,即处于可写状态
            this.buffer = null;
            // 利用入参ByteBuffer类型的buffer和CompressionType类型的type构造Compressor实例compressor
            this.compressor = new Compressor(buffer, type);
        } else {
        	// buffer设置为入参ByteBuffer类型的buffer
            this.buffer = buffer;
            // compressor设置为null
            this.compressor = null;
        }
    }	
}

append函数把消息添加到MemoryRecords中。

public class MemoryRecords implements Records {
    public long append(long offset, long timestamp, byte[] key, byte[] value) {
		// 首先判断MemoryRecords的可写标志位writable
        if (!writable)
            throw new IllegalStateException("Memory records is not writable");
		// 根据key、value通过Record的recordSize()方法计算记录大小size
        int size = Record.recordSize(key, value);
		// 压缩器compressor中记录偏移量offset、记录大小size、记录key和value
        compressor.putLong(offset);
        compressor.putInt(size);
		// putRecord最后会把消息放在appendStream中。
        long crc = compressor.putRecord(timestamp, key, value);
		// 而已写入未压缩总大小writtenUncompresse是记录大小size再加上size所占大小(int类型)和offset所占大小(long类型)之和,也就是额外的Int+Long为12
        compressor.recordWritten(size + Records.LOG_OVERHEAD);
        return crc;
    }
}
hasRoomFor方法判断是否还能写入。
public class MemoryRecords implements Records {
    public boolean hasRoomFor(byte[] key, byte[] value) {
        if (!this.writable)
            return false;
		// 判断写入的数据大小是否为0,是0的话,直接用capacity判断,不是的话用writeLimit判断。
        return this.compressor.numRecordsWritten() == 0 ?
            this.initialCapacity >= Records.LOG_OVERHEAD + Record.recordSize(key, value) :
        //estimatedBytesWritten预估消息压缩后大小
            this.writeLimit >= this.compressor.estimatedBytesWritten() + Records.LOG_OVERHEAD + Record.recordSize(key, value);
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值