存储

Prometheus 包含一个本地磁盘上的时间序列数据库,但也可选地集成了远程存储系统。

本地存储

Prometheus 的本地时间序列数据库以自定义的、高效的格式将数据存储在本地存储上。

磁盘布局

采集的样本被分组为两个小时的块。每个两小时块包含一个目录,其中有一个 chunks 子目录,包含该时间窗口的所有时间序列样本,还有一个元数据文件和一个索引文件(将指标名称和标签索引到 chunks 目录中的时间序列)。chunks 目录中的样本默认被分组到一个或多个最大 512MB 的段文件中。当通过 API 删除时间序列时,删除记录存储在单独的墓碑文件中(而不是立即从 chunk 段中删除数据)。

当前传入样本块保存在内存中,未完全持久化。通过预写日志 (WAL) 确保其免受崩溃影响,该日志可在 Prometheus 服务器重启时回放。预写日志文件存储在 wal 目录中,分为 128MB 的段。这些文件包含尚未压缩的原始数据;因此它们比常规块文件大得多。Prometheus 将至少保留三个预写日志文件。高流量服务器可能会保留超过三个 WAL 文件,以保留至少两小时的原始数据。

Prometheus 服务器的数据目录看起来像这样

./data
├── 01BKGV7JBM69T2G1BGBGM6KB12
│   └── meta.json
├── 01BKGTZQ1SYQJTR4PB43C8PD98
│   ├── chunks
│   │   └── 000001
│   ├── tombstones
│   ├── index
│   └── meta.json
├── 01BKGTZQ1HHWHV8FBJXW1Y3W0K
│   └── meta.json
├── 01BKGV7JC0RY8A6MACW02A2PJD
│   ├── chunks
│   │   └── 000001
│   ├── tombstones
│   ├── index
│   └── meta.json
├── chunks_head
│   └── 000001
└── wal
    ├── 000000002
    └── checkpoint.00000001
        └── 00000000

请注意,本地存储的一个限制是它不是集群或复制的。因此,面对磁盘或节点故障时,它无法任意扩展或保证持久性,应该像管理任何其他单节点数据库一样进行管理。

建议使用快照进行备份。没有快照的备份存在丢失自上次 WAL 同步(通常每两小时发生一次)以来记录的数据的风险。通过适当的架构设计,可以在本地存储中保留多年的数据。

或者,可以通过远程读/写 API 使用外部存储。这些系统在持久性、性能和效率方面差异很大,需要仔细评估。

有关文件格式的更多详细信息,请参阅TSDB 格式

压缩

最初的两个小时的块最终会在后台被压缩成更长的块。

压缩会创建更大的块,包含跨越保留时间最多 10% 或 31 天的数据,取两者中较小的一个。

操作方面

Prometheus 有几个用于配置本地存储的标志。最重要的包括

  • --storage.tsdb.path: Prometheus 写入数据库的位置。默认为 data/
  • --storage.tsdb.retention.time: 在存储中保留样本的时间。如果既未设置此标志,也未设置 storage.tsdb.retention.size,则保留时间默认为 15d。支持的单位:y, w, d, h, m, s, ms。
  • --storage.tsdb.retention.size: 保留的存储块的最大字节数。将首先删除最旧的数据。默认为 0 或禁用。支持的单位:B, KB, MB, GB, TB, PB, EB。例如:“512MB”。基于 2 的幂,因此 1KB 是 1024B。虽然 WAL 和内存映射的 chunk 被计入总大小,但只有持久化块会被删除以遵守此保留策略。因此,磁盘的最低要求是 wal 目录(WAL 和 Checkpoint)和 chunks_head 目录(内存映射的 Head chunks) combined 所占用的峰值空间(每 2 小时达到峰值)。
  • --storage.tsdb.wal-compression: 启用预写日志 (WAL) 的压缩。根据您的数据,您可以期望 WAL 大小减半,而额外的 CPU 负载很少。此标志在 2.11.0 中引入,并在 2.20.0 中默认启用。请注意,一旦启用,将 Prometheus 降级到 2.11.0 以下的版本将需要删除 WAL。

Prometheus 平均每个样本只存储 1-2 字节。因此,为了规划 Prometheus 服务器的容量,您可以使用粗略的公式

needed_disk_space = retention_time_seconds * ingested_samples_per_second * bytes_per_sample

要降低采集样本的速率,您可以减少抓取的时间序列数量(更少的目标或每个目标更少的时间序列),或者增加抓取间隔。然而,由于序列内样本的压缩,减少序列数量可能更有效。

如果您的本地存储损坏到 Prometheus 无法启动的地步,建议备份存储目录并从备份中恢复损坏的块目录。如果您没有备份,最后的办法是删除损坏的文件。例如,您可以尝试删除单个块目录或预写日志 (wal) 文件。请注意,这意味着将丢失这些块或 wal 覆盖的时间范围内的数据。

注意: Prometheus 的本地存储不支持非 POSIX 兼容的文件系统,因为可能会发生不可恢复的损坏。不支持 NFS 文件系统(包括 AWS 的 EFS)。NFS 可能兼容 POSIX,但大多数实现不兼容。强烈建议使用本地文件系统以提高可靠性。

如果同时指定了时间和大小保留策略,则以先触发的为准。

过期块的清理在后台进行。清理过期块可能需要长达两个小时。块必须完全过期后才会被删除。

合理设置保留大小

如果您正在使用 storage.tsdb.retention.size 设置大小限制,您需要考虑相对于您为 Prometheus 分配的存储空间来合理设置此值。明智的做法是减小保留大小以提供缓冲区,确保在分配给 Prometheus 的存储空间满之前删除旧条目。

