directoryinfo 读取 映射磁盘_Prometheus TSDB (第三部分): 磁盘Head Chunks的内存映射

简介

在TSDB博客系列的第1部分中,我提到一旦chunk“已满”,就将其刷新到磁盘和映射的内存中。这有助于减少Head块的内存占用,并有助于加快我们在第2部分中讨论的WAL重播。在本博文中,我们将更深入地探讨Prometheus中的WAL设计方式。

由于这是我编写的Prometheus TSDB博客系列的一部分,建议您阅读第1部分,以了解这些内存映射块在TSDB(或Head块)中的位置,第2部分了解WAL重播。

写 chunks

从第1部分重新开始,当一个chunk已满时,我们剪切了一个新chunk,而较旧的chunk变得不可变,只能从中读取(下面的黄色块)。

3cfbc1da6aea0061a45abb0f32601eef.png

而不是将其存储在内存中,我们将其刷新到磁盘并存储引用以供以后访问。

6bce4984235d355483697e5496d6aa6e.png

此刷新的chunk是磁盘中的内存映射chunk。不变性是最重要的因素,否则对于每个sample而言,重写压缩chunk的效率都太低。

在磁盘上的格式

该格式也可以在GitHub上找到。

File

这些chunks保留在其自己的目录中,称为chunks_head,其文件序列类似于WAL(除了以1开头)。例如:

data
├── chunks_head
|   ├── 000001
|   └── 000002
└── wal
    ├── checkpoint.000003
    |   ├── 000000
    |   └── 000001
    ├── 000004
    └── 000005

文件的最大大小保持为128MiB。现在深入研究单个文件,该文件包含8B标头。

┌──────────────────────────────┐
│  magic(0x0130BC91) <4 byte>  │
├──────────────────────────────┤
│    version(1) <1 byte>       │
├──────────────────────────────┤
│    padding(0) <3 byte>       │
├──────────────────────────────┤
│ ┌──────────────────────────┐ │
│ │         Chunk 1          │ │
│ ├──────────────────────────┤ │
│ │          ...             │ │
│ ├──────────────────────────┤ │
│ │         Chunk N          │ │
│ └──────────────────────────┘ │
└──────────────────────────────┘

Magic Number是可以唯一地将文件标识为内存映射的head chunk文件的任何数字。在实现此功能时,我将其设置为我的生日:)。Chunk Format告诉我们如何解码文件中的chunk。额外的填充是为了允许我们将来可能需要的任何head文件选项。
在文件头之后,是chunks。

Chunks

一个大chunk看起来像这样:

┌─────────────────────┬───────────────────────┬───────────────────────┬───────────────────┬───────────────┬──────────────┬────────────────┐
| series ref <8 byte> | mint <8 byte, uint64> | maxt <8 byte, uint64> | encoding <1 byte> | len <uvarint> | data <bytes> │ CRC32 <4 byte> │
└─────────────────────┴───────────────────────┴───────────────────────┴───────────────────┴───────────────┴──────────────┴────────────────┘

series ref与我们在第2部分中讨论的系列引用相同,它是用于访问内存中系列的系列ID。 mintmaxt是在chunk sample中看到的最小和最大时间戳。encoding是用于压缩块的编码。 len是此后的字节数,data是压缩块的实际字节数。CRC32是上述chunk内容的校验和,用于检查数据的完整性。

读 chunks

对于每个chunk,Head块都会将该chunk的mint和maxt以及引用存储在内存中以对其进行访问。
引用长度为8个字节。前4个字节指示chunk所在的文件编号,后4个字节指示chunk起始位置的文件偏移量(即系列ref的第一个字节)。如果该chunk位于文件00093中,并且series ref从文件中的字节偏移量1234开始,则该chunk的引用将为(93 << 32)|。 1234(左移位,然后按位或)。
我们将mint和maxt存储在Head中,以便我们可以选择chunk而不必查看磁盘。当我们必须访问chunk时,我们仅使用引用访问编码和chunk数据。
在代码中,文件看起来像又一个字节切片(每个文件一个切片),并在某个索引处访问该切片以获取chunk数据,而OS将内存中的切片映射到磁盘。磁盘的内存映射是一项操作系统功能,仅将磁盘的一部分读取到正在访问的内存中,而不是整个文件。

