prometheus源码分析:checkpoint

什么是checkpoint?

checkout是wal中一个目录:

# ls -alh
-rw-r--r--  1 root root  11M 12月 14 17:00 00000999
-rw-r--r--  1 root root  11M 12月 14 19:00 00001000
-rw-r--r--  1 root root 2.1M 12月 14 19:22 00001001
drwxr-xr-x  2 root root   22 12月 14 19:00 checkpoint.00000998
# ls -alh checkpoint.00000998/
-rw-r--r-- 1 root root 384K 12月 14 19:00 00000000

prometheus写入指标时,将指标写入内存和wal,然后返回写入成功。wal保证了prometheus crash-free的能力。

prometheus内存中缓存了最近2hour的指标数据,然后2hour的数据被压缩成block,存储在硬盘上;此时这2hour的WAL数据就可以被删除了。

checkpoint就是用来清理wal日志的。

当2hour的内存数据被压缩成block存储至硬盘时:

  • 该时间之前的wal日志就可以删除了;因为已经持久化到硬盘了,即使prometheus实例宕掉,也不会丢数据;
  • 此时,prometheus生成一个checkpoint,进行wal日志的清理;

checkpoint的整体流程

假设之前checkpoint为checkpoint.m,在segment n处,进行block的存储,此时checkpoint的流程如下:

  • 读取文件:

    • checkpoint.m目录下所有文件
    • segment m+1~n之间的所有文件
  • 遍历文件内容,将block之后的series和samples数据,写入checkpoint.n目录;

image.png

checkpoint生成之后,会删除以下文件:

  • 删除segment.n之前的segment;
  • 删除之前的checkpoint:< n(如checkpoint.m);

checkpoint的代码分析

入口代码:

// tsdb/head.go
// Truncate removes old data before mint from the head.
func (h *Head) Truncate(mint int64) (err error) {
    ....
    // 生成新的checkpoint
    wal.Checkpoint(h.logger, h.wal, first, last, keep, mint)
    // 将segment.n之前的segment删掉
    err := h.wal.Truncate(last + 1)
    // 将之前的checkpoint删掉: < last
    err := wal.DeleteCheckpoints(h.wal.Dir(), last)
}

checkpoint的过程代码:

// tsdb/wal/checkpoint.go
// from/to:segment id
// keep:用于判断series是否保留
// mint: sample.timestamp >= mint时保留
func Checkpoint(logger log.Logger, w *WAL, from, to int, keep func(id uint64) bool, mint int64) (*CheckpointStats, error) {
    var sgmReader io.ReadCloser
    {
        var sgmRange []SegmentRange
        // 读checkpoint.m
        dir, idx, err := LastCheckpoint(w.Dir())
        last := idx + 1
        if err == nil {
            from = last
            sgmRange = append(sgmRange, SegmentRange{Dir: dir, Last: math.MaxInt32})
        }
        // 读segment.m+1 ~ n
        sgmRange = append(sgmRange, SegmentRange{Dir: w.Dir(), First: from, Last: to})
        sgmReader, err = NewSegmentsRangeReader(sgmRange...)
    }
    
    r := NewReader(sgmReader)
    // 遍历所有的record
    for r.Next() {
        rec := r.Record()
        switch dec.Type(rec) {
        case record.Series:
            series, err = dec.Series(rec, series)
            for _, s := range series {
                // series是否保留
                if keep(s.Ref) {
                    repl = append(repl, s)
                }
            }
            // 写入buf
            if len(repl) > 0 {
                buf = enc.Series(repl, buf)
            }
        case record.Samples:
            samples, err = dec.Samples(rec, samples)
            repl := samples[:0]
            for _, s := range samples {
                // timestamp >= mint需要保留
                if s.T >= mint {
                    repl = append(repl, s)
                }
            }
            // 写入buf
            if len(repl) > 0 {
                buf = enc.Samples(repl, buf)
            }
        }
        recs = append(recs, buf[start:])
        // Flush records in 1 MB increments.
        if len(buf) > 1*1024*1024 {
            // 写入checkpoint.n目录中
            if err := cp.Log(recs...); err != nil {
                return nil, errors.Wrap(err, "flush records")
            }
            buf, recs = buf[:0], recs[:0]
        }
    }
    // Flush remaining records.
    err := cp.Log(recs...)
    err := cp.Close();
    ......
}

参考:

1.https://ganeshvernekar.com/bl...

38 声望
19 粉丝
0 条评论
推荐阅读
HPA使用自定义指标进行扩缩容
kubernetes引入HPA进行扩缩容,HPA可以根据指标(metrics),自动对workload进行弹性的扩缩容。HPA资源在autocaling这个group下面,HPA分为v1和v2版本:HPA v1仅支持基于CPU指标的伸缩;HPA v2beta1引入了基于Memor...

a朋阅读 1

Prometheus的使用
在Prometheus的架构设计中,Prometheus Server 并不直接服务监控特定的目标,其主要任务负责数据的收集,存储并且对外提供数据查询支持。因此为了能够能够监控到某些东西,如主机的CPU使用率,我们需要使用到Expo...

代码的路2阅读 365

自定义数据采集export到prometheus使用 Flask实现
如图 想要取到 url get请求的值,使用prometheus blackbox 无法获取,所以考虑使用flask自定义exporter 获取

台湾省委书记阅读 931

封面图
国产 ETL工具 ETL产品 数据交换系统 ETL工具选型 需要考虑哪些因素
多数软件又为什么逐渐国产化? 长期以来,国内数据技术都由海外厂商主导。然而随着国际竞争环境日益激烈,争端所引发的技术卡脖子事件频发,面对特殊的大环境,全球化带来的科技创新共同体背后,国家IT产业实现自...

weigeonlyyou阅读 884

封面图
prometheus pushgateway使用及源码分析
一.Pushgateway是什么pushgatway是prometheus社区推出的一个推送指标的组件,主要应用在:短生命周期(short-lived)或者批任务(batch jobs)的资源/作业的指标;prometheus无法拉取到(网络原因)的target的指标;作...

a朋阅读 763

开源signoz实现可观测性的分析
Signoz是一个开源的APM(Application Performance Management),它是应用可观测性的一个实践,使用OpenTelemetry协议,将traces/metrics/log融合在一起。

a朋阅读 731

如何使用 Blackbox Exporter 监控 URL?
监控域名和 URL 是可观察性的一个重要方面,主要用于诊断可用性问题。接下来会详细介绍如何使用 Blackbox Exporter 和 Prometheus 在 Kubernetes 中实现 URL 监控。

东风微鸣云原生阅读 673

38 声望
19 粉丝
宣传栏