kafka之消息格式

文章目录

  • Kafka版本
  • 消息格式
    • V0版本
    • V1版本
    • Message Set
    • V0与V1的缺陷
    • V2版本

Kafka版本

  1. kafka版本1.1.1,可能绝大部分也适用于kafka 0.10.x及以上版本。

消息格式

  1. 目前Kafka消息格式有三个版本,V0、V1和V2。

V0版本

  1. V0版本主要是指Kafka0.10.0.0之前的版本,是kafka最早的消息版本

    kafka之消息格式_第1张图片

  2. 字段含义

    • CRC(4B):CRC校验码,占用4个字节,校验magic至value之间字节是否被篡改
    • magic(1B):消息格式版本号,占用1个字节。V0版本是0,V1版本是1,V2版本是2
    • attributes(1B):属性字段,占用1个字节,只使用低3位表示消息的压缩类型,其他5位是保留位。
      • 0表示NONE,表示不启用压缩
      • 1表示GZIP
      • 2表示SNAPPY
      • 3表示LZ4
    • key length(4B):表示消息的key的长度。如果为-1,则表示没有设置key,即key=null
    • key:消息key,长度由key length值指定。如果key length值是-1,则无key(没有此字段)
    • value length(4B):表示消息的长度,占用4字节。
    • value:消息value,长度由value length值指定。如果value length值是-1,则无value,消息没有该字段。
  3. 消息头部(message Header):除了Key和Value之外的所有字段统称为消息头部。总共占用14字节(4B+1B+1B+4B+4B),即V0版本的消息长度最小是14B

  4. 此版本的问题

    • 即使不指定key(即key length=-1),还是要占用4个字节的空间
    • 即使不指定value(即value length=-1),还是要占用4个字节的空间
    • 没有消息的时间信息。kafka定期删除过期log只能依靠文件的最后修改时间。文件系统最后的修改时间很容易受到外部不确定因素的干扰。

V1版本

  1. V1版本主要是[0.10.0.0,0.11.0.0)之间的版本

    kafka之消息格式_第2张图片

  2. V1与V0的主要差异

    • 引入了8B的时间戳,即V1版本的消息头部最小是22B(14B+8B)
    • 属性字段第4位被用于指定时间戳类型
      • 0表示timestamp类型为CREATE_TIMECREATE_TIME表示在消息创建时由producer指定的时间戳
      • 1表示timestamp类型为LOG_APPEND_TIMELOG_APPEND_TIME 表示消息被发送到broker端时由broker指定的时间戳。

Message Set

  1. Kafka的消息层次分为:消息集合(message set)和消息。V0和V1版本使用的是日志项(log entry),以下是日志项的格式

    kafka之消息格式_第3张图片

  2. 每个消息集合中的日志项由shallow message和log entry header组成

    • shallow message:如果没有启用消息压缩,那么shallow message就是这条消息本身。如果启用消息压缩,kafka会将多条消息压缩到一起统一封装成shallow message的value字段。此时该shallow message被称为wrapper消息(或者外部消息),而value字段中包含的消息则被称为inner消息(内部消息)。v0和v1版本中的日志项只能包含一条shallow message
    • log entry header(日志项头部):由8B的offset和4B的size组成。offset指该消息在分区日志中的offset,如果是未压缩的消息,该offset就是消息的offset,否则该字段表示wrapper消息中最后一条inner消息的offset。因此,从V0、V1版本消息集合日志项中搜索该日志项的起始偏移是非常困难的,需要遍历所有的inner消息,即broker需要解压缩操作。

V0与V1的缺陷

  1. 空间利用率不高:不论key和value长度是多少,总是固定占用4B
  2. 只保存最新消息偏移量:如果启用压缩,offset是消息集合中最后一条消息的offset。如果想要获取第1条消息的offset,必须解压所有消息并加载到内存中,然后反向遍历才能获取到
  3. CRC校验,为每条消息都执行CRC没有必要
  4. 未保存消息长度:每次需要单条消息的总字节数信息时都需要计算得出,没有使用单独字段来保存。每次计算时为了避免对现有数据结构的破坏,都需要大量的对象副本, 解序列化效率很低。

V2版本

  1. V1版本主要是0.11.0.0(包含)之后的版本。此版本相比于v0和v1改动很大,引入了变长整型(Varints)和ZigZag编码(借鉴ProtoBuffer中的Zig-zag编码方式,绝对值较小的整数占用比较少的字节)。Varints是使用一个或多个字节来序列化整数的一种方法,数值越小,其所占用的字节数就越少。Zig-zag编码方式,使得绝对值较小的整数占用比较少的字节

    kafka之消息格式_第4张图片

  2. 字段详解

    • 增加消息总长度字段
    • 可变时间戳,使用一个可变长度保存与batch起始时间戳的差值。差值一般很小,所以需要保存的字节也小
    • 增加offset,保存消息offset与外层batch起始offset的差值,节省消息总字节数
    • 增加消息headers,主要是为了满足用户定制化需求,用户手动设置的
    • 去除CRC校验,V2不再为每条消息计算CRC32值,而是对整个消息batch进行CRC校验
    • 废弃attribute字段。V2版本将原先保存在attribute字段中的压缩类型、时间戳等信息统一保存在外层batch格式字段中,但是依然保留了单字节attribute为了以后扩展使用。
  3. V2版本中消息集合(message set)被消息批次所取代,叫做RecordBatch。这里的RecordBatch与producer中的batch不是一个含义。

    kafka之消息格式_第5张图片

  4. bath字段详解

    • CRC被放入Batch

    • 增加2B的attribute。

      • 最低3位依然是压缩类型

      • 第4位保存时间戳类型(NO_TIMESTAMP_TYPE是-1,CREATE_TIME是0,LOG_APPEND_TIME是1)。

      • 第5位事务类型(事务消息是1,非事务消息是0)

      • 第6位控制类型(ABORT是0,COMMIT是1,UNKNOWN是-1)

    • PID、 producer epoch 和序列号等信息都是 0.11.0.0 版本为了实现幂等性 producer 和支持事务而引入的。Kafka依靠PID+epoch来辨别消息是否己成功提交,从而防止出现重复生产消息。

  5. 0.11.0.0版本(及以后)的 Kafka消息在支持事务、幕等性 producer的同时还在一定程度上减少了网络I/O和磁盘 I/O 的开销(因V2版本协议的缘故)

你可能感兴趣的:(#,kafka)