vmstorage如何将原始指标转换为有组织的历史

vmstorage如何将原始指标转换为有组织的历史

参考自:vmstorage-how-it-handles-data-ingestion

vmstorage是VictoriaMetrics中负责处理长期存储的组件。

image

读取和解析数据

在vmstorage接收到数据之后,并不会直接读取这些数据。首先会检查读并发限速器(限制为2倍的CPU cores),如果读操作过多,则最终会排队等候处理。

vmstorage每次会读取一个block,block的结构如下,包含一个表示block大小的8字节的size字段以及一个body字段。一个block不能超过100MB。

image

有一个边缘场景值得注意:即当vmstorage在速磁盘空间不足时会转变为只读模式。该模式下vmstorage会对接收到的数据响应"read-only ack",并忽略实际内容,vminsert会识别此种确认类型并重发数据(本文后面讨论)。

本阶段中,vmagent仅使用字节流方式读取原始block,并不会对其解析。这些原始字节最终会被拆分为rows进行处理。

image

如果block过大,vmstorage会以chunks为单位进行处理,每次处理10,000 rows数据并将其写入存储。

查找每条metric的TSID

TSID用于表示不同的时间序列,有如下作用:

数据存储优化

  • TSID 在存储时序数据时起到索引的作用。VictoriaMetrics 使用 TSID 来将时间序列数据映射到磁盘的存储位置,从而避免直接存储复杂的指标名称和标签。
  • 通过 TSID,可以快速找到时间序列对应的样本(samples,时间戳与值的组合)并高效地写入或读取数据。

查询加速

  • 当查询某个指标时,VictoriaMetrics 会解析查询中指定的标签或指标名称,通过倒排索引查找与查询条件匹配的 TSID。

每条metric包含如下几个关键部分:

  • 一个metrics名称
  • 一组metrics labels
  • 一个时间戳(毫秒)
  • 一个浮点数表示的metric value
image

在计算metric的TSID之前,首先需要创建"规范的指标名称",即将metric name和labels组合起来,然后按名字的字母顺序排列,目的是防止包含相同labels的metrics,只是因为labels顺序不同而被认为是不同的metric,如metric{instance="host",job="app"}metric{job="app",instance="host"}是相同的metric,只是label顺序不同。

TSID是一种可以表示时间序列的唯一数字,用于快速定位数据。

image

上一节中,vmstorage从block中获取到了原始的metrics(无排序),然后通过查询TSID缓存来判断是否已经存在对应的TSID,如果存在,则直接插入该指标:

image

如果不存在,则需要向IndexDB查询,由于涉及随机磁盘查询,因此这是一个比较慢的过程。在查找成功后缓存结果。

如果不存在,则说明这是一个全新的metric。此时,系统需要生成一个新的TSID,并将其同时注册到内存缓存和IndexDB,包括如下步骤:

  • 将"规范指标名称"映射到新的TSID
  • 设置反向映射,这样TSID可以指向"规范指标名称"
  • 倒排索引包含"规范指标名称"中的每个label,可以帮助系统在使用标签过滤时快速查询时序数据
  • 创建以天为单位的索引,用于优化按时间范围查找数据的场景。
image

注册新的时间序列涉及向磁盘写入与之相关的所有信息,该过程可能会拖慢整个系统,特别是当metric拥有很多labels或非常长的labels时。

这也是为什么要关注churn rate的原因。vmstorage可以按小时 (-storage.maxHourlySeries)和天(-storage.maxDailySeries)限制新创建的时序数据总量。

向内存缓冲插入数据

一旦注册好TSID,VictoriaMetrics就可以处理实际的数据样本,包括TSID、时间戳、值等,并将其放入一个内存缓冲(称为"raw-row shards"),且一个partition(表示一个月的数据)的shards数目等于CPU cores的数目。例如,机器有4 cores,则每个月的数据有4个shards,每个shards最多可以有8 MB的数据,约149,796 rows。

