4.存储及WAL

  • 一、整体介绍
  • 二、block
    • 2.1 head block
  • 三、WAL(Write-ahead logging, 预写日志)
    • 3.1 数据流向
  • 四、和存储相关的启动参数
  • 五、总结

一、整体介绍

Prometheus 2.x 采用自定义的存储格式将样本数据保存在本地磁盘当中。如下所示,按照两个小时(最少时间)为一个时间窗口,将两小时内产生的数据存储在一个块(Block)中,每一个块中包含该时间窗口内的所有样本数据(chunks),元数据文件(meta.json)以及索引文件(index)。

[mingming.chen@m162p65 data]$ tree
.
├── 01E2MA5GDWMP69GVBVY1W5AF1X
│   ├── chunks               # 保存压缩后的时序数据,每个chunks大小为512M,超过会生成新的chunks
│   │   └── 000001
│   ├── index                # chunks中的偏移位置
│   ├── meta.json            # 记录block块元信息,比如 样本的起始时间、chunks数量和数据量大小等
│   └── tombstones           # 通过API方式对数据进行软删除,将删除记录存储在此处(API的删除方式,并不是立即将数据从chunks文件中移除)
├── 01E2MH175FV0JFB7EGCRZCX8NF
│   ├── chunks
│   │   └── 000001
│   ├── index
│   ├── meta.json
│   └── tombstones
├── 01E2MQWYDFQAXXPB3M1HK6T20A
│   ├── chunks
│   │   └── 000001
│   ├── index
│   ├── meta.json
│   └── tombstones
├── lock
├── queries.active
└── wal                      #防止数据丢失(数据收集上来暂时是存放在内存中,wal记录了这些信息)
    ├── 00000366             #每个数据段最大为128M,存储默认存储两个小时的数据量。
    ├── 00000367
    ├── 00000368
    ├── 00000369
    └── checkpoint.000365
        └── 00000000

二、block

TSDB将存储的监控数据按照时间分成多个block存储,默认最小的block保存时间为2h,后台程序还会将小块合并成大块,减少内存中block的数量,便于索引查找数据,可以通过meta.json查看,可以看到01E2MA5GDWMP69GVBVY1W5AF1X被压缩1次,source有3个block,那么2*3=6小时的数据量。

关于block压缩:

  1. 最初的两个小时的块最终会在后台压缩为更长时间的块;
  2. 压缩的最大时间块为数据保留时间的10%或者31天,取两者的较小者。

2.1 head block

1.head block中的数据是被存储在内存中的并且可以被任意修改;
2.head block和后续的block初始设定保存2h数据,当head block超过3h时,会被拆分为2h+1h,2h block会变成只读块写入磁盘.(通过观察服务器上prometheus存储目录,每次压缩合并小块时间都比块内部时间多三个小时,为head block),如下所示:

三、WAL(Write-ahead logging, 预写日志)

Prometheus为了防止丢失暂存在内存中的还未被写入磁盘的监控数据,引入了WAL机制。WAL被分割成默认大小为128M的文件段(segment),之前版本默认大小是256M,文件段以数字命名,长度为8位的整形。WAL的写入单位是页(page),每页的大小为32KB,所以每个段大小必须是页的大小的整数倍。如果WAL一次性写入的页数超过一个段的空闲页数,就会创建一个新的文件段来保存这些页,从而确保一次性写入的页不会跨段存储。

3.1 数据流向

prometheus将周期性采集到的数据通过Add接口添加到head block,但是这些数据暂时没有持久化,TSDB通过WAL将数据保存到磁盘上(保存的数据没有压缩,占用内存较大),当出现宕机,启动多协程读取WAL,恢复数据。

四、和存储相关的启动参数

--storage.tsdb.path: This determines where Prometheus writes its database. Defaults to data/.
--storage.tsdb.retention.time: This determines when to remove old data. Defaults to 15d. Overrides storage.tsdb.retention if this flag is set to anything other than default.
--storage.tsdb.retention.size: [EXPERIMENTAL] This determines the maximum number of bytes that storage blocks can use (note that this does not include the WAL size, which can be substantial). The oldest data will be removed first. Defaults to 0 or disabled. This flag is experimental and can be changed in future releases. Units supported: KB, MB, GB, PB. Ex: "512MB"
--storage.tsdb.retention: This flag has been deprecated in favour of storage.tsdb.retention.time.
--storage.tsdb.wal-compression: This flag enables compression of the write-ahead log (WAL). Depending on your data, you can expect the WAL size to be halved with little extra cpu load. Note that if you enable this flag and subsequently downgrade Prometheus to a version below 2.11.0 you will need to delete your WAL as it will be unreadable.

PS: 以上有两个参数storage.tsdb.retention.size和storage.tsdb.retention.time,两个同时设置时,两者无优先级,谁先触发就执行删除操作。(其它启动参数参考promethes#promethes 第五章节启动参数部分)

五、总结

需要解决的几个问题:

1.远程存储节点长时间挂掉(默认blocK大小为2小时,实际大于六小时,prometheus2.15经测试验证非官方文档说的两个小时),刷盘到prometheus的数据库中的数据还能不能同步到远程?

2.WAL的缓存数据的时间可不可以调整?

解答:

1.根据以上内容和3.远程写参数优化可知,prometheus本地存储和远程存储并无影响。因为远程存储是通过将WAL中的数据缓存到多个内存队列(shards)中,然后写到远程存储设备,其直接与WAL打交道。而prometheus只是用WAL来防止数据丢失,其存储的一系列动作都与WAL没关系。所以当内存中缓存的数据达到刷盘的阈值,WAL中没有写到远程存储的数据就会丢失,当重新启动远程存储服务,原来那部分没有写入远程存储服务的数据已经丢失,只能从最新的数据开始写入远程存储,这部分可参考3.远程写参数优化2.2部分结论。

2. 可以调整,准确来说是间接调整。wal保留数据的长短与prometheus最小压缩block大小有关系,由于wal中至少保留当前时间正在写入的文件之外的三个文件(每个文件保存一个block大小的数据量),所以当增大block大小的时候就会相应的增大wal保存的数据量,但是,block的大小调整会直接影响内存的使用,需要根据现有的环境进行相应的调优。

如下图所示,当我设置--storage.tsdb.min-block-duration=4h(prometheus的启动参数)时,wal中当前保留的文件(存在的数据时间范围:2020.03.20 20:00:00–2020.03.21 13.52),其中每个文件保留4个小时的数据量。

猜你喜欢

转载自www.cnblogs.com/chenmingming0225/p/12634250.html
WAL