VictoriaMetrics 中文教程(08)VictoriaMetrics 的存储

本文解释 VictoriaMetrics 的存储结构、part、block、IndexDB、后台合并和 retentionPeriod 保留策略,帮助理解数据如何写入、查询、合并、清理以及如何为不同数据设置不同保留期。

作者 快猫运营团队

VictoriaMetrics

VictoriaMetrics 中文教程系列文章:

核心摘要

  • VictoriaMetrics 会先把写入数据短暂缓存在内存中,再周期性刷新到磁盘上的 part,这样可以兼顾写入性能和异常退出后的数据安全。
  • 磁盘数据按月份分区,目录位于 <-storageDataPath>/data/Small/YYYY_MM/ 等路径下,每个 part 包含元数据、压缩后的时间戳和值,以及用于查找的索引文件。
  • part 会在后台合并为更大的 part,合并可以减少文件数量、改善压缩率、提升查询效率,并处理去重、降采样和已删除时序的空间释放。
  • VictoriaMetrics 使用 TSID 作为内部主索引,同时通过倒排索引支持按指标名、标签名和标签值搜索时序。
  • 数据保留期由 -retentionPeriod 控制。开源版如果需要给不同数据设置不同保留期,通常用多套 VictoriaMetrics 实例加 vmauth 代理实现。

先理解几个存储术语

在阅读 VictoriaMetrics 存储机制时,最容易混淆的是 partblock、TSID 和 IndexDB:

  • part:VictoriaMetrics 存储数据的基本文件目录单位,可以位于内存或磁盘中,后续会被后台合并。
  • blockpart 内部更小的数据块,每个块最多包含 8K 个原始样本,并且这些样本属于同一条时间序列。
  • TSID:time series ID,VictoriaMetrics 内部用于识别时间序列的 ID,不暴露给客户端。
  • IndexDB:VictoriaMetrics 的索引库,用倒排索引把指标名、标签名、标签值映射到对应 TSID。

VictoriaMetrics 的数据写入和磁盘存储

VictoriaMetrics 将摄取的数据在内存中缓冲长达一秒钟。然后将缓冲的数据写入内存 parts,可以在查询期间搜索。内存中的 parts 会定期保存到磁盘,因此它们可以承受非正常关机,例如内存不足崩溃、硬件电源丢失或 SIGKILL 信号。可以使用 -inmemoryDataFlushInterval 命令行标志配置将内存数据刷新到磁盘的间隔(请注意,刷新间隔太短可能会显著增加磁盘 IO)。

内存中的 parts 被持久化到 <-storageDataPath>/data/Small/YYYY_MM/ 文件夹下,其中 YYYY_MM 是存储数据的月份分区。例如,2022_11 是从 2022 年 11 月开始的带有原始样本的 parts 的分区。每个分区目录都包含 parts.json 文件,该文件中存储了所有的 parts 目录。

每个 part 目录都包含具有以下字段的 metadata.json 文件:

  • RowsCount - 该 part 中存储的原始样本数量
  • BlocksCount - 存储在该 part 中的块数(请参阅下面有关块的详细信息)
  • MinTimestamp 和 MaxTimestamp - 存储在该 part 中的原始样本的最小和最大时间戳
  • MinDedupInterval - 应用于给定 part 的重复数据删除间隔

每个 part 由按 time series ID(又称 TSID)排序的块组成。每个块包含最多 8K 个原始样本,这些样本属于单个时间序列。每个块中的原始样本按时间戳排序。同一时间序列的块按第一个样本的时间戳排序。所有块的 timestamps 和 values 都以压缩形式存储在 part 目录下的单独文件中,也就是 timestamps.bin 和 values.bin。

part 目录还包含 index.bin 和 metaindex.bin 文件 - 这些文件包含用于快速块查找的索引,属于给定的 TSID 并覆盖给定的时间范围。

可以把这段机制概括成一句话:VictoriaMetrics 先按时间序列组织样本,再按块压缩存储,最后通过索引文件快速定位指定 TSID 在指定时间范围内的数据。

后台合并为什么重要

part 会定期在后台合并为更大的 part。后台合并具有以下优势:

  • 控制数据文件数量,使其不超过打开文件的限制
  • 提高数据压缩率,因为较大的 part 通常比较小的 part 压缩得更好
  • 提高查询速度,因为对较少数量的 part 的查询执行速度更快
  • 合并期间会执行各种后台维护任务,例如重复数据删除、降采样以及为已删除的时间序列释放磁盘空间

对使用者来说,后台合并不仅是内部优化,它还影响查询延迟、磁盘空间释放和异常数据删除后的最终落盘状态。如果磁盘空间不足导致合并受阻,查询会面对更多 part,整体开销会增加。

新添加的 part 有可能会成功出现在存储中,有可能会失败。新添加的 part 在完全写入并 fsync 到存储后,将原子地注册到相应分区下的 parts.json 文件中。由于这种算法,存储永远不会包含部分创建的 part,即使在将 part 写入磁盘的过程中发生硬件断电 - 这些未完整写入的 part 会在下次 VictoriaMetrics 启动时自动删除。

合并过程也是如此 - part 要么完全合并成一个新 part,要么合并失败,源部分保持不变。然而,由于硬件问题,无论 VictoriaMetrics 流程如何,磁盘上的数据都可能损坏。VictoriaMetrics 可以在数据块解压缩、解码或健全性检查期间检测损坏情况。但它无法修复损坏的数据。启动时无法加载的数据部分需要删除或从备份中恢复。这就是为什么建议定期进行备份。

