Prometheus TSDB (Part 1): The Head Block

Prometheus TSDB (Part 1): The Head Block

原文
介绍

​ 尽管Prometheus 2.0大约是在3年前(2017年)发布的,但是除了Fabian的博客文章(深层次文章)之外,没有多少资源可以了解它(TSDB),并且官方文档仅供开发人员参考。

​ Prometheus的TSDB最近吸引了许多新的贡献者,但由于缺乏相关的文档资源,导致开发人员难以深入理解TSDB。

​ 在此博客文章中,我主要讨论TSDB的内存部分(Head-block),届时我将更深入地研究WAL和它的检查点,如何设计chunks的内存映射,压缩,持久性,块及其索引,以及将来文章中即将出现的块快照。

名称解释
Sample-样本
Samples form the actual time series data. Each sample consists of:
  - a float64 value
  - a millisecond-precision timestamp
WAL
WAL is a write ahead log that can log new series labels and samples.
It must be completely read before new entries are logged.
Block-块
Block represents a directory of time series data covering a continuous time range. A Block contains multi chunks and their index.
Chunk-分块
Chunk holds a sequence of sample pairs that can be iterated over and appended to.
内存映射的数据块,每一个分块包含120个sample或者指定单位时间跨度的数据。
序文

Fabian的博客文章 深入的阐述了数据模型,核心概念以及如何设计TSDB。他还在PromCon 2017上就此发表了演讲。我建议您先阅读Fabian的博客文章或观看演讲,在它的基础上深入阅读这篇文章。

​ 如果您愿意,您可以在我的KubeCon演讲中观看这篇文档所讲解的关于Head-block生命周期的内容。

TSDB概述

tsdb1


在上图中,Head block是数据库(TSDB)的内存部分,上图中的灰色方框代表的是磁盘上不可更改的持久化数据块。
我们通过一个预写日志(WAL)进行持续写入。传入的sample(粉红色的方框)首先进入Head block,并在内存中停留一段时间,然后刷新到磁盘并映射到内存中(蓝色的方框)。当这些内存映射的块(蓝色的方框)或内存中的块停留时间到一定程度时(块大小或跨度时间超过配置值),它们将作为持久性块刷新到磁盘(数据落盘)。随着它们(数据块)停留时间的增长,(TSDB)将合并更多的块(数据块合并,压缩),并在超过保留期限后将其最终删除。

Head Block中Sample的生命周期

​ 这里的所有讨论都是关于单时间序列的,但也同样适用于多时间序列。

tsdb2

​ Sample 存储在 “chunk(分块)” 这个压缩单元中。(TSDB)收到Sample后,它将被存储到“活动块”(红色块)中。这是唯一一个我们可以主动写入数据的单元(内存存储单位)。在将Sample提交到分块的同时,我们还将其记录在磁盘(棕色块)的磁盘上的Write-Ahead-Log(WAL)中(双写机制),以确保数据的持久性(这意味着即使机器突然崩溃,我们也可以从WAL中恢复内存中的数据) )。 我将撰写单独博客文章来讲解有关Prometheus如何处理WAL文件。

tsdb3

​ 一旦块填满到120个Sample(或)超过分块的时间跨度(默认的chunkRange),默认情况下为2h,则将剪切一个新的分块(黄色块),并且旧的份块被称为“已满”分块。 在此博客文章中,我们将采集间隔设置为15s,因此120个Sample(完整块)的时间跨度是30m。

​ 黄色数字为1的块是已填充的完整块,红色块是已创建的新块。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tn8WPR2K-1628429771492)(https://cdn.jsdelivr.net/gh/woraser/imageUpload@master/uPic/tsdb4.svg)]

​ 从Prometheus v2.19.0开始,我们不再将所有分块都存储在内存中。剪切新的分块后,整个分块将刷新到磁盘并从磁盘进行内存映射,仅将引用存储在内存中。通过使用内存映射,我们可以在需要的时候,使用该引用将块动态加载到内存中。这是操作系统提供的功能。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EK05wFzl-1628429771493)(https://cdn.jsdelivr.net/gh/woraser/imageUpload@master/uPic/tsdb5.svg)]

​ 同样,随着新Sample的不断添加,TSDB会持续剪切新的块,然后将它们刷新到磁盘并映射到内存中。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S1uJRSum-1628429771495)(https://cdn.jsdelivr.net/gh/woraser/imageUpload@master/uPic/tsdb6.svg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6zAKKZgV-1628429771496)(https://cdn.jsdelivr.net/gh/woraser/imageUpload@master/uPic/tsdb7.svg)]

​ 一段时间后,Head Block将如上图所示。如果红色块几乎已满,那么Head block 中存在三小时的的数据(6个块,每个块跨越30m,5个黄色块+一个红色块)。即chunkRange * 3/2。(chunkRange默认为2小时)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IXwYuB0R-1628429771497)(https://cdn.jsdelivr.net/gh/woraser/imageUpload@master/uPic/tsdb8.svg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ULopyjSl-1628429771498)(https://cdn.jsdelivr.net/gh/woraser/imageUpload@master/uPic/tsdb9.svg)]

​ 当Head Block中的数据跨度超过chunkRange * 3/2的时间时,单位时间(chunkRange时间,默认为2小时)的数据将被压缩为一个持久块(即5个分块)。 从上文中可以看出,WAL在此时将被截断,并创建一个checkpoint(检查点,数据的完整性检查)(图中未显示)。我将在以后的博客文章中详细介绍checkpoint(检查点),WAL截断,压缩,持久性块及其索引。

​ “Sample的获取->内存映射->压缩成持久块” 这一流程的循环持续进行,构成了Head Block模块的基本功能。

其他注意事项
索引在哪里?

​ 索引存储于内存中并被存储为反向索引。有关索引的更多详细内容,请参考Fabian的博客文章Head Block进行数据压缩时,创建了一个持久块,Head Block会删除旧的块,并且对被删除块的索引进行了垃圾回收,以删除Head Block中不存在的时序信息。

重启处理

​ 如果TSDB必须重新启动(正常或非正常重启),它将使用磁盘上的内存映射的块和WAL重播数据和事件,并重新构建内存中的索引和块。

参考代码

tsdb/db.go 内包含管理TSDB的整体逻辑。

​ 本文描述的相关部分,内存块提取的核心逻辑全部在tsdb/head.go 中,文中的WAL和内存映射操作作为黑盒处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值