登陆

极彩登录网址-揭秘Prometheus时序数据库规划

admin 2019-10-29 282人围观 ,发现0个评论

Prometheus作为一个独登时开源监控体系和告警东西,是继Kubernetes之后参加CNCF的第二个项目,社区具有十分活泼的开发者用户,也被越来越多的公司和安排选用。Pormetheus一般单点方法布置,每个周期能够从上万个Target抓取并处理数百万个时序数据,支撑PromQL高效(聚合)查询历史数据,其间心在于时序数据库TSDB规划缬沙坦胶囊与完结

时序数据

Prometheus随时刻搜集监控数据点,每个数据点都是时刻戳和值的元组。出于监控的意图,时刻戳是一个整数,值是恣意数字--64位浮点数关于Counter和Gauge类型来说都是一个很好的表明方法。按时刻戳严厉单调递加的数据点序列是一个由标识符寻址的Series标识符是带有标签维度的监控项称号,标签维度区别单个监控项的衡量空间,每个监控项称号加上一组仅有标签是其自己的时刻序列,其具有与之相关的值流

## series格局为 identifier -> (t0, v0), (t1, v1), (t2, v2), (t3, v3), ....
## 一组典型的系列标识符,是恳求技能监控衡量的一部分
requests_total{path="/status", method="GET", instance=”10.0.0.1:80”}
requests_total{path="/status", method="POST", instance=”10.0.0.3:80”}
requests_total{path="/", method="GET", instance=”10.0.0.2:80”}
## 简化表明,监控项称号能够是另一个标签维度__name__,在查询是它或许会被特别处理,但与咱们存储它的方法无关
{__name__="requests_total", path="/status", method="GET", instance=”10.0.0.1:80”}
{__name__="requests_total", path="/status", method="POST", instance=”10.0.0.3:80”}
{__name__="requests_total", path="/", method="GET", instance=”10.0.0.2:80”}
因而,identifier 形如 metricName{label1=value1,label2=value2,...} 或
{__name__="metricName",label1=value1,label2=value2,...}
## 在简化的视图中,一切数据点能够在二维平面上打开。水平维度表明时刻,笔直维度按series打开
series
^
│ . . . . . . . . . . . . . . . . . . . . . . {__name__="request_total", method="GET"}
│ . . . . . . . . . . . . . . . . . . . . . . {__name__="request_total", method="POST"}
│ . . . . . . .
│ . . . . . . . . . . . . . . . . . . . ...
│ . . . . . . . . . . . . . . . . . . . . .
│ . . . . . . . . . . . . . . . . . . . . . {__name__="errors_total", method="POST"}
│ . . . . . . . . . . . . . . . . . {__name__="errors_total", method="GET"}
│ . . . . . . . . . . . . . .
│ . . . . . . . . . . . . . . . . . . . ...
│ . . . . . . . . . . . . . . . . . . . .
v
<-------------------- time --------------------->

Prometheus通过定时抓取一组时刻序列的当时值来检索数据点,从中抓取这个时序数据批次的实体称为Target。单个Prometheus实例从数万个Target中搜集数据,每个Target供给数百到数千个不同的时刻序列,来自每个Target的样本(series)被独登时抓取,那么每个周期(分钟/半分钟)大约搜集数百万个时序数据,在此规划上,按时序次序批量地写入是一个不行洽谈的功能要求(次序和批量写入也是旋转磁盘和SSD的抱负写入方式)

查询方式不同于写入方式,咱们能够查询单个数据点的单个时序、单个数据点的10000个时序、单个时序数周的数据点、10000个时序数周的数据点。因而,在二维平面上,查询既不是彻底笔直的也不是水平,而是两者的矩形组合。装备查询规矩能够缓解已知查询的问题,但不是实时查询的惯例处理方案,后者仍需相当好地履行

