首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Kafka 消息存储与索引设计

Kafka 消息存储与索引设计

作者头像
张乘辉
发布于 2020-12-31 02:48:55
发布于 2020-12-31 02:48:55
1.6K00
举报
文章被收录于专栏:后端进阶后端进阶
运行总次数:0

消息中间件的性能好坏,它的消息存储的机制是衡量该性能的最重要指标之一,而 Kafka 具有高性能、高吞吐、低延时的特点,动不动可以上到几十上百万 TPS,离不开它优秀的消息存储设计。下面我按照自己的理解为大家讲解 Kafka 消息存储设计的那些事。

在 Kafka 的设计思想中,消息的存储文件被称作日志,我们 Java 后端绝大部分人谈到日志,一般会联想到项目通过 log4j 等日志框架输出的信息,而 Kafka 的消息日志类似于数据库中的提交记录,他们会按照时间顺序进行追加,Kafka 的消息也是严格按照时间顺序并已一定的格式写入日志文件中,有意思的是 Kafka 的消息不叫 Message,而是叫作 Record:

Kafka 将消息封装成一个个 Record,并以自定义的格式序列化成二进制字节数组进行保存:

如上图所示,消息严格按照顺序进行追加,一般来说,左边的消息存储时间都要小于右边的消息,需要注意的一点是,在 0.10.0.0 以后的版本中,Kafka 的消息体中增加了一个用于记录时间戳的字段,而这个字段可以有 Kafka Producer 端自定义,意味着客户端可以打乱日志中时间的顺序性。

Kafka 的消息存储会按照该主题的分区进行隔离保存,即每个分区都有属于自己的的日志,在 Kafka 中被称为分区日志(partition log),每条消息在发送前计算到被发往的分区中,broker 收到日志之后把该条消息写入对应分区的日志文件中:

以上简单介绍了 Kafka 的消息是如何追加存储的,那么在具体的存储文件中,日志的文件是怎么样的呢?

如果每个分区只存在一个日志文件,对于消息的过期清除和检索都是一个大难题,因此 Kafka 会将每个分区的日志文件继续细分成若干个日志文件,这些日志文件也称作日志段文件(log segment file),每个日志段文件都会伴随一个索引文件和时间戳索引文件,在 broker 所属节点打开对应分区日志的目录,可以看到相关文件:

每个日志段包含了 .log/.index/timeindex 三个文件,而且名字都是相同的。

1、log 文件

.log 后缀文件保存了 Kafka 消息的记录,而且每个 log 文件都有对应的消息记录范围,名字的数字代表了消息记录的初始位移值,并且随着消息数量的增多而增大,因此,每个新创建的分区一定会包含 0 的 log 文件。Kafka 文件名字使用了 20 位来标识位移,对于实际的生产环境已经足够用了。

每个 log 文件的默认大小为 1 GB,可以通过 log.segment.bytes 参数进行控制,每当 log 文件被填满后,Kafka 会自动创建一组新的日志文件和索引文件,也就是说日志段文件一旦被填满后,就不会再继续写入新消息,而是写到新的日志段文件中,而当前可被写入消息的日志段文件也称作当前日志段文件,它是一种特殊的日志段文件,它不会受到 Kafka 任何后台任务的影响,比如日志过期清除、日志 compaction 等任务。

2、索引文件

每个 log 文件都会包含两个索引文件,分别是 .index 和 .timeindex,在 Kafka 中它们分别被称为位移索引文件和时间戳索引文件,位移索引文件可根据消息的位移值快速地从查询到消息的物理文件位置,时间戳索引文件可根据时间戳查找到对应的位移信息。

Kafka 的索引文件按照稀疏索引文件的思想进行设计的,每个索引文件包含若干条索引项,之前在文章「kill -9 导致 Kakfa 重启失败的惨痛经历!」中有分析过。稀疏索引的核心即不会为每个记录都保存索引,而是写入一定的记录之后才会增加一个索引值,具体这个间隔有多大则通过 log.index.interval.bytes 参数进行控制,默认大小为 4 KB,意味着 Kafka 至少写入 4KB 消息数据之后,才会在索引文件中增加一个索引项。

