Prometheus有着非常高效的时间序列数据存储方法,每个采样数据仅仅占用3.5byte左右空间,上百万条时间序列,30秒间隔,保留60天,大概花了200多G(引用官方PPT)。

接下来让我们看看他的原理。

Prometheus内部主要分为三大块,Retrieval是负责定时去暴露的目标页面上去抓取采样指标数据,Storage是负责将采样数据写磁盘,PromQL是Prometheus提供的查询语言模块。

从最原始的抓取数据上来看,基本是这个样子,timestamp是当前抓取时间戳:

每个Metric name代表了一类的指标,他们可以携带不同的Labels,每个Metric name + Label组合成代表了一条时间序列的数据。

例如图上的数据:

http_requests_total{status="200",method="GET"}
http_requests_total{status="404",method="GET"}

表示了两条不同的时间序列。

在Prometheus的世界里面,所有的数值都是64bit的。每条时间序列里面记录的其实就是64bit timestamp(时间戳) + 64bit value(采样值)。

而对于时间序列的基本特性来说,通常是过去的数据一般是只读的,是不会变更的,当前时间的数据才会可能在写,模式如下图:

根据上面的分析,时间序列的存储似乎可以设计成key-value存储的方式(基于BigTable)。

进一步拆分,可以像下面这样子:

上图的第二条样式就是现在Prometheus内部的表现形式了,__name__是特定的label标签,代表了metric name。

再回顾一下Prometheus的整体流程:

上面提到了K-V存储,当然是使用了LevelDB的引擎,它的特点是顺序读写性能非常高,这是非常符合时间序列的存储的。

为了得到顺序的时间序列哈希索引值,Prometheus是这样处理的:

FNV哈希算法全名为Fowler-Noll-Vo算法,是以三位发明人Glenn Fowler,Landon Curt Noll,Phong Vo的名字来命名的,最早在1991年提出。

FNV能快速hash大量数据并保持较小的冲突率,它的高度分散使它适用于hash一些非常相近的字符串,比如URL,hostname,文件名,text,IP地址等。

1KB Chunks

在Prometheus的世界中,无论是内存还是磁盘,它都是以1KB单位分成块来操作的。(新出的Prometheus 2.0对存储底层做了很大改动,专门针对SSD的写放大进行了优化,提高SSD的读写性能和读写次数等。)

整体流程是 抓取数据 -> 写到head chunk,写满1KB,就再生成新的块,完成的块,是不可再变更的 -> 根据配置文件的设置,有一部份chunk会被保留在内存里,按照LRU算法,定期将块写进磁盘文件内。

注意: 一条时间序列,保存到一个磁盘文件内。

时间序列的保留维护

在Prometheus的启动选项中,有一项storage.local.retention可以设置数据自动保留多长时间,例如24h,表示数据超过24小时内的将会自动清除,类似于zabbix的housekeeping功能。storage.local.series-file-shrink-ratio可以按一定的比例保留数据。

关于Chunk 块编码的剖析

Prometheus 提供三种不同类型的块编码,用户可以在Prometheus启动时指定最新的编码方式,-storage.local.chunk-encoding-version,有效值是0,1,2。

版本0的编码是较老版本上的Prometheus上使用的,新版本已经不再建议使用的。

版本1是当前版本默认提供的编码方式,它相对于0版有较好的压缩能力,而且在一个块内,有较高的访问速度,当然版本0的编码速度是最快的,但是相对版本1,速度优势不是特别明显。

版本2提供了一个更高的压缩比例,编码和解码需要耗更多的CPU,当然,这是取决于查询的数据集有多大。通常如果是较少的查询,仅用于存档的数据,可以使用这种编码。

对比:

Chunk版本号 每个采样点所占字节 耗CPU核 块编码耗时
1 3.3 1.6 2.9s
2 1.3 2.4 4.9s

V0 结构

V1 结构

V2 结构

Prometheus是如何访止数据丢失的呢?例如发生异常关闭或者什么别的情况?它提供了一个Checkpointing功能,对于内存里面的块,Prometheus 使用了一个checkpoint file 去同步写入磁盘,类似于Hbase的WAL原理,当发生crash时,先从checkpoint file去恢复数据。

以上内容是根据Prometheus官方人员的一份PPT摘取,原文件在此:https://files.cnblogs.com/files/vovlie/copyofprometheusstorage1-160127133731.pdf

