
VictoriaMetrics 中文教程系列文章:
- VictoriaMetrics 中文教程(01)简介
- VictoriaMetrics 中文教程(02)安装
- VictoriaMetrics 中文教程(03)如何配置 Prometheus 使其把数据远程写入 VictoriaMetrics
- VictoriaMetrics 中文教程(04)对接 Grafana 同时介绍 vmui
- VictoriaMetrics 中文教程(05)对接各类监控数据采集器
- VictoriaMetrics 中文教程(06)容量规划
- VictoriaMetrics 中文教程(07)高可用(High availability)方案
核心摘要
- VictoriaMetrics 会先把写入数据短暂缓存在内存中,再周期性刷新到磁盘上的
part,这样可以兼顾写入性能和异常退出后的数据安全。 - 磁盘数据按月份分区,目录位于
<-storageDataPath>/data/Small/YYYY_MM/等路径下,每个part包含元数据、压缩后的时间戳和值,以及用于查找的索引文件。 part会在后台合并为更大的part,合并可以减少文件数量、改善压缩率、提升查询效率,并处理去重、降采样和已删除时序的空间释放。- VictoriaMetrics 使用 TSID 作为内部主索引,同时通过倒排索引支持按指标名、标签名和标签值搜索时序。
- 数据保留期由
-retentionPeriod控制。开源版如果需要给不同数据设置不同保留期,通常用多套 VictoriaMetrics 实例加 vmauth 代理实现。
先理解几个存储术语
在阅读 VictoriaMetrics 存储机制时,最容易混淆的是 part、block、TSID 和 IndexDB:
part:VictoriaMetrics 存储数据的基本文件目录单位,可以位于内存或磁盘中,后续会被后台合并。block:part内部更小的数据块,每个块最多包含 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 的存储机制可以分为四层理解:内存缓冲和刷新、磁盘 part 与 block 组织、IndexDB 索引检索、按保留期清理历史数据。对使用者来说,最重要的运维结论是:关注磁盘剩余空间、理解后台合并对性能和空间释放的影响、按业务需求规划保留期,并在需要差异化保留时选择商业版能力或多实例方案。