需要注意的一点是,消息大小还会影响 Kakfa 索引的插入频率,假设每个消息大小均大于 4 KB,会导致每次追加消息的时候,都会伴随一次索引项的增加。因此 log.index.interval.bytes 也是 Kafka 调优一个重要参数值。

那么既然有了索引文件,Kafka 是如何根据索引文件进行快速检索的呢?由于索引文件也是按照消息的顺序性进行增加索引项的,位移索引文件按照位移顺序保存,而时间戳索引文件则按照时间顺序保存索引项,因此 Kafka 可以利用二分查找算法来搜索目标索引项,把时间复杂度降到了 O(lgN),大大减少了查找的时间。

每个日志段的索引文件可通过 log.index.size.max.bytes 参数控制,默认大小为 10 MB。

1)位移索引文件

位移索引文件的索引项结构如下:

可以看出,每个索引项的大小为 8 bytes,源码 kafka.log.OffsetIndex#entrySize = 8 限定了索引项的大小。

需要注意的是,索引文件大小必须是索引项的整数倍,假设 log.index.size.max.bytes = 500,则 Kafka 会创建一个大小为 496 bytes 的索引文件。

相对位移:保存于索引文件名字上面的起始位移的差值,假设一个索引文件为:00000000000000000100.index,那么起始位移值即 100,当存储位移为 150 的消息索引时,在索引文件中的相对位移则为 150 - 100 = 50,这么做的好处是使用 4 字节保存位移即可,可以节省非常多的磁盘空间。

文件物理位置:消息在 log 文件中保存的位置,也就是说 Kafka 可根据消息位移,通过位移索引文件快速找到消息在 log 文件中的物理位置,有了该物理位置的值,我们就可以快速地从 log 文件中找到对应的消息了。

下面我用图来表示 Kafka 是如何快速检索消息:

假设 Kafka 需要找出位移为 3550 的消息,那么 Kafka 首先会使用二分查找算法找到小于 3550 的最大索引项:[3528, 2310272],得到索引项之后,Kafka 会根据该索引项的文件物理位置在 log 文件中从位置 2310272 开始顺序查找,直至找到位移为 3550 的消息记录为止。

2)时间戳索引文件

Kafka 在 0.10.0.0 以后的版本当中,消息中增加了时间戳信息,为了满足用户需要根据时间戳查询消息记录,Kafka 增加了时间戳索引文件,时间戳索引文件的索引项结构如下:

可以看出,每个索引项的大小为 12 bytes,源码 kafka.log.TimeIndex#entrySize = 12 限定了索引项的大小。

同样地,时间戳索引文件大小也必须为索引项的整数倍大小,计算方式与位移索引文件相同。

下面我用图来表示 Kafka 是如何快速检索消息:

使用时间戳查找消息的流程与使用位移查找消息的流程的一些细节少有不同,下面我结合源码与例子,解释上图的流程:

kafka.log.LogSegment#findOffsetByTimestamp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def findOffsetByTimestamp(timestamp: Long, startingOffset: Long = baseOffset): Option[TimestampAndOffset] = {
  // Get the index entry with a timestamp less than or equal to the target timestamp
  val timestampOffset = timeIndex.lookup(timestamp)
  val position = offsetIndex.lookup(math.max(timestampOffset.offset, startingOffset)).position
  // Search the timestamp
  Option(log.searchForTimestamp(timestamp, position, startingOffset))
}

假设要查询时间戳为 1609087040523 附近的消息,从源码逻辑,根据二分算法找到时间戳索引项 [1609087040112, 5146],然后根据根据位移值从位移索引文件中找到小于 5146 位移的最大索引项[5046, 3111375]。

org.apache.kafka.common.record.FileRecords#searchForTimestamp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public TimestampAndOffset searchForTimestamp(long targetTimestamp, int startingPosition, long startingOffset) {
  for (RecordBatch batch : batchesFrom(startingPosition)) {
    if (batch.maxTimestamp() >= targetTimestamp) {
      // We found a message
      for (Record record : batch) {
        long timestamp = record.timestamp();
        if (timestamp >= targetTimestamp && record.offset() >= startingOffset)
          return new TimestampAndOffset(timestamp, record.offset(),
                                        maybeLeaderEpoch(batch.partitionLeaderEpoch()));
      }
    }
  }
  return null;
}