VictoriaMetrics 不对存储的数据块使用校验和。原因参考这里

如果各部分的摘要大小超出可用磁盘空间,VictoriaMetrics 不会合并这些部分。这可以防止合并过程中出现潜在的磁盘空间不足错误。在可用磁盘空间不足的情况下,part 数量可能会随着时间的推移而显着增加。这会增加数据查询期间的开销,因为 VictoriaMetrics 每次请求都需要从更多 part 读取数据。这就是为什么建议在 -storageDataPath 命令行标志指向的目录下至少有 20% 的可用磁盘空间。

可以从下面两个仪表盘中查看存储的 merge 过程的信息:

索引库

VictoriaMetrics 通过 TSID(时间序列 ID)识别时间序列,并按 TSID 排序存储原始样本。因此,TSID 是主索引,可用于搜索和检索原始样本。但是,TSID 永远不会暴露给客户端,仅供内部使用。

相反,VictoriaMetrics 维护一个倒排索引,通过将这些值映射到相应的 TSID,可以按指标名称、标签名称和标签值搜索原始样本。

VictoriaMetrics 使用两种类型的倒排索引:

  • 全局索引。使用此索引的搜索将在整个保留期内执行。
  • 按日索引。此索引存储与全局索引类似的映射,但每个映射中还包括日期。这加快了较短时间范围内查询(通常只是最后一天)的数据检索速度。

当执行搜索查询时,VictoriaMetrics 会根据查询的时间范围决定使用哪个索引:

  • 如果搜索时间范围为 40 天或更短,则使用每日索引。
  • 全局索引用于时间范围大于 40 天的搜索查询。

在数据摄取期间将映射添加到索引:

  • 在全局索引中,每个映射每个保留期仅创建一次。
  • 按天的索引,则是每天创建一次。只要对应的某个日期里出现了相关的时序数据,这些时序数据的索引就会被添加到这个日期的索引中。

IndexDB 尊重保留期,一旦保留期结束,索引就会被删除。对于新的保留期,随着新样本的到来,索引会逐渐再次填充。

从查询视角看,IndexDB 的价值在于把用户熟悉的 Prometheus 标签选择器转换为内部 TSID 集合。标签基数越高、短期新增时间序列越多,索引压力也会越明显。

VictoriaMetrics 的数据保留

保留期使用 -retentionPeriod 命令行标志配置,该标志采用数字后跟时间单位字符 - h(小时)、d(天)、w(周)、y(年)。如果未指定时间单位,则假定为一个月(31 天)。例如,-retentionPeriod=3 表示数据将存储 3 个月(93 天),然后删除。默认保留期为一个月。最短保留期为 24 小时或 1 天。

数据按月划分在 <-storageDataPath>/data/{small,big} 文件夹内。配置保留期之外的数据分区将在新月的第一天删除。每个分区由一个或多个数据 part 组成。配置的保留期之外的数据 part 最终会在后台合并期间被删除。数据 part 所涵盖的时间范围不受保留期单位限制。一个数据 part 可以涵盖数小时或数天的数据。因此,只有完全超出配置的保留期时,才能删除数据 part

给定 -retentionPeriod 的最大磁盘空间使用量为 (-retentionPeriod + 1) 个月。例如,如果 -retentionPeriod 设置为 1,则 1 月份的数据将在 3 月 1 日删除。延长现有数据的 -retentionPeriod 是安全的。如果将 -retentionPeriod 设置为比以前更低的值,则配置期限之外的数据最终将被删除。

VictoriaMetrics 不支持无限期保留,但您可以指定任意长的保留期限,例如 -retentionPeriod=100y

如果想让不同的数据使用不同的保留期,有两个办法:

  • 使用商业版,商业版支持在一个实例上配置不同的时序数据不同的保留期。
  • 开源版的话,使用多个 VictoriaMetrics 实例,每个实例配置不同的保留期。然后在前面使用 vmauth 做代理。

常见问题

VictoriaMetrics 为什么需要至少 20% 可用磁盘空间?

因为后台合并需要额外的磁盘空间。如果 <-storageDataPath> 目录下可用空间不足,VictoriaMetrics 不会继续合并相关 part,从而避免合并过程中出现磁盘空间不足错误。副作用是 part 数量会增加,查询时需要读取更多文件。

删除数据后,磁盘空间为什么没有立刻下降?

本文介绍的存储机制决定了空间释放依赖后台合并。删除标记产生后,相关数据通常要等到后续 part 合并时才会从磁盘上真正释放。

开源版可以给不同业务配置不同保留期吗?

单个开源版实例不适合在同一实例内给不同数据设置不同保留期。更常见的做法是部署多个 VictoriaMetrics 实例,每个实例配置自己的 -retentionPeriod,前面再用 vmauth 做代理。

总结

VictoriaMetrics 的存储机制可以分为四层理解:内存缓冲和刷新、磁盘 partblock 组织、IndexDB 索引检索、按保留期清理历史数据。对使用者来说,最重要的运维结论是:关注磁盘剩余空间、理解后台合并对性能和空间释放的影响、按业务需求规划保留期,并在需要差异化保留时选择商业版能力或多实例方案。

联系我们交流

延伸路径

继续看解决方案和产品对比

如果你正在做监控、可观测性或故障定位相关选型,建议从解决方案和产品对比继续往下看。

快猫星云 联系方式 快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云