Prometheus 包含一个本地磁盘时间序列数据库,同时也可选地与远程存储系统集成。
本地存储
Prometheus 的本地时间序列数据库以自定义的高效格式在本地存储上存储数据。
磁盘布局
采集的样本被分组到两小时的块中。每个块由一个目录组成,其中包含一个 chunks 子目录(包含该时间窗口的所有时间序列样本)、一个元数据文件和一个索引文件(将指标名称和标签映射到 chunks 目录中的时间序列)。chunks 目录中的样本被组织成一个或多个段文件,每个段文件默认最大 512 MB。当通过 API 删除序列时,删除记录存储在单独的 tombstone 文件中,而不是立即从 chunk 段中删除。
当前接收样本的块保存在内存中,尚未完全持久化。它通过预写日志(WAL)来防止崩溃,当 Prometheus 服务器重启时可以重放该日志。预写日志文件以 128MB 段存储在 wal 目录中。这些文件包含尚未压缩的原始数据;因此它们比常规块文件大得多。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
需要注意的是,本地存储的一个限制是它不是集群化或复制的。因此,在面对驱动器或节点故障时,它不具备任意可扩展性或持久性,应该像管理任何其他单节点数据库一样进行管理。通过适当的架构,可以在本地存储中保留数年的数据。
建议使用快照进行备份。不使用快照进行的备份有丢失自上次 TSDB 块创建以来记录的数据的风险,通常每两小时发生一次,覆盖最近三小时的样本。在备份或恢复时排除 WAL 文件(storage.tsdb.path 中的 chunks_head/、wal/ 和 wbl/ 目录)将确保备份的一致性,无论如何都以丢失 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 和 m-mapped chunks 会被计入总大小。因此磁盘的最低要求是wal(WAL 和 Checkpoint)和chunks_head(m-mapped Head chunks)目录占用的峰值空间之和(每 2 小时达到峰值)。--storage.tsdb.wal-compression:启用预写日志(WAL)压缩。根据你的数据,你可以期望 WAL 大小减少一半,而只需少量额外的 CPU 负载。此标志在 2.11.0 中引入,在 2.20.0 中默认启用。注意,一旦启用,降级到 2.11.0 以下版本的 Prometheus 将需要删除 WAL。
Prometheus 每个样本平均只存储 1-2 个字节。因此,要规划 Prometheus 服务器的容量,你可以使用以下粗略公式:
needed_disk_space = retention_time_seconds * ingested_samples_per_second * bytes_per_sample
要降低采集样本的速率,你可以减少抓取的时间序列数量(更少的目标或每个目标更少的序列),或者增加抓取间隔。然而,减少序列数量可能更有效,因为同一序列内的样本具有压缩效果。
如果你的本地存储损坏到 Prometheus 无法启动的程度,建议备份存储目录并从备份中恢复损坏的块目录。如果没有备份,最后的手段是删除损坏的文件。例如,你可以尝试删除单个块目录或预写日志(WAL)文件。请注意,这意味着丢失这些块或 WAL 覆盖的时间范围的数据。
注意:不支持非 POSIX 兼容的文件系统用于 Prometheus 的本地存储,因为可能发生不可恢复的损坏。不支持 NFS 文件系统(包括 AWS 的 EFS)。NFS 可能是 POSIX 兼容的,但大多数实现不是。强烈建议使用本地文件系统以确保可靠性。
如果同时指定了时间和大小保留策略,将使用先触发的策略。
过期块的清理在后台进行。删除过期块可能需要长达两小时。块必须完全过期才能被删除。
正确设置保留大小
如果你使用 storage.tsdb.retention.size 设置大小限制,你需要考虑相对于为 Prometheus 分配的存储的正确大小。明智的做法是减小保留大小以提供缓冲区,确保在为 Prometheus 分配的存储满之前删除旧条目。
目前,我们建议将保留大小设置为最多分配的 Prometheus 磁盘空间的 80-85%。这增加了在达到任何磁盘限制之前删除旧条目的可能性。
远程存储集成
Prometheus 的本地存储受限于单节点的可扩展性和持久性。Prometheus 没有尝试在自身解决集群存储问题,而是提供了一组接口允许与远程存储系统集成。
概述
Prometheus 以四种方式与远程存储系统集成:
- Prometheus 可以将采集的样本以 Remote Write 格式写入远程 URL。
- Prometheus 可以从其他客户端接收 Remote Write 格式的样本。
- Prometheus 可以从远程 URL 以 Remote Read 格式读取(回)样本数据。
- Prometheus 可以以 Remote Read 格式返回客户端请求的样本数据。

远程读写协议都使用 snappy 压缩的 protocol buffer 编码通过 HTTP 传输。读协议尚未被视为稳定 API。
写协议有一个稳定的 1.0 版本规范和实验性的 2.0 版本规范,两者都受 Prometheus 服务器支持。
有关在 Prometheus 中作为客户端配置远程存储集成的详细信息,请参阅 Prometheus 配置文档的 remote write 和 remote read 部分。
需要注意的是,在读路径上,Prometheus 仅从远程端获取一组标签选择器和时间范围的原始序列数据。所有对原始数据的 PromQL 评估仍然在 Prometheus 本身进行。这意味着远程读查询有一定的可扩展性限制,因为所有必要的数据需要先加载到查询 Prometheus 服务器中,然后在那里处理。然而,目前支持完全分布式的 PromQL 评估被认为是不可行的。
Prometheus 也提供这两种协议的服务。内置的 remote write 接收器可以通过设置 --web.enable-remote-write-receiver 命令行标志来启用。启用后,remote write 接收器端点为 /api/v1/write。Remote read 端点可通过 /api/v1/read 访问。
现有集成
要了解更多与远程存储系统的现有集成,请参阅集成文档。
从 OpenMetrics 格式回填
概述
如果用户想从 OpenMetrics 格式的数据创建 TSDB 块,可以使用回填功能。但是,他们应该注意不要回填最近 3 小时的数据(当前 head 块),因为此时间范围可能与 Prometheus 仍在修改的当前 head 块重叠。回填将创建新的 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 将使用默认块持续时间(2h)来创建块;这是最通用和正确的行为。但是,当回填长时间范围的数据时,使用更大的块持续时间值可能更有利,以加快回填速度并防止 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(对于 Prometheus v2.38 及以下版本,必须启用 --storage.tsdb.allow-overlapping-blocks 标志)。移动后,当下一次压缩运行时,新块将与现有块合并。
限制
- 如果你使用重叠的开始/结束时间多次运行规则回填器,每次运行规则回填器时都会创建包含相同数据的块。
- 记录规则文件中的所有规则都将被评估。
- 如果在记录规则文件中设置了
interval,它将优先于规则回填命令中的eval-interval标志。 - 如果记录规则文件中有告警,当前会被忽略。
- 同一组中的规则无法看到之前规则的结果。这意味着不支持引用正在回填的其他规则的规则。解决方法是多次回填并先创建依赖数据(并将依赖数据移动到 Prometheus 服务器数据目录,以便可以通过 Prometheus API 访问)。