kafka各版本消息介绍
V0
- offset:分区中的偏移量
- message size:消息大小
- crc32(4B):crc32校验值。校验范围为magic至value之间。
- magic(1B):消息格式版本号,此版本的magic值为0。
- attributes (1B):消息的属性。总共占1个字节,低3 位表示压缩类型:0表示NONE、1表示GZIP、2表示SNAPPY、3 表示LZ4(LZ4自 Kafka 0.9.x引入),其余位保留。
- keylength(4B):表示消息的 key 的长度。如果为-1,则表示没有设置 key,即key = null.
- key:可选,如果没有 key 则无此字段
- value length(4B):实际消息体的长度。如果为-1,则表示消息为空
- value:消息体。可以为空,比如墓碑 (tombstone)消息。
V1
改动点:
- 增加timestamp,标识消息的时间戳
- v1版本的magic字段的值为1。
- v1 版本的attributes 字段中的低3位和vO版本的一样,还是表示压缩类型而第4个位(bit)也被利用了起来:0表示timestamp类型为CreateTime,而1表示timestamp类型为LogAppendTime,其他位保留。
timestamp 类型由broker 端参数log,message.timestamp.type 来配置,默认值为CreateTime,即采用生产者创建消息时的时间戳。如果在创建 ProducerRecord 时没有显式指定消息的时间戳,那么 KafkaProducer也会在发送这条消息前自动添加上。下面是 KafkaProducer 中与此对应的一句关键代码:long timestamp= record.timestamp() == null ? time.milliseconds() :record.timestamp();
v1版本的消息的最小长度(RECORDOVERHEADV1)要比版本的大8个字节即22B。
V2
v2 版本中消息集称为 Record Batch,而不是先前的 Message Set,其内部也包含了一条或多条消息,消息的格式参见图5-7 的中部和右部。在消息压缩的情形下,Record Batch Header部分(参见图5-7左部,从first offset 到records count 字段)是不被压缩的,而被压缩的是records字段中的所有内容。生产者客户端中的ProducerBatch对应这里的RecordBatch,而 ProducerRecord 对应这里的 Record。
先讲述消息格式 Record的关键字段可以看到内部字段大量采用了 Varints,这样 Kafka可
以根据具体的值来确定需要几个字节来保存。v2 版本的消息格式去掉了 crc 字段,另外增加了
length (消息总长度)、timestamp delta (时间戳增量)、offset delta(位移增量)
和headers信息,并且attributes 字段被弃用了,笔者对此做如下分析(key、keylength
value、valuelength字段同v0和vl版本的一样,这里不再赘述)。
- length:消息总长度
- attributes:弃用,但还是在消息格式中占据1B 的大小,以备未来的格式扩展。
- timestamp delta:时间戳增量。通常一个timestamp 需要占用8个字节,如果像
这里一样保存与RecordBatch 的起始时间戳的差值,则可以进一步节省占用的字节数。 - offset delta:位移增量。保存与 RecordBatch 起始位移的差值,可以节省占用的字节数。
- headers:这个字段用来支持应用级别的扩展,而不需要像v0和v1版本一样不得不
将一些应用级别的属性值嵌入消息体。Header 的格式如上图最右部分所示包含 key
和value,一个Record 里面可以包含0至多个Header。
对于vI版本的消息,如果用户指定的 timestamp 类型是 LogAppendTime 而不是
CreateTime,那么消息从生产者进入 broker 后,timestamp 字段会被更新,此时消息的crc
值将被重新计算,而此值在生产者中已经被计算过一次。再者,broker 端在进行消息格式转换
时(比如 v1 版转成v0版的消息格式)也会重新计算 cr 的值。在这些类似的情况下,消息从
生产者到消费者之间流动时,crc 的值是变动的,需要计算两次 crc 的值,所以这个字段的设
计在 vO和v1版本中显得比较“鸡肋”。在 v2版本中将cr的字段从 Record 中转移到了
RecordBatch 中。
v2版本对消息集(RecordBatch)做了彻底的修改,参考上图最左部分,除了刚刚提及的
crc字段,还多了如下字段。
- first offset:表示当前 RecordBatch 的起始位移
- length:计算从partition leader epoch 字段开始到末尾的长度
- partition leader epoch:分区leader 纪元,可以看作分区leader 的版本号或更新次数
- magic:消息格式的版本号,对v2版本而言,magic等于2。
- attributes:消息属性,注意这里占用了两个字节。低3位表示压缩格式,可以参
考v0和vl;第4位表示时间戳类型;第5位表示此RecordBatch 是否处于事务中,0
表示非事务,1表示事务。第6位表示是否是控制消息(ControlBatch),0表示非控
制消息,而 1表示是控制消息,控制消息用来支持事务功能。 - last offset delta: RecordBatch 中最后一个 Record 的offset 与first offiset 的差值
主要被broker用来确保RecordBatch 中Record 组装的正确性。 - first timestamp:RecordBatch 中第一条 Record 的时间戳。
- maxtimestamp:RecordBatch 中最大的时间戳,一般情况下是指最后一个 Record
的时间戳,和last offset delta的作用一样,用来确保消息组装的正确性。 - producerid:PID,用来支持幂等和事务。
- producer epoch:和producer id一样,用来支持幂等和事务。
- first sequence:和 producer id、producer epoch 一样,用来支持幂等和事务
- recordscount:RecordBatch中Record的个数。