咱们想要批量写数据,但咱们获取的是批量跨series的笔直数据点集。在一个时刻窗口查询时序数据点时,有必要从磁盘上的许多随机方位读取且难以找出方针数据点的方位,即使是在速度最快的SSD上每个查询也或许会触及数百万个样本。读取还将从磁盘中检索比恳求16字节样本更多的数据,SSD将加载整页,HDD将至少读取整个扇区...不管哪种方法都在糟蹋名贵的读取吞吐量

抱负情况下,同一系列的样本将按次序存储,因而咱们只需求知道此序列开端拜访一切数据点的方位和尽或许少的读取,就能够扫描到它们。按抱负方式将搜集到的数据写入磁盘与显着进步服务功率的布局之间存在显着的严重联系,这是TSDB需求处理的根本问题

微观布局

在TSDB根目录运转`tree`指令,展现如下结构

目录树

在顶层,有一系列带编号的块,编号以"b-"为前缀。每个块包括一个或许有多个文件的chunks目录、一个index文件和一个meta.json文件。chunks目录只包括很多的原始序列数据点。这使得在一个时刻窗口上读取序列数据十分便当,而且能够运用高效的紧缩算法

但为什么有几个目录是包括chunks和index的布局,而终究一个包括wal目录?了解这两个问题,也就弄清楚TSDB的规划精华

数据库构成

将横向维度(即时刻空间)区别为非堆叠的块(默许跨度两小时),每个块充任一个彻底独立的数据库(区别于chunks,以下简称数据块),包括其时刻窗口内的一切时序数据。因而它有自己的index和chunks文件

沿时刻轴区别数据库

每一个数据块都是不行变的,咱们有必要能够在搜集新数据时将新序列和样本添加到最新的数据块中。关于这个块,一切新数据都写入内存数据库,该数据库供给与耐久块相同的查找特点,能够有用地更新内存中的数据结构。为防止数据丢掉,一切传入数据会写入暂时预写日志,即wal目录中的文件集,这些文件都用自己的序列化格局(flags、offsets、varints、CRC32 checksums),当发作重启时能够顺次康复内存数据库

tips: 在核算机科学中,WAL(Write-Ahead Logging,预写式日志),是联系数据库中用于供给原子性和耐久性的一系列技能。在运用WAL的体系中,一切的修正在提交之前都要先写入log文件中

这种布局答应咱们将查询fan out到与查询相关的一切数据块,将各个数据块回来的部分成果兼并构成全体查询成果

水平分区的长处

  • 查询时刻规模时,能够很简略疏忽时刻窗口不在此区间的数据块
  • 完结一个数据块后,咱们能够通过次序写入一些较大的文件来耐久化内存数据块,防止任何写入扩大,相同很好地为SSD和HDD供给服务
  • 坚持V2的优秀特性,最近被频频查询的数据块热加载于内存中
  • 为更好地对齐磁盘数据,chunk文件巨细不再限制为1KB,咱们能够将其指定为对各个数据点和所选紧缩格局最有含义的恣意巨细
  • 处理数据删去只需删去一个目录即极彩登录网址-揭秘Prometheus时序数据库规划可,变得十分即时和便当。在之前的存储方法中,有必要剖析偏重新编写多大数亿个文件,或许需求数小时才干收敛

每个数据块还包括一个meta.json文件,它以人类可读的方式保存数据块的信息,以便了解存储状况及其包括的数据

紧缩和保存数据块

存储有必要定时"剪切"一个新数据块并将之前完结的数据块写入磁盘,只要在数据块成功耐久化后,才会删去用于康复内存数据块的预写日志文件。数据块应坚持合理的巨细(默许两小时),以防止内存中堆集太多的数据;查询多个数据块时,咱们有必要将其成果兼并为一个全体成果,这个兼并进程明显需求本钱,一个周期的查询不应该兼并超越80个自成果

为完结以上两点,引进紧缩。紧缩描绘了获取一个或多个数据块并将其写入或许更大的数据块的进程,还能够趁便修正现有数据,例如:删去现已删去的数据、重构样本块以进步查询功能