剖析Prometheus的内部存储机制的更多相关文章

  1. 剖析 Vue.js 内部运行机制 (1)

    1. new Vue() 之后. Vue 会调用 _init 函数进行初始化,也就是这里的 init 过程,它会初始化生命周 期.事件. props. methods. data. computed ...

  2. Windows程序内部运行机制 转自http://www.cnblogs.com/zhili/p/WinMain.html

    一.引言 要想熟练掌握Windows应用程序的开发,首先需要理解Windows平台下程序运行的内部机制,然而在.NET平台下,创建一个Windows桌面程序,只需要简单地选择Windows窗体应用程序 ...

  3. 深入浅出话VC++(1)——Windows程序内部运行机制

    一.引言 要想熟练掌握Windows应用程序的开发,首先需要理解Windows平台下程序运行的内部机制,然而在.NET平台下,创建一个Windows桌面程序,只需要简单地选择Windows窗体应用程序 ...

  4. Memcache存储机制与指令汇总

    1.memcache基本简介 memcached是高性能的分布式内存缓存服务器.一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度.提高可扩展性. Memcach ...

  5. 深度剖析HashMap的数据存储实现原理(看完必懂篇)

    深度剖析HashMap的数据存储实现原理(看完必懂篇) 具体的原理分析可以参考一下两篇文章,有透彻的分析! 参考资料: 1. https://www.jianshu.com/p/17177c12f84 ...

  6. HashMap的内部实现机制,Hash是怎样实现的,什么时候ReHash

    1.HashMap的内部实现机制 HashMap是对数据结构中哈希表(Hash Table)的实现,Hash表又叫散列表.Hash表是根据关键码Key来访问其对应的值Value的数据结构,它通过一个映 ...

  7. Java提高篇——通过分析 JDK 源代码研究 Hash 存储机制

    HashMap 和 HashSet 是 Java Collection Framework 的两个重要成员,其中 HashMap 是 Map 接口的常用实现类,HashSet 是 Set 接口的常用实 ...

  8. Kafka文件的存储机制

    Kafka文件的存储机制 同一个topic下有多个不同的partition,每个partition为一个目录,partition命名的规则是topic的名称加上一个序号,序号从0开始. 每一个part ...

  9. Android--数据持久化之内部存储、Sdcard存储

    前言 之前一直在讲AndroidUI的内容,但是还没有完结,之后会慢慢补充.今天讲讲其他的,关于数据持久化的内容.对于一个应用程序而言,不可避免的要能够对数据进行存储,Android程序也不例外.而在 ...

随机推荐

  1. 201521123031 《Java程序设计》第4周学习总结

    ---恢复内容开始--- 1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. (1)父类只能有一个,即单继承,子类继承父类的全部成员(属性和方法 ...

  2. 201521123025 《Java程序设计》第1周学习总结

    1. 本章学习总结 (1)对JAVA的历史有了初步了解 (2)学会安装JDK和设置JAVA_HOME,PATH,CLASSPATH环境变量 (3)范围:JDK>JRE>JVM 2. 书面作 ...

  3. 201521123057《Java程序设计》第14周学习总结

    0. 本周课程设计发布 Java课程设计 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 数据库基本操作(目前为止主要介绍了表的基本操作) 创建表 CREATE ...

  4. 201521123049 《JAVA程序设计》 第10周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 1.finally 题目4-2 1.1 截图你的提交结果(出 ...

  5. 【化繁为简】非前端开发者的福音---CSS的预处理语言 Less&Sass

    写在前面:        众所周知CSS 是一门非程序式语言,没有变量.函数.SCOPE(作用域),在前期的界面样式设计时,需要书写大量看似没有逻辑的代码,不方便维护及扩展,也不利于重复调用,尤其对于 ...

  6. Lucene第一篇【介绍Lucene、快速入门】

    什么是Lucene?? Lucene是apache软件基金会发布的一个开放源代码的全文检索引擎工具包,由资深全文检索专家Doug Cutting所撰写,它是一个全文检索引擎的架构,提供了完整的创建索引 ...

  7. Struts2开山篇【引入Struts、自定义MyStruts框架】

    前言 这是Strtus的开山篇,主要是引入struts框架-为什么要引入struts,引入struts的好处是什么-. 为什么要引入struts? 首先,在讲解struts之前,我们来看看我们以前写的 ...

  8. 常用Java API(转)

    一. java.io.BufferedReader类(用于从文件中读入一段字符:所属套件:java.io) 1. 构造函数BufferedReader(java.io.FileReader FileR ...

  9. [python学习笔记] pyinstaller打包pyqt5程序无法运行

    问题 pyinstaller打包的pyqt5程序在部分电脑上会失败.用户截图提示下边错误日志 无法定位程序输入点 ucrtbase.terminate 于动态链接库 api-ms-win-crt-ru ...

  10. 最详细的PHP flush()与ob_flush()的区别详解

    buffer ---- flush()buffer是一个内存地址空间,Linux系统默认大小一般为4096(1kb),即一个内存页.主要用于存储速度不同步的设备或者优先级不同的 设备之间传办理数据的区 ...