Kafka 分区
关于 Kafka 分区
- 每一个分区都是一个有序、不可变的消息序列,后续新来的消息会源源不断、持续追加到分区的后面,这相当于一种结构化的提交日志(类似于Git的提交日志)
- 分区中的每一条消息都会被分配一个连续的id 值(即 offset), 该值用于唯一标识分区中的每一条消息。
- 分区中的消息是存储到日志中的,而且同一个分区中的消息数据是按照发送顺序严格有序的。分区在逻辑上对应的日志,但生产者将消息写入分区中时,
实际上写到分区所对应的日志当中。而日志可以看作是一种逻辑上的概念,它对应于磁盘上的一个目录。一个日志文件由多个 Segment(段)来构成,每个 Segment 对应于一个索引文件与一个日志文件。
- 借助于分区我们可以 Kafka 的水平拓展。对于一台机器来说。无论是物理还是虚拟机,其运行能力总归是有上限的。当一台机器到达其能力上限时
就无法再拓展了,即垂直拓展能力总是受到硬件制约的。通过使用分区,我们可以将一个主题的消息分散到不同的 Kafka Server(这里需要使用Kafka集群) 这样当机器能力不足时,我们只需要添加机器就可以了,在新的机器上创建新的分区,这样理论上可以实现无限的水平拓展能力。
- 分区还可以实现并行处理能力,向一个主题所发送的消息发送给消息的不同分区中,由多个分区进行接收和处理,
Segment(段)
- 一个分区(partition)是由一系列有序、不可编的消息所构成。一个partition 中的消息数量可能会非常多,因此显然不能将所有消息都保存到一个文件当中
因此,类似于 log4j 的 rolling log, 当partition 中的消息数量增长到一定程度过后,消息文件就会进行切割,新的消息会写入到一个新的文件当中, 当新的文件增长到一定程度后,新的消息又会写入到另一个新的文件中,以此类推;这个一个个新的数据文件我们就称为segment(段)。
- 因此,partition 在物理上是由一个或者多个segment 所构成的。每个segment 中则保存了真实的消息数据。
partition 与 segment 之间的关系
- 每一个partition 都相当于一个大型的文件被分配到多个大小相等的segment 数据文件中,每个segment 中的消息数量未必相等(这与消息大小有着密切的关系,
不同的消息所占据的磁盘空间显然是不一样的),这个特点使得老的 segment 很容易被删掉,有助于提升磁盘的效率。
- 每一个partition 只需要支持顺序读写即可,segment 文件的生命周期是由 Kafka Server 的配置参数所决定,比如说,server.properties 中参数项
log.retention.hours=168 就表示7天后会删除老的 segment 文件。
关于分区目录中的4个文件的含义与其作用
- 00000000000000000000.index: 它是一个segment 文件的索引文件,它接下来我们要介绍00000000000000000000.log数据文件是成对出现的,后缀
为.index 的就表示这个是一个索引文件。
- 00000000000000000000.log: 它的segment文件的数据文件, 用于存储实际的消息。该文件时二进制格式的。segment 文件的命名规则是 partition
全局的第一个segment从0开始,后续每个segment 文件名为上一个segment 文件最有一条消息的offset 值。没有数字则用0来填充。
- 00000000000000000000.timeindex: 该文件时一个基于消息日期的索引文件,主要用途是在一些根据日期或事件来寻找消息的场景下使用,此外在基于
日期的日志 rolling 或是基于事件的日志保留策略等情况下也会使用。实际上,该文件是在Kafka 新版本中才增加的,老版本Kafka 没有该文件的。 它堆 .index 文件的有益补充。.index 文件是基于偏移量的索引嗯呢建,而*.timeindex 则是基于时间戳的索引文件。
- leader-epoch-checkpoint: 是leader 的缓存文件,实际上,它是与Kafka 的HW(High Water)与LEO(Log End Offset)相关的重要文件。
分区和主题
- 分区: 每个主题可以划分多个分区(每个主题都至少会有一个分区,在之前的实例中,我们创建主题时所使用的桉树 --partitions 即表示所创建的主题的
分区数),当时指定值为1 )在同一主题下的不同分区包含的消息是不同的。每个消息都被添加到分区中是,都会被添加一个偏移量(offset), 它是消息在所在 分区中唯一的编号,Kafka 是通过offset 来确保消息在一个分区内的顺序。offset 的顺序性。并不跨越分区,这意味着Kafka只会确保在同一个分区内的消息是有序 的,但是同一个主题的多个分区内的消息,Kafka 并不会保证其顺序性。
- 从上图可以看到, 消息在每个分区中是严格有序的 ,而不同分区之间的消息顺序则是不保证顺序
- 基于这样的设计策略,Kafka 的性能并不会随着分区中消息的增多而产损耗, 因此存储较长时间的数据也不会导致什么问题.
- Kafka 的消息记录是保存在磁盘上的,通过为每个消息分配一个offset , 即可以很好的确保同一分区中消息的顺序性,另外。
Kafka 中的消息在磁盘上是有一定的保存时间的,在这个时间内,消息会存储在磁盘;当过了这个时间,消息会被丢掉,从而释放 磁盘空间。该参数位于 server.properties 默认为:log.retention.hours=168。 即消息默认会保留7天;当然,你可以根据实际情况来自由修改时间, 修改后重启 Kafka Server 即可生效。
- 分区与主题的关系
- 可以看到,每个消息在同一个分区中都有唯一的一个偏移量 (offset)
- 分区是Kafka 实现高吞吐量的一个重要手段,特别是在 Kafka 集群环境下,一个主题的消息会分布在不同的 Kafka Server 上
实现了分布式的消息存储,特别是搭配在Kafka 的副本的配置效果更佳。