紧缩数据块

上述比如中有[1,2,3,4]四个数据块,块1,2,3能够紧缩在一起终究构成[1,4];1,2和3,4别离紧缩在一起终究构成[1,3]; 一切的时序数据仍然存在,仅仅现在总的数据块变少了,因而查询回来的部分成果数量变少,削减兼并开支而且有利于削减查询时刻

时刻窗口及保存数据

时刻窗口之外的就数据会被主动删去,上例中数据块1在保存时刻窗口之外,通过删去数据块1的目录即可删去旧数据;数据块2部分部分数据在有用时刻窗口之内,部分数据在时刻窗口之外,暂时保存待时刻窗口彻底没有落在数据块2的跨度时,它地点的目录也将被删去

数据库规划

为每一个时序series分配一个仅有的ID,通过该ID能够极彩登录网址-揭秘Prometheus时序数据库规划在常量时刻检索到这个时序,这个ID成为前向索引; 反向索引(倒排索引)依据其内容的子集供给数据项的快速查找,例如:咱们能够快速查找具有标签`app="nginx"`的一切时序,而无需阅读一切时序查看它是否包括该标签

## Example
ID号为9,10,29的时序数据包括标签`app="nginx"`,"nginx"标签的
反向索引列表简略表明为[9,10,29],依据反向索引列表,即使是在200亿个的
样本中也能够快速找到包括标签`app="nginx"`的一切时序,而不会影响查询速度

简而言之,假如n是时序总数,m是给定查询的成果集巨细(m一般比n小的多),那么运用索引的查询时刻复杂度是O(m)。假定咱们能够在稳定时刻内检索反向索引自身,在最坏的情况下,一个标签存在于一切的时序中,m=n,时刻复杂度是O(n)

索引磁盘格局

下面描绘每个数据块中索引文件(index)的格局,它由一个目录(TOC, Table Of Contents)停止,该目录用作索引的进口点

当写入索引时,能够在下面列出的首要段之间添加恣意数量的填充字节。次序扫描文件时,有必要越过段指定长度后的零bytes。下面描绘的大多数段都以len最初,它表明尾部CRC32校验和之前的字节数,校验和也是依据len个字节核算

Index Format

Symbol Table

符号表包极彩登录网址-揭秘Prometheus时序数据库规划括已存储过的时序标签对中呈现的通过重复数据删去的字符串的排序列表,它们能够从后续段中引证,并能显着削减总索引巨细。该段包括一系列字符串条目,每个字符串以字符串原始byte长度为前缀,一切字符串以utf-8编码,依照字典次序升序排序,并由次序索引引证

Symbol Table

Series

这个段包括一系列(按标签字典次序排序的)时序,用于坚持时序的标签集及其数据块内的chunk文件。每一个时序段按16字节对齐,因而,Series ID = offset / 16(在后续段中会引证到),Series ID的排序列表就意味着按字典次序排序的时序标签组列表

Series

每一个时序条目首要保存其标签数,然后包括引证自Symbol Table的标签称号和标签值元组,标签组对按字典次序排序。标签之后,编码被索引的chunk文件数量,接着是包括数据块最小(mint)和最大(maxt)时刻戳的元数据条目以及其在chunk文件中方位的引证。mint是榜首个样本的完好时刻戳,maxt是chunk文件中终究一个样本的时刻戳。在索引中保存时刻规模数据答应丢掉与查询时刻规模无关的数据块。delta编码格局存储 存储榜首个chunk文件的mint,它的maxt存储为delta,mint和maxt被编码为前一个chunk文件的时刻增量,类似地,存储榜首个chunk的引证,并将下一个ref存储为前一个的delta

Series Detail

Label Index

