zoukankan      html  css  js  c++  java
  • Prometheus TSDB分析

    Prometheus TSDB分析

    概述

    Prometheus是著名开源监控项目,其监控任务调度给具体的服务器,该服务器到目标上抓取监控数据,然后保存在本地的TSDB中。自定义强大的PromQL语言查询实时和历史时序数据,支持丰富的查询组合。
    Prometheus 1.0版本的TSDB(V2存储引擎)基于LevelDB,并且使用了和Facebook Gorilla一样的压缩算法,能够将16个字节的数据点压缩到平均1.37个字节。
    Prometheus 2.0版本引入了全新的V3存储引擎,提供了更高的写入和查询性能。本文主要分析该存储引擎设计思路。

    设计思路

    Prometheus将Timeseries数据按2小时一个block进行存储。每个block由一个目录组成,该目录里包含:一个或者多个chunk文件(保存timeseries数据)、一个metadata文件、一个index文件(通过metric name和labels查找timeseries数据在chunk文件的位置)。最新写入的数据保存在内存block中,达到2小时后写入磁盘。为了防止程序崩溃导致数据丢失,实现了WAL(write-ahead-log)机制,将timeseries原始数据追加写入log中进行持久化。删除timeseries时,删除条目会记录在独立的tombstone文件中,而不是立即从chunk文件删除。
    这些2小时的block会在后台压缩成更大的block,数据压缩合并成更高level的block文件后删除低level的block文件。这个和leveldb、rocksdb等LSM树的思路一致。
    这些设计和Gorilla的设计高度相似,所以Prometheus几乎就是等于一个缓存TSDB。它本地存储的特点决定了它不能用于long-term数据存储,只能用于短期窗口的timeseries数据保存和查询,并且不具有高可用性(宕机会导致历史数据无法读取)。
    Prometheus本地存储的局限性,所以它提供了API接口用于和long-term存储集成,将数据保存到远程TSDB上。该API接口使用自定义的protocol buffer over HTTP并且并不稳定,后续考虑切换为gRPC。

    磁盘文件结构

    内存中的block

    内存中的block数据未刷盘时,block目录下面主要保存wal文件。

    ./data/01BKGV7JBM69T2G1BGBGM6KB12
    ./data/01BKGV7JBM69T2G1BGBGM6KB12/meta.json
    ./data/01BKGV7JBM69T2G1BGBGM6KB12/wal/000002
    ./data/01BKGV7JBM69T2G1BGBGM6KB12/wal/000001
    

    持久化的block

    持久化的block目录下wal文件被删除,timeseries数据保存在chunk文件里。index用于索引timeseries在wal文件里的位置。

    ./data/01BKGV7JC0RY8A6MACW02A2PJD
    ./data/01BKGV7JC0RY8A6MACW02A2PJD/meta.json
    ./data/01BKGV7JC0RY8A6MACW02A2PJD/index
    ./data/01BKGV7JC0RY8A6MACW02A2PJD/chunks
    ./data/01BKGV7JC0RY8A6MACW02A2PJD/chunks/000001
    ./data/01BKGV7JC0RY8A6MACW02A2PJD/tombstones
    

    mmap

    使用mmap读取压缩合并后的大文件(不占用太多句柄),建立进程虚拟地址和文件偏移的映射关系,只有在查询读取对应的位置时才将数据真正读到物理内存。绕过文件系统page cache,减少了一次数据拷贝。查询结束后,对应内存由Linux系统根据内存压力情况自动进行回收,在回收之前可用于下一次查询命中。因此使用mmap自动管理查询所需的的内存缓存,具有管理简单,处理高效的优势。
    从这里也可以看出,它并不是完全基于内存的TSDB,和Gorilla的区别在于查询历史数据需要读取磁盘文件。

    Compaction

    Compaction主要操作包括合并block、删除过期数据、重构chunk数据。其中合并多个block成为更大的block,可以有效减少block个数,当查询覆盖的时间范围较长时,避免需要合并很多block的查询结果。
    为提高删除效率,删除时序数据时,会记录删除的位置,只有block所有数据都需要删除时,才将block整个目录删除。因此block合并的大小也需要进行限制,避免保留了过多已删除空间(额外的空间占用)。比较好的方法是根据数据保留时长,按百分比(如10%)计算block的最大时长。

    Inverted Index

    Inverted Index(倒排索引)基于其内容的子集提供数据项的快速查找。简而言之,我可以查看所有标签为app=“nginx”的数据,而不必遍历每一个timeseries,并检查是否包含该标签。
    为此,每个时间序列key被分配一个唯一的ID,通过它可以在恒定的时间内检索,在这种情况下,ID就是正向索引。
    举个栗子:如ID为9,10,29的series包含label app="nginx",则lable "nginx"的倒排索引为[9,10,29]用于快速查询包含该label的series。

    性能

    在文章Writing a Time Series Database from Scratch里,作者给出了benchmark测试结果为Macbook Pro上写入达到2000万每秒。这个数据比Gorilla论文中的目标7亿次写入每分钟(1000千多万每秒)提供了更高的单机性能。

    参考

    Writing a Time Series Database from Scratch
    Prometheus官方介绍
    时间序列数据的存储和计算 - 开源时序数据库解析(四)

  • 相关阅读:
    Digital Video Stabilization and Rolling Shutter Correction using Gyroscope 论文笔记
    Distortion-Free Wide-Angle Portraits on Camera Phones 论文笔记
    Panorama Stitching on Mobile
    Natural Image Stitching with the Global Similarity Prior 论文笔记 (三)
    Natural Image Stitching with the Global Similarity Prior 论文笔记(二)
    Natural Image Stitching with the Global Similarity Prior 论文笔记(一)
    ADCensus Stereo Matching 笔记
    Efficient Large-Scale Stereo Matching论文解析
    Setting up caffe on Ubuntu
    Kubernetes配置Secret访问Harbor私有镜像仓库
  • 原文地址:https://www.cnblogs.com/jimbo17/p/8659119.html
Copyright © 2011-2022 走看看