目前,我们建议将保留大小最多设置为您分配给 Prometheus 的磁盘空间的 80-85%。这增加了在达到任何磁盘限制之前移除旧条目的可能性。

远程存储集成

Prometheus 的本地存储受限于单个节点的扩展性和持久性。Prometheus 没有尝试在其自身解决集群存储问题,而是提供了一组接口,允许与远程存储系统集成。

概览

Prometheus 通过四种方式与远程存储系统集成

Remote read and write architecture

远程读写协议都使用基于 HTTP 的 snappy 压缩的 protocol buffer 编码。读取协议尚未被视为稳定 API。

写入协议有1.0 版本的稳定规范2.0 版本的实验性规范,两者都受 Prometheus 服务器支持。

有关在 Prometheus 中作为客户端配置远程存储集成的详细信息,请参阅 Prometheus 配置文档的远程写入远程读取部分。

请注意,在读取路径上,Prometheus 只从远程端获取一组标签选择器和时间范围的原始时间序列数据。原始数据上的所有 PromQL 求值仍然在 Prometheus 自身中进行。这意味着远程读取查询有一定的可伸缩性限制,因为所有必要的数据首先需要加载到进行查询的 Prometheus 服务器中,然后在此处处理。然而,目前完全分布式地求值 PromQL 被认为是不可行的。

Prometheus 也支持这两种协议。可以通过设置 --web.enable-remote-write-receiver 命令行标志来启用内置的远程写入接收器。启用后,远程写入接收器端点是 /api/v1/write。远程读取端点可在 /api/v1/read 获取。

现有集成

要了解更多关于与远程存储系统的现有集成,请参阅集成文档

从 OpenMetrics 格式回填

概览

如果用户希望从 OpenMetrics 格式的数据创建块到 TSDB 中,他们可以使用回填功能。但是,他们应该小心注意,回填过去 3 小时(当前头部块)的数据是不安全的,因为这个时间范围可能与 Prometheus 仍在修改的当前头部块重叠。回填将创建新的 TSDB 块,每个块包含两小时的指标数据。这限制了块创建的内存需求。将两小时块压缩成更大块的操作随后由 Prometheus 服务器自身完成。

典型的用例是将指标数据从不同的监控系统或时间序列数据库迁移到 Prometheus。为此,用户必须首先将源数据转换为 OpenMetrics 格式,这是如下所述的回填的输入格式。

请注意,此过程不支持原生直方图和陈旧标记,因为它们无法在 OpenMetrics 格式中表示。

用法

回填可以通过 Promtool 命令行使用。Promtool 会将块写入一个目录。默认情况下,输出目录是 ./data/,您可以通过在子命令中使用期望的输出目录名称作为可选参数来更改它。

promtool tsdb create-blocks-from openmetrics <input file> [<output directory>]

创建块后,将其移动到 Prometheus 的数据目录中。如果与 Prometheus 中现有块存在重叠,对于 v2.38 及以下版本的 Prometheus,需要设置标志 --storage.tsdb.allow-overlapping-blocks。请注意,任何回填的数据都受您 Prometheus 服务器配置的保留策略(按时间或大小)的约束。

更长的块持续时间

默认情况下,promtool 会为块使用默认的块持续时间(2 小时);这种行为是最普遍适用且正确的。然而,当回填长时间范围的数据时,使用更大的块持续时间可能更有优势,可以更快地回填并防止 TSDB 后期进行额外的压缩。

--max-block-duration 标志允许用户配置块的最大持续时间。回填工具将选择一个不超过此值的合适块持续时间。

虽然更大的块可能提高回填大型数据集的性能,但也存在缺点。如果(潜在的)大块中即使只有一个样本仍在其保留策略范围内,基于时间的保留策略也必须保留整个块。相反,基于大小的保留策略将移除整个块,即使 TSDB 仅轻微超出大小限制。

因此,使用少量块进行回填(从而选择更大的块持续时间)必须谨慎进行,不建议在任何生产实例中使用。

记录规则的回填

概览

创建新的记录规则时,它没有历史数据。记录规则数据仅从创建时间开始存在。promtool 使创建历史记录规则数据成为可能。

用法

要查看所有选项,请使用:$ promtool tsdb create-blocks-from rules --help

使用示例

$ promtool tsdb create-blocks-from rules \
    --start 1617079873 \
    --end 1617097873 \
    --url http://mypromserver.com:9090 \
    rules.yaml rules2.yaml

提供的记录规则文件应是正常的 Prometheus 规则文件

promtool tsdb create-blocks-from rules 命令的输出是一个目录,其中包含记录规则文件中所有规则的历史规则数据块。默认情况下,输出目录是 data/。为了使用这些新的块数据,必须将这些块移动到正在运行的 Prometheus 实例的数据目录 storage.tsdb.path 中(对于 v2.38 及以下版本的 Prometheus,必须启用标志 --storage.tsdb.allow-overlapping-blocks)。移动后,当下次压缩运行时,新块将与现有块合并。

限制

  • 如果您多次运行规则回填器并使用重叠的开始/结束时间,每次运行规则回填器时都会创建包含相同数据的块。
  • 记录规则文件中的所有规则都将被求值。
  • 如果在记录规则文件中设置了 interval,它将优先于规则回填命令中的 eval-interval 标志。
  • 如果告警包含在记录规则文件中,则目前会被忽略。
  • 同一组中的规则无法看到之前规则的结果。这意味着不支持引用正在回填的其他规则的规则。一个解决方法是多次回填,首先创建依赖数据(并将依赖数据移动到 Prometheus 服务器数据目录,以便可以从 Prometheus API 访问)。

本文档是开源的。请通过提交 issue 或 pull request 帮助改进它。