首页 > 其他分享 >vmstorage如何将原始指标转换为有组织的历史

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

时间:2024-12-30 09:55:46浏览次数:1  
标签:vmstorage 转换 TSID parts 原始 内存 part block

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

标签:vmstorage,转换,TSID,parts,原始,内存,part,block
From: https://www.cnblogs.com/charlieroro/p/18632385

相关文章

  • 上市公司-技术多元化、知识多元化(1990-2022年 原始数据,代码do文件,参考文献,最终结果)
    上市公司-技术多元化、知识多元化(1990-2022年原始数据,代码do文件,参考文献,最终结果).rar  https://download.csdn.net/download/2401_84585615/90025529          https://download.csdn.net/download/2401_84585615/90025529        ......
  • go语言:实现volume conversions体积转换算法(附完整源码)
    go语言:实现volumeconversions体积转换算法代码说明:使用说明:下面是一个用Go语言实现的体积转换算法的示例代码。这个程序可以将不同单位的体积进行转换,包括升(L)、毫升(mL)、立方米(m³)、立方厘米(cm³)和加仑(gal)。你可以根据需要扩展或修改此代码。packagemainimpo......
  • 将一个浮点数或任何其他类型的值赋给 unsigned char 类型的变量时,C语言进行类型转换
    C语言中,unsignefcharTemp_Val;Temp_Val=(unsignefchar)rd_temperature();若rd_temperature()函数返回51.7,则Temp_Val等于多少?在C语言中,unsignedchar 类型通常用于存储0到255之间的无符号整数。当你将一个浮点数或任何其他类型的值赋给 unsignedchar 类型的变量时,C语言......
  • [20241227]字符串转换成列表问题.txt
    [20241227]字符串转换成列表问题.txt--//开发经常会写sql语句,经常会出现in('111122','1111113'..,'2222111')之类的情况,一般语句in里面内容经常变化,导致无法使--//用绑定变量。--//实际上以前例子,通过建立type,然后建立函数将拼接的字符串转换为数字或者字符串列表。--//前几天有......
  • 雷达坐标转换公式(二)
    转自:https://gitcode.com/Open-source-documentation-tutorial/7da0b/overview......
  • C++ 中将 float 类型转换为 std::string
    在C++中,可以使用多种方法将 float 类型转换为 std::string 类型。以下是常用的几种方法:方法1:std::to_string (C++11及以上)这是最简单的方法之一,直接使用 std::to_string。#include<iostream>#include<string>intmain(){floatnum=123.456f;std::......
  • SY8089 兼容代替 MT3520B SOT23-5 5.5V、2A、2MHz,同步降压转换器
    产品描述SY8089是一种高效的,直流到直流的降压开关调节器,能够提供高达2A的输出电流。该设备的工作电压范围为从2.6V到5.5V的输入电压范围,并提供从0.6V到VIN的输出电压。在2MHz的固定频率下工作,允许使用小的外部组件,如陶瓷输入和输出帽,以及小的电感器,同时仍然提供低输出波纹。这......
  • LeetCode-字符串转换整数(008)
    一.题目描述请你来实现一个 myAtoi(strings) 函数,使其能将字符串转换成一个32位有符号整数。函数 myAtoi(strings) 的算法如下:空格:读入字符串并丢弃无用的前导空格("")符号:检查下一个字符(假设还未到字符末尾)为 '-' 还是 '+'。如果两者都不存在,则假定结果为正。......
  • 使用js写一个方法,将字符串中单词的第一个字母转换为大写
    在JavaScript中,你可以使用split(),map(),和join()方法,配合正则表达式来实现这个功能。以下是一个简单的函数,该函数接受一个字符串作为参数,并返回一个新的字符串,其中每个单词的首字母都被转换为大写:functioncapitalizeFirstLetterOfEachWord(str){returnstr......
  • 嵌入式单片机模数转换控制与实现详解
    第一:模数转换的概述模数转换的概念   一般在电路中,信号分为两种,一种是模拟信号,一种是数字信号,绝大多数传感器采集的都是模拟信号,如温度、湿度、烟雾浓度、亮度.......,但是对于计算机需要处理的数字信号,那就需要利用电路把模拟信号转换为数字信号,这个转换的过程需要利......