存储
Prometheus 包括本地磁盘时间序列数据库,并且还可以与远程存储系统进行集成。
本地存储
Prometheus 的本地时间序列数据库(即 time series database,TSDB)以自定义且高度高效的形式在本地存储中存储数据。
磁盘布局
输入的样本被分组为两小时的块(chunks)。每个两小时的块包含一个目录,其中包含该时间段内的所有时间序列样本,一个元数据文件及一个索引文件(用于索引指标名称和标签到块目录中的具体时间序列)。块目录中的样本通过默认的最大 512MB 的段(segments)文件进行分组。当通过 API 删除序列时,删除记录会先被存储在单独的墓碑文件(tombstone files)中(而不是立即从块段中删除数据)。
正在接收的当前块被保持在内存中,并未完全持久化。它通过写前日志(WAL)得到保护,当 Prometheus 服务器重启时此日志中的记录会被恢复。WAL 文件存储在wal
目录中的 128MB 段中。这些文件包含尚未被压缩的数据,因此它们比常规块文件大得多。Prometheus 将保留至少三个写前日志文件。高流量服务器可能会保留超过三个 WAL 文件,以便至少保留两小时的原始数据。
Prometheus 服务器的数据目录看起来类似于:
请注意,本地存储的一个限制是它没有集群化或副本。因此,在面对磁盘或节点故障时,它不能任意扩展或持久,应像其他单节点数据库一样进行管理。
快照推荐用于备份。通常每两小时进行一次同步,不使用快照进行的备份存在丢失自上一次 WAL 同步以来记录的数据的风险。通过适当的架构设计,我们可以在本地存储中保留数年的数据。
作为替代方案,可以通过 remote read/write API 使用外部存储。对于这些系统,因为它们在持久性、性能和效率方面差异很大,需要仔细进行评估。
关于文件格式的详细信息,请参阅 TSDB 格式。
压缩
初始的两小时块最终会在后台进行压缩后形成更长的块。
压缩会创建包含跨度长达 10% 的保留时间或 31 天(取两者中的较小值)的数据的大块。
运维方面
Prometheus 具有配置本地存储的多个标志。最重要的包括:
--storage.tsdb.path
:Prometheus 数据库的位置。默认值为data/
。--storage.tsdb.retention.time
:在存储中样本保留的时间长度。当设置此标志时,它会覆盖storage.tsdb.retention
。如果没有设置此标志、storage.tsdb.retention
或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 和映射到内存的块也被计算在总大小内,但只有持久块会因为超出块大小而被删除。因此,Prometheus 对于磁盘容量的最小要求是wal
(WAL 和检查点)和chunks_head
(映射到内存的头块)目录的集合(每两小时达到峰值)。--storage.tsdb.retention
:在 2.11.0 版本中弃用,建议使用storage.tsdb.retention.time
。--storage.tsdb.wal-compression
:启用写前日志(WAL)的压缩。根据你处理的数据的不同,你可能会期望以较小地增加 CPU 的负载的代价使得 WAL 大小减少一半。此标志于 2.11.0 版本引入,并在 2.20.0 版本中默认启用。注意,一旦启用,如果要将 Prometheus 降级至低于 2.11.0 的版本,你将需要删除 WAL。
Prometheus 每个样本平均只存储 1-2 字节的数据。因此,为了规划 Prometheus 服务器的磁盘容量,你可以使用以下粗略公式进行计算:
为了降低消费样本的速度,你可以减少你抓取的时间序列的数量(Target 数量较少或每个 Target 的序列数量较少),或者增加抓取间隔。然而,减少序列数量可能更为有效,因为同一序列内的样本可以被压缩。
如果本地存储由于某种原因而损坏,解决该问题的最佳策略是关闭 Prometheus,然后删除整个存储目录。你也可以尝试删除单个块目录或 WAL 目录来解决问题。请注意,一旦删除,就意味着大约每个块目录都会丢失两小时的数据。再次强调,Prometheus 的本地存储并非旨在提供长期持久性存储;外部解决方案提供了更长的保留时间和更好的数据持久性。
注意:不符合 POSIX 规范的文件系统不支持 Prometheus 的本地存储,使用这些文件系统可能会导致不可恢复的损坏。NFS 文件系统(包括 AWS 的 EFS)不被支持。NFS 可能是符合 POSIX 规范的,但大多数实现都不是。我们强烈建议使用本地文件系统以提高可靠性。
如果同时指定了时间保留策略和大小保留策略,则将先触发的策略将被使用。
过期块清理在后台进行。移除过期块可能需要长达两小时的时间完成。块必须完全过期后才能被移除。
合理调整保留大小
如果你使用storage.tsdb.retention.size
设置大小限制,则需要考虑相对于为 Prometheus 分配的存储,该值的正确大小。较为明智的做法是减少保留的大小以提供缓冲,确保较早的记录在 Prometheus 分配的存储空间满之前就被移除。
目前,我们推荐将保留大小最多设置为分配给 Prometheus 磁盘空间的 80-85%。这增加了较早的条目在遇到任何磁盘限制之前就被移除的可能性。
远程存储集成
Prometheus 的本地存储功能仅限于单节点的可扩展性和持久性,而不是试图在 Prometheus 自身解决集群存储。Prometheus 提供了一套接口,允许其与远程存储系统集成。
概览
Prometheus 在三个方面与远程存储系统进行集成:
- Prometheus 可以将它获取的样本写入到标准格式的远程 URL 中。
- Prometheus 可以接收来自其他 Prometheus 服务器的标准格式的样本。
- Prometheus 可以从远程 URL 读取(回溯)符合标准格式的样本数据。
读取和写入协议均使用基于 HTTP 的 Snappy 压缩的 Protocol Buffer 编码。这些协议目前尚未被视为稳定的 API,将来在 Prometheus 与远程存储之间的所有跳转都能安全地假设支持 HTTP/2 时,可能会改为使用 gRPC。
有关在 Prometheus 中配置远程存储集成的详细信息,请参阅 Prometheus 配置文档中的 remote write 和 remote read 部分。
内置的 remote write 接收器可以通过设置--web.enable-remote-write-receiver
命令行标志来启用。当启用时,remote write 接收器端点为/api/v1/write
。
有关请求和响应消息的详细信息,请参阅远程存储协议缓冲区定义。
值得注意的是,在读取路径上,Prometheus 仅从远端获取一组标签选择器和时间范围的原始序列数据。对原始数据的所有 PromQL 评估仍然在 Prometheus 自身中进行。这意味着 remote read 查询具有一定的可伸缩性限制,因为所有必要的数据都需要首先加载到要查询的 Prometheus 服务器中,然后在那里处理。目前不支持分布式评估 PromQL。
已有的集成
要了解与远程存储系统的现有集成,请参阅 Integrations文档。
从 OpenMetrics 格式回填
概览
如果用户希望从 OpenMetrics 格式的数据创建 TSDB 中的块,则可以使用回填(backfilling)来实现。但是,你必须注意,回填过去三小时的数据(距离当前头部块)是不安全的,因为这个时间范围可能与 Prometheus 仍在修改的当前头部块重叠。回填会创建新的TSDB块,每个块包含两小时的指标数据。这降低了创建块所需的内存需求。随后,Prometheus 服务器自己会将两小时的块合并为较大的块 。
典型的用例是从不同的监控系统或时间序列数据库迁移指标数据到 Prometheus。为此,用户必须首先将源数据转换为 OpenMetrics 格式,这是回填所需要的数据格式。
请注意,此过程不支持原生 Histogram 和过期标记(staleness markers),因为它们无法在 OpenMetrics 格式中表示。
使用方法
回填功能可以通过 Promtool 命令行使用。Promtool 会将块写入一个目录中。默认输出目录为 ./data/
。可以通过在子命令中使用所需输出目录作为可选参数来更改输出目录。
创建块后,请将其移动到 Prometheus 的数据目录中。如果与 Prometheus 中存在的块有重叠,则需要设置 Prometheus 版本 v2.38 及以下的标志--storage.tsdb.allow-overlapping-blocks
。请注意,任何回填的数据都取决于你的Prometheus 服务器配置的数据保留时间(按时间或大小)。
更长的块持续时间
默认情况下,Promtool 将使用默认块持续时间(2小时)来创建块;这种行为最为普遍且正确。但是,在长时间范围内回填数据时,使用更大的块持续时间值可能有助于更快地回填,并防止 TSDB 后续进行额外的压缩。
--max-block-duration
标志允许用户配置块的最大持续时间。回填工具将选择不大于此值的合适块持续时间。
虽然较大的块可能有助于提高处理大型数据集的性能,但也存在缺点。基于时间的保留策略必须保留整个块,即使只有块中的一个样本仍在保留策略内也是如此。相反,基于大小的保留策略可能会移除整个块,即使 TSDB 仅仅是轻微超过大小限制。
因此,选择较少的块和较大的块持续时间进行回填需要谨慎操作,不推荐将这一配置用于生产实例。
记录规则回填
概览
- 当创建新的记录规则(recording rules)时,它没有对应历史数据。
- 记录规则的数据仅从创建时间开始存在。
promtool
允许创建历史记录规则数据。
使用方法
要查看所有选项,请使用:$ promtool tsdb create-blocks-from rules --help
。
示例用法:
提供的记录规则文件应为正确的 Prometheus 规则文件。
promtool tsdb create-blocks-from rules
命令的输出是一个包含记录规则文件中所有规则的历史数据块的目录。默认输出目录为data/
。为了利用这些新块数据,必须将块移动到正在运行的 Prometheus 实例数据目录storage.tsdb.path
(对于 Prometheus 版本 v2.38 及以下,必须启用--storage.tsdb.allow-overlapping-blocks
)。一旦移动,新块将在下一次压缩运行时与现有块合并。
局限
- 如果你多次运行规则回填器(rule backfiller),并带有重叠的开始/结束时间,则每次运行规则回填器时都会创建包含相同数据的块。
- 记录规则文件中的所有规则都将被计算。
- 如果在记录规则文件中设置了
interval
,则会优先于eval-interval
标志。 - 目前,如果在记录规则文件中包含告警,则其会被忽略。
- 同一组中的规则无法看到先前规则的结果。这意味着不支持依赖其他规则回填的规则。解决方法是首先创建被依赖的数据,然后多次回填(并将依赖数据移动到 Prometheus 服务器数据目录,以便通过 Prometheus API 访问)。
该文档基于 Prometheus 官方文档翻译而成。