Kafka持久化机制
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kafka持久化机制相关的知识,希望对你有一定的参考价值。
参考技术A Kakfa 依赖文件系统来存储和缓存消息。对于硬盘的传统观念是硬盘总是很慢,基于文件系统的架构能否提供优异的性能?实际上硬盘的快慢完全取决于使用方式。为了提高性能,现代操作系统往往使用内存作为磁盘的缓存,所有的磁盘读写操作都会经过这个缓存,所以如果程序在线程中缓存了一份数据,实际在操作系统的缓存中还有一份,这等于存了两份数据。
同时 Kafka 基于 JVM 内存有以下缺点:
实际上磁盘线性写入的性能远远大于任意位置写的性能,线性读写由操作系统进行了大量优化(read-ahead、write-behind 等技术),甚至比随机的内存读写更快。所以与常见的数据缓存在内存中然后刷到硬盘的设计不同,Kafka 直接将数据写到了文件系统的日志中:
这样实现的好处:
一个 Topic 被分成多 Partition,每个 Partition 在存储层面是一个 append-only 日志文件,属于一个 Partition 的消息都会被直接追加到日志文件的尾部,每条消息在文件中的位置称为 offset(偏移量)。
日志文件由“日志条目(log entries)”序列组成,每一个日志条目包含一个4字节整型数(值为N),其后跟N个字节的消息体。每条消息都有一个当前 Partition 下唯一的64字节的 offset,标识这条消息的起始位置。消息格式如下:
Kafka 持久化日志视图
日志文件允许串行附加,并且总是附加到最后一个文件。当文件达到配置指定的大小( log.segment.bytes = 1073741824 (bytes))时,就会被滚动到一个新文件中(每个文件称为一个 segment file)。日志有两个配置参数:M,强制操作系统将文件刷新到磁盘之前写入的消息数;S,强制操作系统将文件刷新到磁盘之前的时间(秒)。在系统崩溃的情况下,最多会丢失M条消息或S秒的数据。
通过给出消息的偏移量(offset)和最大块大小(S)来读取数据。返回一个缓冲区为S大小的消息迭代器,S应该大于任何单个消息的大小,如果消息异常大,则可以多次重试读取,每次都将缓冲区大小加倍,直到成功读取消息为止。可以指定最大消息大小和缓冲区大小,以使服务器拒绝大于某个大小的消息。读取缓冲区可能以部分消息结束,这很容易被大小分隔检测到。
读取指定偏移量的数据时,需要首先找到存储数据的 segment file,由全局偏移量计算 segment file 中的偏移量,然后从此位置开始读取。
消息数据随着 segment file 一起被删除。Log manager 允许可插拔的删除策略来选择哪些文件符合删除条件。当前策略为删除修改时间超过 N 天前的任何日志,或者是保留最近的 N GB 的数据。
为了避免在删除时阻塞读操作,采用了 copy-on-write 技术:删除操作进行时,读取操作的二分查找功能实际是在一个静态的快照副本上进行的。
上面提到日志文件非由一个文件构成,而是分成多个 segment(文件达到一定大小时进行滚动),每个 segment 名为该 segment 第一条消息的 offset 和 ".kafka" 组成。另外会有一个索引文件,标明了每个 segment 下包含的日志条目的 offset 范围。
有了索引文件,消费者可以从 Kafka 的任意可用偏移量位置开始读取消息。索引也被分成片段,所以在删除消息时,也可以删除相应的索引。Kafka 不维护索引的校验和,如果索引出现损坏,Kafka 会通过重新读取消息来重新生成索引。
以上是关于Kafka持久化机制的主要内容,如果未能解决你的问题,请参考以下文章