Grafana Mimir 压实器
压实器通过合并块来提高查询性能并减少长期存储使用量。
压实器是负责以下功能的组件:
- 将给定租户的多个块压缩成一个经过优化的更大块。这可以对块进行去重并减小索引大小,从而降低存储成本。查询更少的块速度更快,因此它也提高了查询速度。
- 保持每个租户的桶索引最新。桶索引由 Querier、Store-gateway 和 Ruler 使用,用于发现存储中的新块和已删除块。
- 删除不再处于可配置保留期内的块。
压实器是无状态的。
压实工作原理
压实按租户进行。
压实器按可配置的固定间隔运行。
垂直压实将 Ingester 为同一时间范围(默认为 2 小时)上传的给定租户的所有块合并成一个块。它还会对由于复制而最初写入 N 个块的样本进行去重。垂直压实将单个时间范围内的块数量从 Ingester 数量减少到每个租户一个块。
水平压实在垂直压实后触发。它将几个相邻时间范围的块压缩成一个更大的块。水平压实后,相关块块的总大小不会改变。水平压实可以显著减小 Store-gateway 保存在内存中的索引和索引头的大小。
扩展
可以针对拥有大型租户的集群调整压实。配置指定了压实器在按租户进行压实时的垂直和水平扩展方式。
- 垂直扩展
设置-compactor.compaction-concurrency
配置单个压实器实例中运行的最大并发压实数。每次压实使用一个 CPU 核心。 - 水平扩展
默认情况下,租户块可以由任何 Grafana Mimir 压实器进行压实。当您通过将-compactor.compactor-tenant-shard-size
(或其相应的 YAML 配置选项)设置为大于0
且小于可用压实器数量的值来启用压实器洗牌分片时,只有指定数量的压实器才有资格对给定租户的块进行压实。
压实算法
Mimir 使用一种复杂的压实算法,称为拆分合并(split-and-merge)。
根据设计,拆分合并算法克服了时间序列数据库 (TSDB) 索引的限制,并且避免了在任何压实阶段已压实块对非常大型的租户无限增长的情况。
此压实策略是一个两阶段过程:拆分和合并。默认配置禁用拆分阶段。
对于拆分阶段,第一个压实级别(例如 2h
),压实器将所有源块划分为 N (-compactor.split-groups
) 组。对于每组,压实器对块进行压实,但它不生成单个结果块,而是输出 M (-compactor.split-and-merge-shards
) 个块,称为拆分块。每个拆分块仅包含属于 M 个分片中给定分片的一部分时间序列。在拆分阶段结束时,压实器会生成 N * M 个块,并在块的 meta.json
文件中包含对其相应分片的引用。
压实器合并每个分片的拆分块。这会对给定分片的所有 N 个拆分块进行压实。合并将块的数量从 N * M 减少到 M。对于给定的压实时间范围,每个 M 个分片都会有一个已压实块。
然后,合并在其他配置的压实时间范围(例如 12h 和 24h)上运行。它会对属于同一分片的块进行压实。
此策略适用于拥有大型租户的集群。分片数量 M 可以使用 -compactor.split-and-merge-shards
按租户配置,并且可以根据每个租户的时间序列数量进行调整。租户的时间序列越多,您可以增加配置的分片数量。这样做可以提高压实的并行性,并控制每个分片的已压实块大小。我们建议每 800 万活跃时间序列使用 1 个分片。例如,对于拥有 1 亿活跃时间序列的租户,大约使用 12 个分片。请使用偶数作为数量。
拆分组的数量 N 也可以使用 -compactor.split-groups
选项按租户进行调整。增加此值可在拆分阶段产生更多块数量较少的压实作业。这使得多个压实器可以处理这些作业,并更快地完成拆分阶段。但是,增加此值也会在拆分阶段生成更多中间块,这些块只会在稍后的合并阶段减少。
如果在压实期间 -compactor.split-and-merge-shards
的配置发生变化,则此变化仅影响尚未拆分的块的压实。已拆分的块在合并时将使用原始配置。原始配置存储在每个拆分块的 meta.json
中。
拆分和合并可以水平扩展。不冲突且不重叠的作业将并行执行。
压实器分片
压实器对来自单个租户或多个租户的压实作业进行分片。单个租户的压实可以拆分并由多个压实器实例处理。
无论压实器池是增长还是缩小,租户和作业都会在可用的压实器实例之间重新分片,无需任何手动干预。
压实器分片使用哈希环。启动时,压实器生成随机令牌并注册到压实器哈希环。运行时,它会按照 -compactor.compaction-interval
定义的每个间隔定期扫描存储桶,以发现存储中的租户列表,并为哈希与哈希环中分配给实例本身的令牌范围匹配的每个租户压实块。
要配置压实器的哈希环,请参阅配置哈希环。
启动时等待稳定的哈希环
集群冷启动或同时增加两个或更多压实器实例可能导致每个新的压实器实例在稍有不同的时间启动。然后,每个压实器根据哈希环的不同状态运行其第一次压实。这并非错误条件,但可能效率低下,因为多个压实器实例可能几乎同时开始压实同一个租户。
为了缓解此问题,可以将压实器配置为在启动时等待稳定的哈希环。如果在至少 -compactor.ring.wait-stability-min-duration
时间内没有实例添加到或从哈希环中移除,则认为环是稳定的。压实器将等待的最长时间由标志 -compactor.ring.wait-stability-max-duration
(或相应的 YAML 配置选项)控制。一旦压实器完成等待,无论是由于环稳定还是达到最大等待时间,它都将正常启动。
-compactor.ring.wait-stability-min-duration
的默认值为零,表示禁用等待环稳定。
压实作业顺序
压实器允许通过 -compactor.compaction-jobs-order
标志(或其相应的 YAML 配置选项)配置压实作业顺序。配置的顺序定义了应首先执行哪些压实作业。支持的 -compactor.compaction-jobs-order
值如下:
smallest-range-oldest-blocks-first
(默认)此顺序优先处理最小范围、最旧的块。
例如,对于压实范围
2h, 12h, 24h
,压实器会先压实 2h 范围的块,并在其中优先处理最旧的块。一旦 2h 范围内的所有块都被压实,它会移至 12h 范围,最后是 24h 范围。所有拆分作业都会被移至工作队列的前面,因为完成给定时间范围内的所有拆分作业可以解锁合并作业。
newest-blocks-first
此顺序优先处理最新的时间范围,无论其压实级别如何。
例如,对于压实范围
2h, 12h, 24h
,压实器会先压实最新的块(直到 24h 范围),然后移至较旧的块。此策略偏好最新的块,假设它们被查询的频率最高。
块删除
成功压实后,原始块会从存储中删除。块删除并非立即发生;它遵循一个两步过程:
- 原始块被标记为待删除;这是软删除
- 一旦块被标记为待删除的时间超过可配置的
-compactor.deletion-delay
,该块就会从存储中删除;这是硬删除
压实器负责标记块和硬删除。软删除基于存储在存储桶中块位置内的小型 deletion-mark.json
文件。
软删除机制让 Querier、Ruler 和 Store-gateway 有时间在原始块被删除之前发现新的已压实块。如果这些原始块立即被硬删除,涉及已压实块的一些查询可能会暂时失败或返回部分结果。
块保留
压实器负责强制执行存储保留,从长期存储中删除包含早于配置保留期样本的块。默认情况下禁用存储保留,除非您明确配置保留期,否则不会从长期存储中删除任何数据。
有关更多信息,请参阅配置指标存储保留。
压实器临时存储卷
每个压实器使用挂载在 -compactor.data-dir
的存储设备来临时存储:
- 从对象存储下载的用作压实输入的 文件
- 压实器生成的将上传到对象存储的 块文件
注意
虽然压实器是无状态服务,但建议您将其临时文件存储在非根卷的其他位置。这可以避免与系统上运行的其他工作负载发生 I/O 争用。常见的卷类型包括本地 SSD 或云提供商的块存储服务。
在 Kubernetes 中,将压实器作为 StatefulSet 运行,以便每个 Pod 都有一个专用卷。
压实器磁盘利用率
大型租户可能需要大量磁盘空间。假设 max_compaction_range_blocks_size
是最大租户在最长 -compactor.block-ranges
周期内的总块大小,则估算所需最小磁盘空间的表达式是:
compactor.compaction-concurrency * max_compaction_range_blocks_size * 2
另外,假设最大的 -compactor.block-ranges
是 24h
(默认),您可以估算每 1000 万最大租户拥有的活跃时间序列需要 150GB 磁盘空间。例如,如果您的最大租户有 3000 万活跃时间序列,且 -compactor.compaction-concurrency=1
,我们建议至少有 450GB 可用磁盘空间。
压实器配置
有关压实相关配置的详细信息,请参阅压实器块部分和限制块部分。
Alertmanager 和 Ruler 组件也可以使用对象存储来存储其配置以及用户上传的规则。在这种情况下,应创建一个单独的存储桶来存储 Alertmanager 配置和规则:在 Ruler/Alertmanager 和块之间使用同一个存储桶会与压实器产生问题。