如果shard被填满,则这些rows会被推入一个称为"pending series"的地方,等待被处理成“LSM part”,并最终写入磁盘。只有刷新到LSM part的数据才能被查询到,之后便完成了本block的数据处理,可以开始处理下一个block。

image

数据如何写入磁盘

在如下两种情况中,Shard缓冲会刷新数据:

  1. 当缓冲达到阈值(约120MB),刷新pending series
  2. 如果距上一次刷新超过2s,则系统会自动刷新 pending series和raw-row shards

在刷新过程中,数据会转换为一个LSM part,LSM part中的项会根据TSID和时间戳进行排序。

LSM Parts的类型

每个partition(涵盖一个月的数据)会将其数据组织为3种LSM parts类型:

  • 内存 part:存放raw-row shards首次刷新后的数据,此时数据可以被搜索和查询
  • Small part:比内存part稍大,存储在持久化磁盘上
  • big part:最大的parts,存储在磁盘上

vmstorage同一时间最多可以持有60个内存parts,占用约10%的系统内存。例如,vmstorage内存为10GB,则内存parts占1GB,每个part约1MB~17MB。

image

随着数据的写入,会创建越来越多的parts,当LSM parts过多(无论是内存还是磁盘)时,每个查询(如来自grafana的查询)都需要扫描并合并这些parts,可能会拖慢系统。

为了防止上述问题,vmstorage依赖两个关键处理:刷新和合并。

  • 刷新:将所有内存parts刷新到磁盘的small parts。每5s,vmstorage(-inmemoryDataFlushInterval)会将内存parts刷新到基于磁盘或文件的parts上。
  • 合并:将多个parts合并为更高效的存储。这并不意味着将所有small parts合并为big parts,而是将一部分small parts合并为稍大一些的small parts

合并过程

合并并不是固定调度的。只要有parts累积,系统就会尝试合并这些parts,将内存parts合并为较大的内存part,将small parts合并为较大的small part,将big parts合并为较大的big part。

small parts不能超过10MB,big parts最大可以占用大约剩余磁盘空间/4,但不能超过1TB。注意small parts和big parts只是系统在合并过程中评估出来的需要创建的part类型,并不是说small parts一定小于big parts。

small parts合并的结果最终会被写入磁盘,该过程中会执行去重操作。

去重是确认并移除那些几乎相等,但记录时间略微不同的时间点。通常发生在出于冗余或可靠性目的,而使用两个或多个监控系统将相同指标并发往同一个存储的场景。

image

默认关闭去重,可以通过-dedup.minScrapeInterval启用去重功能。

Retention, Free Disk Space Guard和 Downsampling

vmstorage的默认回收周期是1个月。需要注意的是,每个part包含很多样本,只要有一个样本在回收周期内,则必须保留整个part。

image

Free Disk Space Watcher: Read Only Mode

一开始提到,在磁盘空间不足的情况下,vmstorage会进入read-only模式,该模式下,vminset会接收到数据发送的确认信息,但vmstorage会忽略掉这些数据。此时vmstorage仍然能够提供查询请求,但停止接收任何写数据。一旦释放了磁盘空间(-storage.minFreeDiskSpaceBytes,默认10MB),vmstorage会退出read-only模式。

Partition的结构

无论是内存parts,small parts还是big parts,其数据都是列模式,即TSID、时间戳和值都不会组合在一个记录中,而是被分散到不同的列,每一列都保存在各自的文件中。

  • 所有 TSIDs 都保存在 index.bin.
  • 所有时间戳都保存在 timestamps.bin.
  • 所有值都保存在 values.bin.

对于内存parts,这些列结构已经就绪,可以直接刷新到基于文件的parts中。

image

列模式便于压缩和快速查找。 timestamps.binvalues.bin中的每个block表示单个TSID行,一个block最多可以有8192 行。

index.bin的每一行包括多个block首部,一个block首部包含:

  • block的TSID
  • block的行数
  • block在timestamps.binvalues.bin中的位置
image
posted @ 2024-12-30 09:46  charlieroro  阅读(65)  评论(0编辑  收藏  举报