prometheus本地存储采用TSDB,分析TSDB的存储方式。主要参考文末的文章。

采样数据结构

Prometheus Server 采集的数据成为Sample,每次采集数据结构包括:

  • 指标名称(metrics name):定义某项数据指标,例如:cpu、http_request等。
  • 时间戳(timestamp):一个精确到毫秒的时间戳,表示数据记录的时间。
  • 标签(Lables):对指标名称进行进一步分类,例如增加服务器名称标签,同一指标名称包含从多个服务器获取来的数据。
  • 样本值(value):该指标具体数据。
TSDB存储流程

1)采样的数据优先存入内存head chunk,同时将采集到的数据写入wal。wal记录samples内容,wal通常是顺序写入磁盘,对于机械磁盘写入效率较高。当prometheus挂了,系统启动后优先恢复wal数据,防止数据丢失。

java Prometheus 能设置时间吗 prometheus timestamp_倒排索引


2)当Head采集到指定数量的Sample,将该chunk交给mmap chunks进行持久化存储。

java Prometheus 能设置时间吗 prometheus timestamp_prometheus_02


3)经过一段时间后,mmap chunks多个chunks合并为block。

java Prometheus 能设置时间吗 prometheus timestamp_数据_03

Block 存储结构(图来自于文末参考)

java Prometheus 能设置时间吗 prometheus timestamp_倒排索引_04


meta.json:包含块唯一标识(ulid),该块内Sample的时间范围(MinTime、MaxTime、),版本(Version)等。

index: 记录chunk的索引信息,包括根据指标名称、标签搜索样本数据(倒排索引)。

tombstones:对Series的删除记录,系统不是立刻删除,先在tombstones做标记,后续块压缩时处理。

chunks:sample数据,由多个chunk文件组成。

Index结构

java Prometheus 能设置时间吗 prometheus timestamp_数据结构_05


magic:固定 0xBAAAD700

version:v1、v2

Symbol Table: Label标签包含大量Key、Value,而大部分Sample可能会重复Key、Value信息,如果直接存储将会浪费存储空间,Symbol Table对Lable中的Key 或 Value进行编号,节省存储空间。

java Prometheus 能设置时间吗 prometheus timestamp_数据结构_06


Series:每个时间序列下包含的内容,该序列的Lab标签、每个chunk的时间范围、以及该chunk在chunks目录下的位置。

java Prometheus 能设置时间吗 prometheus timestamp_数据_07


lable index:记录Label中Key对应的所有Value。

java Prometheus 能设置时间吗 prometheus timestamp_数据结构_08


postings:倒排索引,记录某个Label关联的SeriesID。

java Prometheus 能设置时间吗 prometheus timestamp_倒排索引_09


label index table:记录所有的Key关联的Value 在Label Index中的位置。

java Prometheus 能设置时间吗 prometheus timestamp_倒排索引_10


postings table:每个label的key和value 关联的Series ID 列表。

java Prometheus 能设置时间吗 prometheus timestamp_数据结构_11

ToC:记录上面字段在index文件的偏移。索引的索引,俄罗斯套娃。

java Prometheus 能设置时间吗 prometheus timestamp_数据_12

参考:https://qnmlgb.tech/articles/63ace69548efc8e43d134ae3/
参考:https://zhuanlan.zhihu.com/p/404468461