在启动时重播

在第2部分中,我们讨论了WAL重播,其中重播每个单独的sample以重新创建压缩块。现在,我们已经在磁盘上压缩了完整的chunks,我们不需要重新创建这些chunks,而仍然需要从WAL创建不完整的chunks。现在,使用磁盘中的这些内存映射chunks,可以按以下方式进行重播。

在启动时,首先我们遍历chunks_head目录中的所有chunks,并在内存中构建series ref(chunk引用列表以及属于该series引用的mint和maxt的映射)。

然后,我们继续进行第2部分中所述的WAL重播,但进行少量修改:

  • 当我们遇到“series”记录时,在创建series之后,我们在上图中查找该series的引用,并且如果存在任何内存映射chunks,则将该列表附加到该series中。
  • 当我们遇到“sample”记录时,如果该sample的相应chunks具有任何内存映射的chunk,并且该sample属于其涵盖的时间范围,那么我们将跳过该sample。如果不是,那么我们将sample提取到Head块中。

增强功能

这种额外的复杂性有什么用,而我们却可以避免将chunk存储在内存和WAL中了?该功能是在2020年最近添加的,因此让我们看看它带来了什么。

节省内存

如果必须将chunk存储在内存中,则它可能需要120到200字节之间的任意空间(甚至更多,具体取决于sample的可压缩性)。现在,将其替换为24个字节-chunk引用,最小时间和最大时间各8个字节。
虽然这听起来像是减少80-90%的内存,但实际情况却有所不同。 Head还需要存储更多东西,例如内存索引,所有符号(标签值)等,以及占用一些内存的TSDB的其他部分。
在现实世界中,我们可以看到内存占用量减少了15-50%,具体取决于抓取sample的速率和创建新series的速率。要注意的另一件事是,如果您正在运行一些查询,这些查询涉及磁盘上的许多这些chunk,则需要将它们加载到要处理的内存中。因此,这并不是绝对减少峰值内存使用量。

快速启动

WAL重播是启动最慢的部分。主要是,(1)从磁盘解码WAL记录和(2)从各个sample重建压缩chunk是重放的缓慢部分。内存映射chunks的迭代相对较快。

我们无法避免对记录进行解码,因为我们需要检查所有记录。如您在上面的重放中所见,我们正在跳过内存映射chunks范围内的samples。在这里,我们避免重新创建那些完全压缩的chunk,从而节省了重放时间。可以将启动时间减少15-30%。

垃圾回收

内存中的垃圾回收发生在Head截断期间,在该截断期间,它只是丢弃了比截断时间T更早的chunk的引用。但是文件仍然存在于磁盘上。与WAL段一样,我们还需要定期删除旧的m映射文件。
对于每个内存映射的chunk文件,我们将文件中所有chunks中的绝对最大时间存储在内存中。对于实时文件(当前正在其中写入chunk的文件),我们在添加新chunk时会更新内存中的最大时间。在重新启动期间,当我们迭代所有内存映射的chunk时,我们将恢复内存中文件的最大时间。
因此,当时间T之前的数据发生Head截断时,我们在时间T上对这些文件调用截断。最大时间低于T的文件(实时文件除外)在此时保留顺序(如果文件已删除)是5、6、7、8,并且如果文件5和7在时间T之后,则仅删除5,其余序列为6、7、8)。
截断后,我们关闭实时文件并开始一个新文件,因为在小容量和小设置的情况下,可能需要很多时间才能达到文件的最大大小。因此,在此处rotate文件将有助于在下一次截断期间删除旧chunk。