根据查到的索引项位移值 5046 开始查询,当消息时间戳最接近目标搜索的时间戳并且位移大于等于搜索起始位移时,则该消息即是满足该时间戳条件的消息。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 后端进阶 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
rsync+inotify实现远程实时同步
rsync,英文全称是remote synchronize,是一款实现远程同步功能的免费软件,它在同步文件的同时,可以保持原来文件的权限、时间、软硬链接等附加信息。 rsync提供了一个客户机和远程文件服务器的文件同步的快速方法,而且可以通过ssh方式来传输文件。甚至还可以实现只同步一个文件里有变化的内容部分,所以可以实现快速的同步备份数据。同时,rsync还可以实现同步本地数据、删除文件和目录的功能。
星哥玩云
2022/07/14
8000
rsync+inotify实现远程实时同步
大点干!早点散----------rsync+inotify实现远程实时同步
rsync是linux系统下的数据镜像备份工具,使用快速增量备份工具remote sync可以远程同步,可以在不同主机之间进行同步,可以实现全量备份与增量备份,保持链接和权限,且采用优化的同步算法,传输前执行压缩,因此非常适合用于架构集中式的备份或异地备份等应用。同时rsync支持本地复制,或者与其他ssh、rsync主机同步。
不吃小白菜
2020/09/15
7810
19 张图详解 Rsync 远程同步
从字面意思上,rsync 可以理解为 remote sync(远程同步),但它不仅可以远程同步数据(类似于 scp 命令),还可以本地同步数据(类似于 cp 命令)。不同于 cp 或 scp 的一点是,使用 rsync 命令备份数据时,不会直接覆盖以前的数据(如果数据已经存在),而是先判断已经存在的数据和新数据的差异,只有数据不同时才会把不相同的部分覆盖。
我的小碗汤
2023/03/20
7.3K0
19 张图详解 Rsync 远程同步
在CentOS7上配置rsync源服务器+inotify实时同步
rsync是一个开源的快速备份工具,可以再不同主机之间镜像同步整个目录树,支持增量备份,保持链接和权限,且采用优化的同步算法,再传输前执行压缩,因此非常适用于异地备份、镜像服务器等应用。
拓荒者
2019/03/11
1.1K0
在CentOS7上配置rsync源服务器+inotify实时同步
Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
Rsync 是一个开源的快速备份工具,是Linux和UNIX操作系统默认安装的组件之一,可在不同主机间镜像同步整个目录,并支持增量备份文件传输,保持链接和权限,采用优化的同步算法,传输前执行压缩,适用于异地备份,镜像服务器等应用。
杰哥的IT之旅
2020/06/18
2.1K0
配置rsync+inotify实现站点文件实时同步
rsync /etc/fstab /opt rsync -rl /etc/fstab /boot/grub /opt
星哥玩云
2022/07/14
1.1K0
配置inotify+rsync实时同步
对rsync服务及命令不熟悉的,可以参考博文通过rsync实现远程同步 另外本文也是基于“通过rsync实现远程同步”这篇的试验环境的。
星哥玩云
2022/07/28
7820
配置inotify+rsync实时同步
配置 inotify+rsync 实时同步
rsync 虽然可以实现快速备份,但是什么东西都不可能是十全十美的,作为计划任务备份,都是固定时间进行的,而且延迟明显、实时性差,当同步源长期不变化时,密集的定期任务是不必要的。 实时备份就不同了,一旦同步源出现变化,立即启动备份,只要同步源无变化,则不执行备份,但是他只能实现上传功能。 Linux内核提供了inotify通知接口,用来监控文件系统的各种变化情况,如文件存取、删除、移动、修改等。利用这个机制,可以非常方便地实现文件异动告警、增量备份,并针对目录或文件的变化及时作出响应。
小手冰凉
2019/09/10
1.2K0
rsync远程同步文件_ssh远程登录
一款快速增量备份工具Remote Sync,远程同步 支持本地复制,或者与其他SSH、rsync 主机同步 它名称里面的r指的是 remote,rsync 其实就是”远程同步”(remote sync)的意思。与其他文件传输工具(如 FTP 或 scp)不同,rsync 的最大特点是会检查发送方和接收方已有的文件,如果没有相当于新建则是全量备份,如果目标方已有一些文件,则用增量备份方式仅传输有变动的部分(默认规则是文件大小或修改时间有变动)。
全栈程序员站长
2022/11/04
2.5K0
rsync远程同步文件_ssh远程登录
CentOS下(rsync+inotify)监听式实现服务器间的备份实时同步
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011415782/article/details/78720072
泥豆芽儿 MT
2018/09/11
2.6K0
CentOS下(rsync+inotify)监听式实现服务器间的备份实时同步
Rsync远程同步
rsync是一款优秀的、快速的、多平台的本地或远程数据镜像同步备份工具。适用于Unix/Linux/Windows等多种平台。
星哥玩云
2022/07/03
1K0
inotify+rsync实现实时同步
惨绿少年
2017/12/27
1.8K0
inotify+rsync实现实时同步
rsync+inotify实现分布式集群部署
上一篇:Linux下使用ssh密钥实现无交互备份 上二篇:Linux下使用rsync实现文件备份 缘起 由于公司要对支付做压测,于是使用了公司的服务器搭建了一个简单的集群环境,但是各个节点分别部署确实有点麻烦,由此产生了一下想法,使用rsync+inotify同步部署集群项目,就是主节点项目变更会自动同步到其他集群节点上。 优点 使用rsyn工具和inotify机制相结合,可以实现触发式部署(实时同步),只要原始(主)位置的文档发生变幻,则立即启用增量推送操作,否则处于静态等待状态,这样以来,就避免了分布式
小柒2012
2018/04/13
1.4K0
rsync+inotify实现分布式集群部署
Linux下rsync+inotfy/sersync实现数据实时同步
导读:本文主要讲解了如何利用 rsync+inotfy/sersync 实现数据实时同步的操作过程和部分原理、参数。
开心分享
2020/08/11
1.4K0
Linux下rsync+inotfy/sersync实现数据实时同步
rsync+inotify实时同步
1.rsync 与传统的cp、tar备份方式相比,rsync具有安全性高、备份迅速、支持增量备份的优点,通过rsync可以解决对实时性要求不高的数据备份需求,例如定期的备份文件服务器数据到远端服务器,对本地磁盘定期做数据镜像等。 随着应用系统规模不断的扩大,对数据安全性和可靠性也提出了更高的要求,rsync在高端业务中也逐渐暴露出许多不足。首先,rsync实时同步时,需要扫描所有的文件进行比对,进行差量传输。如果文件数量打到了百万甚至千万量级,扫描所有的文件是非常耗时的,而且正在发生变化的往往是其中很少一部
用户1173509
2018/01/17
1.5K0
采用Rsync与Inotify实时同步文件目录
描述: Rsync(remote synchronize)是一个提供快速增量文件传输的开源实用程序, rsync是根据GNU通用公共许可证免费提供的,目前由Wayne Davison维护。
全栈工程师修炼指南
2022/09/28
3.5K0
采用Rsync与Inotify实时同步文件目录
文件同步rsync
rsync 远程同步 rsync(remote sync) 备份 完全备份 增量备份(差异备份) rsync 优点: 支持增量备份 选择性保持:符号链接,硬链接,文件属性,权限及时间等。 传输前执行压缩,适合于异地备份,镜像服务器等应用。 使用ssh作为传输端口,sftp,ssh,xshell 。 与scp区别: 当文件数据很大时候: scp 的效率太低,(scp是先统计信息,需要多少空间后,在复制) rsync 边复制,边比较,边统计 基础知识 端口:873 模式: 如果直接使用命令
若与
2018/04/25
4K0
文件同步rsync
使用 inotify 和 rsync 实现文件实时同步
在生产中有一种需求是,当目录下的文件数据发生变化时,就将数据备份到备份服务器上。实现这样的需求需要做到以下两点:
:Darwin
2023/07/05
2.1K0
rsync+inotify实现本地文件实时同步
sync官方网站: https://www.samba.org/ftp/rsync/rsync.html
斯文的程序
2019/11/07
2K0
Linux服务器使用rsync+inotify实现实时同步
rsync是linux系统下的数据镜像备份工具。使用快速增量备份工具Remote Sync可以远程同步,支持本地复制,或者与其他SSH、rsync主机同步。
西门呀在吹雪
2020/11/09
7.3K0
推荐阅读
相关推荐
rsync+inotify实现远程实时同步
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档