标签索引段索引一个或多个标签称号现有(组合)的值,`#name` 字段确认索引标签称号的数量,后跟`#entries`字段表明条目总数。正文包括Symbol Table引证的`#entries / #name`元组,每个元组的长度为`#name`,值元组按字典递加的次序排序

Label Index

Example: 四个不同值的单标签称号将被编码为

Label Index Example

标签索引段的极彩登录网址-揭秘Prometheus时序数据库规划序列将由包括标签偏移条意图标签偏移表终究确认,该标签偏移条目指向给定标签称号每个标签索引段的最初

Postings

该段存储单调添加的序列引证列表,其间包括与列表相关的给定标签对,由Posting偏移表终究确认,Posting偏移表包括指向给定标签对每个posting段最初部分的posting偏移条目

Postings

Label Offset Table

标签偏移表存储一系列标签偏移条目,每一个标签偏移条目都将标签偏移称号和偏移量保存到标签索引段中的值

Label Offset Table

Postings Offset Table

它存储一系列posting偏移条目,每个条目都包括标签称号/值对以及postings段其序列列表的偏移量,它用于追寻Postings段,加载索引文件是会将它们读入内存

Postings Offset Table

TOC

TOC作为整个索引的进口点,并指向索引文件的各个部分,假如引证为零,表明相应的段不存在,在查找时应回来空成果

Table Of Content

块磁盘格局

下面描绘chunk文件格局,它被创立于`chunks/`目录下,每个段文件最大巨细为512MB。文件中的chunk由索引引证,uint64由文件内偏移量(低4字节)和段序列号(高4字节)组成

Chunks

Single Chunk

Tombstones磁盘格局

tombstones文件(待删去)坐落数据块block的尖端目录中,文件的终究8字节指定了Stones段最初的偏移量,关于快速扫描,stone段为零填充为4的倍数

Tombstones

Single Tombstone

WAL磁盘格局

预写式日志按编号次序操作,例如:000000,000001,000002等,默许限制为128MB。一个段以32KB的页写入,只要最近段的终究一页或许是部分的。WAL是一个不透明的字节切片,假如它超出当时页的剩下空间,它将被拆分为子记载。记载永久不会块段鸿沟切割,假如单个记载超越默许的段巨细,将会创立具有更大size的段。编码首要引证自[2]Le极彩登录网址-揭秘Prometheus时序数据库规划velDB/RocksDB的预写式日志

记载片段被编码为如下格局

WAL

type标志有以下几种状况

  • 0 页面的其余部分将为空
  • 1 一个完好的记载被编码在单个片段中
  • 2 记载的榜首个片段
  • 3 记载的中心片段
  • 4 记载的终究片段

记载编码 写入预写日志的记载编码如下

Series Records 编码标识一个时序的标签及其仅有ID

Series Records

Sample Records 将样本编码为三元组(series_id,timestamp,value)列表,时序引证和时刻戳在榜首个样本中编码为增量值(delta编码)。榜首行存储开端ID和开端时刻戳,从第二行开端记载榜首个样本

Sample Records

Tombstone Records 将tombstone编码为三元组列表(series_id,min_time,max_time)而且指定删去时序样本的时刻距离

Tombstone Records

小结

了解Prometheus TSDB存储结构规划,有助于了解时序数据处理逻辑。将时刻轴区别为不堆叠的时刻空间,构成小的独立数据库(数据块)。每个数据库包括index,meta.json,chunks及tombstone文件及文件夹,时序按标签对字典次序排序引证Symbol Table(重复数据删去)及时刻戳以Delta-Of-Delta编码格局紧缩数据节约存储资源。依据标签树立时序的倒排索引表,疏忽查询时刻规模之外的数据块,再依据Series ID兼并查询成果,完结高效检索历史数据

推 荐 阅 读

[1] https://github.com/prometheus/tsdb

[2] https://github.com/facebook/rocksdb/wiki/Write-Ahead-Log-File-Format

请关注微信公众号
微信二维码
不容错过
Powered By Z-BlogPHP