Kafka 的存储机制主要涉及以下几个方面:
主题与分区
Kafka 中的数据以主题(Topic)为单位进行组织,每个主题可以分为多个分区(Partition)。分区是数据存储和读写的基本单元,每个分区在物理上对应一个文件夹,文件夹内包含多个数据文件和索引文件。
数据文件
日志段:每个分区由多个日志段(Log Segment)组成,日志段是 Kafka 存储数据的基本单位。每个日志段包含一个数据文件(.log)和两个索引文件,分别是偏移量索引文件(.index)和时间戳索引文件(.timeindex)。数据文件以追加的方式顺序写入消息,当文件大小达到一定阈值或时间间隔时,会创建新的日志段。
消息格式:消息在数据文件中以二进制格式存储,每个消息包含消息头和消息体。消息头包含消息的元数据,如消息的偏移量、时间戳、键值对的长度等;消息体则是实际的消息内容。
索引文件
偏移量索引:偏移量索引文件记录了消息的偏移量与数据文件中物理位置的映射关系。它采用稀疏索引的方式,每隔一定数量的消息才会在索引文件中记录一条索引项,通过这种方式可以快速定位到消息在数据文件中的大致位置,然后再进行顺序查找,提高消息的读取效率。
时间戳索引:时间戳索引文件记录了消息的时间戳与偏移量的映射关系。它可以根据时间戳快速定位到某个时间范围内的消息偏移量,进而通过偏移量索引找到消息在数据文件中的位置,方便按照时间进行消息的查询和消费。
存储流程
消息写入:生产者将消息发送到 Kafka 集群,Kafka 根据主题和分区策略将消息分配到对应的分区。然后,消息会被追加到该分区的当前日志段的数据文件中。同时,更新偏移量索引文件和时间戳索引文件,记录消息的偏移量和时间戳等信息。
消息读取:消费者从 Kafka 集群拉取消息时,根据指定的主题、分区和偏移量,先从偏移量索引文件中查找消息在数据文件中的位置,然后从数据文件中读取消息内容。如果是按照时间进行查询,则先从时间戳索引文件中找到对应的偏移量,再通过偏移量索引进行消息读取。
存储优化
顺序读写:Kafka 通过将消息顺序写入数据文件,充分利用了磁盘的顺序读写特性,大大提高了读写性能。同时,在消息读取时也尽量保持顺序读取,减少磁盘寻道时间,提高读取效率。
零拷贝技术:Kafka 在消息传输过程中采用了零拷贝技术,避免了数据在用户空间和内核空间之间的多次拷贝,减少了 CPU 开销和内存占用,提高了消息的传输效率。