PS: 本文属于翻译,原文

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于PyTorch的Embedding和LSTM的自动写诗实验LSTM (Long Short-Term Memory) 是一种特殊的循环神经网络(RNN)架构,用于处理具有长期依赖关系的序列数据。传统的RNN在处理长序列时往往会遇到梯度消失或梯度爆炸的问题,导致无法有效地捕捉长期依赖。LSTM通过引入门控机制(Gating Mechanism)和记忆单元(Memory Cell)来克服这些问题。 以下是LSTM的基本结构和主要组件: 记忆单元(Memory Cell):记忆单元是LSTM的核心,用于存储长期信息。它像一个传送带一样,在整个链上运行,只有一些小的线性交互。信息很容易地在其上保持不变。 输入门(Input Gate):输入门决定了哪些新的信息会被加入到记忆单元中。它由当前时刻的输入和上一时刻的隐藏状态共同决定。 遗忘门(Forget Gate):遗忘门决定了哪些信息会从记忆单元中被丢弃或遗忘。它也由当前时刻的输入和上一时刻的隐藏状态共同决定。 输出门(Output Gate):输出门决定了哪些信息会从记忆单元中输出到当前时刻的隐藏状态中。同样地,它也由当前时刻的输入和上一时刻的隐藏状态共同决定。 LSTM的计算过程可以大致描述为: 通过遗忘门决定从记忆单元中丢弃哪些信息。 通过输入门决定哪些新的信息会被加入到记忆单元中。 更新记忆单元的状态。 通过输出门决定哪些信息会从记忆单元中输出到当前时刻的隐藏状态中。 由于LSTM能够有效地处理长期依赖关系,它在许多序列建模任务中都取得了很好的效果,如语音识别、文本生成、机器翻译、时序预测等。
CSDN IT狂飙上传的代码均可运行,功能ok的情况下才上传的,直接替换数据即可使用,小白也能轻松上手 【资源说明】 基于MATLAB实现的这个代码主要是研究手写数字的识别效率,用卷积神经网络算法来实现,用的是官方手写字体数据,能够显现百分之九十以上的识别率+使用说明文档 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2020b;若运行有误,根据提示GPT修改;若不会,私信博主(问题描述要详细); 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可后台私信博主; 4.1 期刊或参考文献复现 4.2 Matlab程序定制 4.3 科研合作 功率谱估计: 故障诊断分析: 雷达通信:雷达LFM、MIMO、成像、定位、干扰、检测、信号分析、脉冲压缩 滤波估计:SOC估计 目标定位:WSN定位、滤波跟踪、目标定位 生物电信号:肌电信号EMG、脑电信号EEG、心电信号ECG 通信系统:DOA估计、编码译码、变分模态分解、管道泄漏、滤波器、数字信号处理+传输+分析+去噪、数字信号调制、误码率、信号估计、DTMF、信号检测识别融合、LEACH协议、信号检测、水声通信 5、欢迎下载,沟通交流,互相学习,共同进步!
基于LSTM+CNN的自然语言处理,基于单维LSTM、多维LSTM时序预测算法和多元线性回归算法的预测模型LSTM (Long Short-Term Memory) 是一种特殊的循环神经网络(RNN)架构,用于处理具有长期依赖关系的序列数据。传统的RNN在处理长序列时往往会遇到梯度消失或梯度爆炸的问题,导致无法有效地捕捉长期依赖。LSTM通过引入门控机制(Gating Mechanism)和记忆单元(Memory Cell)来克服这些问题。 以下是LSTM的基本结构和主要组件: 记忆单元(Memory Cell):记忆单元是LSTM的核心,用于存储长期信息。它像一个传送带一样,在整个链上运行,只有一些小的线性交互。信息很容易地在其上保持不变。 输入门(Input Gate):输入门决定了哪些新的信息会被加入到记忆单元中。它由当前时刻的输入和上一时刻的隐藏状态共同决定。 遗忘门(Forget Gate):遗忘门决定了哪些信息会从记忆单元中被丢弃或遗忘。它也由当前时刻的输入和上一时刻的隐藏状态共同决定。 输出门(Output Gate):输出门决定了哪些信息会从记忆单元中输出到当前时刻的隐藏状态中。同样地,它也由当前时刻的输入和上一时刻的隐藏状态共同决定。 LSTM的计算过程可以大致描述为: 通过遗忘门决定从记忆单元中丢弃哪些信息。 通过输入门决定哪些新的信息会被加入到记忆单元中。 更新记忆单元的状态。 通过输出门决定哪些信息会从记忆单元中输出到当前时刻的隐藏状态中。 由于LSTM能够有效地处理长期依赖关系,它在许多序列建模任务中都取得了很好的效果,如语音识别、文本生成、机器翻译、时序预测等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值