图解 Kafka 的数据存储设计

Partition 数据文件

Kafka 中的 Message 是以 Topic 为基本单位进行归类的,不同的 Topic 之间是相互独立的。Topic 是一个逻辑上的概念,为了提升整个集群的吞吐量,Topic 在物理上还可以细分为多个 Partition(每个 Topic 划分几个 partition 是在创建 Topic 时指定的)。

每个 Partition 都负责保存和处理 Topic 的一部分 Message 数据,Partition 的个数对应了消费者和生产者的并发度,比如 Partition 的个数为 3 个,则集群中最多同时有 3 个线程的消费者并发处理数据。

​可以把 Partition 看作一个可追加的日志文件,Message 在被追加到分区日志文件的时候,都会分配一个特定的偏移量 offset,用作唯一标识,从而 Kafka 通过它来保证 Message 在 Partition 内的顺序性,不过 offset 并不跨分区,也就是说 Kafka 只能保证分区有序而非主题​有序。
在这里插入图片描述

一个 Patition 只属于一个 Topic,每个 partition 在磁盘上对应一个文件夹,该文件夹下存放了这个 Patition 的所有消息文件和索引文件。

Patition 中的每条 Message 都包含 offset、messageSize 以及 Data 。其中,offset 用来标识 Message 在这个 Patition 中的偏移量,它是一个逻辑值而并非实际物理偏移量,可以唯一确定 Patition 中的一条 Message;messageSize 表示消息内容的大小;Data 为消息的具体内容。

Message 的详细结构如下图所示,中间部分为一条完整的 Message,其中,“Record” 部分为消息格式,接下来我们具体描述一下 Record 格式中的各个字段。

在这里插入图片描述

  • crc32:是对 magic 到 value 范围的校验值,占4B;
  • magic:消息格式版本号,0.9.X 的版本对应的值为0,占1B;
  • attributes:消息属性,低 3 位表示压缩类型,其余位保留,占1B;
  • key length:表示消息的 key 的长度,若为 -1,则表示没有设置 key;
  • key:可选,没有 key 则无此字段;
  • value length:表示实际消息体的长度,若为 -1,则表示消息为空;
  • value:消息体,可以为空。

与 Message 对应的则是 Message Set(消息集)的概念(上图左侧),消息集中包含一条或者多条 Message,按 offset 由小到大排列在一起的。Message Set 不仅是存储在磁盘以及在网络上传输的基本形式,也是 Kafka 进行数据压缩的基本单元。

LEO & HW

每个 Patition 都有两个重要的属性:

  • LEO(Log End Offset):日志末端偏移,标识当前日志文件中下一条消息的偏移量 offset(也就是下一条消息的写入位置);
  • HW(High Watermark):标识了一个特定的消息偏移量 offset,消费者只能拉取到这个 offset 之前的消息,因其类似于木桶效应中短板决定水位高度,故取名为高水位。

所有高水位以下消息都是已经备份过的,消费者仅可消费这些已备份了的,对于任何一个副本分区而言,其 HW 的值都不会大于其 LEO 的值。

举个栗子,有一个日志文件如下图所示,其中有 10 条消息,第一条消息的 offset (LogStartOffset)为 0,最后一条消息的 offset 为 9,offset 为 10 的消息用虚线框表示,代表下一条待写入的消息。

在这里插入图片描述
该日志文件的 HW 为 6 ,表示消费者只能拉取到小于这个 offset 的消息,而 offset 为 6 的消息对消费者是不可见的;该日志文件的 LEO 为 10,相当于当前日志分区中最后一条消息的 offset 的值加 1。

ISR 与 LEO、HW 的关系

分区 ISR 集合中的每个副本都会维护自身的 LEO,而 ISR 集合中最小的 LEO 即为分区的 HW,对消费者而言只能消费 HW 之前的消息。

为了更好地理解 ISR 与 LEO、HW ,接下来通过一个栗子来说明三者之间的关系。如下图所示,为三个副本分区组成的 ISR,包含一个 Leader 和两个 Follower,此时 ISR 的 HW 和 LEO 都为 3。

在这里插入图片描述

右侧为生产者 Producer ,会发出消息写入到 Leader 分区中,然后 Follower 会向 Leader 发送拉取请求来进行消息同步。

在这里插入图片描述

同步过程中,不同的 Follower 的同步效率也不尽相同,如下图所示,Follower1 完全跟上了 Leader 而 Follower2 只同步了消息3。那么此时,Leader 副本的 LEO 为 5,Follower1 副本的 LEO 也为 5,而 Follower2 副本的 LEO 为 4,那么当前 ISR 的 HW 取最小的 LEO 值,此时消费者可以消费到 offset 为 0 至 3 之间的消息。

在这里插入图片描述
当所有 Follower 副本都成功的同步到 Leader 写入的消息之后,那么整个分区的 HW 和 LEO 也都变为了 5,此时消费者可以消费到 offset 为 0 至 4 之间的消息。

Kafka 为什么要设计 LEO 和 HW?

在上述分析中,我们知道 Kafka 的复制机制并不是完全的同步复制,也不是单纯的异步复制。同步复制是要求所有的 Follower 副本都复制完,这条消息才会被确认为已经成功提交,这种方式将会极大地影响同步性能。而在异步复制中,只要消息被写入到 Leader 副本中就会被确认为已经成功提交,那么这种情况下,如果所有 Follower 副本都没有完全复制完而落后于 Leader 副本,突然 Leader 出现故障或者宕机,那么将造成数据丢失。

而 Kafka 通过设计 ISR、LEO、HW 的方式,可以有效地权衡数据同步的性能与可靠性的关系。


最后

获取本文PDF版的方式,关注:Data跳动,回复:Kafka123。

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值