Prometheus 监控体系原理:Pull 模式与 TSDB 时序数据库

Prometheus 监控体系原理:Pull 模式与 TSDB 时序数据库

深入剖析 Prometheus 核心架构,从 Pull 拉取模式到 TSDB 时序数据库的内部实现,结合源码解析与实践案例

目录

  • [一、Prometheus 架构概览](#一、Prometheus 架构概览)
  • [二、Pull 模式原理与优势](#二、Pull 模式原理与优势)
  • [三、TSDB 时序数据库架构](#三、TSDB 时序数据库架构)
  • [四、Head Block 内存存储机制](#四、Head Block 内存存储机制)
  • [五、WAL 与数据持久化](#五、WAL 与数据持久化)
  • [六、Block 压缩与查询优化](#六、Block 压缩与查询优化)
  • 七、性能优化最佳实践

一、Prometheus 架构概览

Prometheus 是一套开源的监控告警系统,采用 Pull 拉取模式采集数据,并内置专用的时序数据库(TSDB)进行存储。其核心架构设计体现了"简单即是美"的理念。

1.1 核心组件架构

外部组件
Prometheus 服务器
拉取
查询
告警
Retrieval 采集器
TSDB 时序数据库
HTTP Server API
PromQL 引擎
Service Discovery
目标抓取 Target
Pushgateway
Alertmanager
Exporter
Grafana

1.2 数据流向全景图

组件 职责 数据流方向
Retrieval 定期拉取目标指标 Pull → Exporter
TSDB 存储时序数据 接收 → 落盘
PromQL 查询与分析 TSDB → 结果
Alertmanager 告警路由与分组 PromQL → 通知

User Alertmanager PromQL TSDB Exporter Prometheus User Alertmanager PromQL TSDB Exporter Prometheus 查询与告警流程 1. HTTP GET /metrics 2. 返回指标文本 3. 写入时序数据 4. 内存 + WAL 落盘 5. PromQL 查询 6. 返回时序数据 7. 触发告警规则 8. 发送通知

1.3 与传统监控对比

特性 Prometheus (Pull) 传统监控 (Push)
数据采集 服务端主动拉取 客户端主动上报
服务发现 原生支持 (Consul/K8s) 需额外配置
目标健康 拉取失败即视为宕机 心跳机制
扩展性 水平扩展需联邦/分片 天然支持分布式
数据模型 多维时序 通常较简单

二、Pull 模式原理与优势

2.1 Pull 模式工作流程

Pull 模式是 Prometheus 最核心的设计理念之一,与传统 Push 模式有本质区别。
定时执行
配置文件

scrape_configs
服务发现

Service Discovery
生成目标列表

Target List
Scrape Loop

抓取循环
HTTP GET /metrics

拉取指标
解析文本格式

Parse Metrics
写入 TSDB

Append to TSDB

关键源码位置(Prometheus v2.55.0):

go 复制代码
// 文件: scrape/manager.go
// ScrapeManager 管理所有抓取任务
type ScrapeManager struct {
    scrapeConfigs  map[string]*config.ScrapeConfig
    targetSets     map[string]*TargetSet
    scrapePools    map[string]*scrapePool
    logger         *slog.Logger
}

// 每 1 秒执行一次抓取循环
func (sm *ScrapeManager) Run(ctx context.Context) error {
    ticker := time.NewTicker(time.Second)
    defer ticker.Stop()
    
    for {
        select {
        case <-ticker.C:
            sm.sync() // 同步并执行抓取
        case <-ctx.Done():
            return nil
        }
    }
}

2.2 Scrape Loop 抓取循环详解

go 复制代码
// 文件: scrape/scrape.go
// Scraper 执行单次抓取
type scraper struct {
    client  *http.Client
    timeout time.Duration
}

func (s *scraper) scrape(ctx context.Context, target *Target) error {
    // 1. 构建 HTTP 请求
    req, _ := http.NewRequestWithContext(ctx, "GET", target.URL, nil)
    
    // 2. 设置请求头(支持压缩)
    req.Header.Set("Accept-Encoding", "gzip")
    req.Header.Set("Accept", "text/plain")
    
    // 3. 发送请求
    resp, err := s.client.Do(req)
    if err != nil {
        return fmt.Errorf("scrape failed: %w", err)
    }
    defer resp.Body.Close()
    
    // 4. 解析响应体(支持 gzip)
    reader, _ := gzip.NewReader(resp.Body)
    defer reader.Close()
    
    // 5. 解析指标格式
    parser := expfmt.NewParser(reader, expfmt.FmtText)
    return parser.MetricFamilies(func(mf *dto.MetricFamily) error {
        // 写入 TSDB
        return s.append(mf)
    })
}

2.3 Pull vs Push 深度对比

维度 Pull 模式 Push 模式
流量控制 服务端掌控,易限流 客户端涌峰时难控
故障检测 拉取失败 = 目标异常 需心跳机制
网络拓扑 适合内网/Docker/K8s 适合跨公网
数据完整性 拉取窗口内数据可能丢失 客户端可缓存重发
配置复杂度 集中式配置 每个客户端需配置

Push 模式
主动上报
主动上报
主动上报
Target 1
Collector
Target 2
Target N
Pull 模式
主动拉取
主动拉取
主动拉取
Prometheus
Target 1
Target 2
Target N

2.4 Pushgateway:短生命周期任务的特殊处理

对于短生命周期任务(如 Cron 任务、批处理作业),Prometheus 提供 Pushgateway 作为缓存层:

bash 复制代码
# 客户端主动推送指标到 Pushgateway
echo "batch_job_duration_seconds 123.45" | \
  curl --data-binary @- http://pushgateway:9091/metrics/job/batch_job

# Prometheus 从 Pushgateway 拉取
# scrape_configs:
#   - job_name: 'pushgateway'
#     honor_labels: true
#     static_configs:
#       - targets: ['pushgateway:9091']

⚠️ 注意:Pushgateway 仅用于特殊场景,不是 Pull 模式的替代品。


三、TSDB 时序数据库架构

3.1 TSDB 整体架构

Prometheus TSDB 采用 LSM-Tree(Log-Structured Merge Tree)变体架构,数据分为内存和磁盘两部分:
TSDB 架构
定期压缩
写入请求
Head Block

内存存储
WAL

Write-Ahead Log
Persistent Blocks

持久化块
索引文件

Index
数据块

Chunks
查询请求
查询结果

3.2 时序数据模型

一条时序由 度量名称 + 标签键值对 唯一确定:

复制代码
# 格式
metric_name{label1="value1", label2="value2"} value

# 示例
http_requests_total{method="POST", handler="/api/users", status="200"} 1247

源码中的时序定义(v2.55.0):

go 复制代码
// 文件: model/labels.go
// Labels 是标签集合,用于唯一标识时序
type Labels []Label

type Label struct {
    Name  string
    Value string
}

// Series 代表单个时序
type Series interface {
    // 返回时序的标签
    Labels() Labels
    
    // 返回时序的样本迭代器
    Iterator() ChunkIterator
}

3.3 存储目录结构

bash 复制代码
/data/prometheus/
├── wal/                    # Write-Ahead Log(预写日志)
│   ├── 00000001
│   ├── 00000002
│   └── ...
├── 01JE9TB3K4W7JZY8MVP5X2/ # 持久化 Block(时间范围 2h)
│   ├── chunks/            # 数据块文件
│   │   ├── 000001
│   │   └── 000002
│   ├── index/             # 索引文件
│   │   └── 000001
│   └── meta.json          # Block 元数据
├── 01JE9TB8K2X6LZ9N7YU4A3/ # 下一个 Block
└── locks                  # 文件锁

Block 元数据示例meta.json):

json 复制代码
{
  "ulid": "01JE9TB3K4W7JZY8MVP5X2",
  "minTime": 1704067200000,
  "maxTime": 1704080000000,
  "stats": {
    "numSeries": 15234,
    "numChunks": 45678,
    "numSamples": 891012
  },
  "compaction": {
    "level": 1,
    "sources": ["wal"]
  }
}

3.4 TSDB vs 其他时序数据库

特性 Prometheus TSDB InfluxDB TimescaleDB
存储引擎 自定义 LSM-Tree TSM (基于 LSM) 基于 PostgreSQL
数据模型 多维标签 Tag + Field 关系型扩展
查询语言 PromQL InfluxQL / Flux SQL
分布式 需联邦方案 原生集群 原生集群
压缩率 极高 中等
适用场景 指标监控 IoT/时序分析 复杂查询

四、Head Block 内存存储机制

4.1 Head Block 架构

Head Block 是 TSDB 的内存部分,存储最近写入的时序数据:
索引
存储
写入请求
MemSeries

时序元数据
MemChunk

样本数据块
Series Hash Map

快速查找
Chunk Ring Buffer

循环缓冲区

核心数据结构(v2.55.0):

go 复制代码
// 文件: tsdb/head.go
// Head 是内存数据库的核心结构
type Head struct {
    // 系列 ID 到 Series 的映射
    seriesByID map[Reference]MemSeries
    
    // 标签到 Series 的倒排索引
    seriesByLabel map[string]map[string]map[Reference]struct{}
    
    // 读写锁
    mtx sync.RWMutex
    
    // Chunk 缓存(环形缓冲区)
    chunkRange uint64 // 默认 2 小时
    
    // WAL 写入器
    wal *wlog.WL
    
    // 统计信息
    stats *HeadStats
}

// MemSeries 内存中的时序
type MemSeries struct {
    ref      Reference      // 唯一引用 ID
    labels   Labels         // 标签集合
    chunks   *ChunkRingBuf  // Chunk 环形缓冲区
    modTime  time.Time      // 最后修改时间
}

// ChunkRingBuf 环形缓冲区实现
type ChunkRingBuf struct {
    chunks []Chunk
    head   int
    tail   int
    size   int
}

4.2 写入流程源码解析

go 复制代码
// 文件: tsdb/head.go
// Appender 向 Head 追加数据
func (h *Head) Appender() Appender {
    return &headAppender{
        head: h,
        // 分配样本缓冲区
        samples: make([]sample, 0, 1024),
    }
}

type headAppender struct {
    head    *Head
    samples []sample
}

// Append 追加单个样本
func (a *headAppender) Append(ref Ref, l Labels, t int64, v float64) (Ref, error) {
    // 1. 查找或创建 Series
    series, err := a.head.getOrCreate(l)
    if err != nil {
        return 0, err
    }
    
    // 2. 获取当前活跃的 Chunk
    chunk := series.chunks.chunkFor(t)
    
    // 3. 写入样本到 Chunk
    if err := chunk.Add(t, v); err != nil {
        // Chunk 已满,创建新 Chunk
        series.chunks.append(newChunk())
        chunk.Add(t, v)
    }
    
    // 4. 写入 WAL(保证持久化)
    if a.head.wal != nil {
        a.head.wal.Log(series.ref, t, v)
    }
    
    return series.ref, nil
}

// getOrCreate 根据 Labels 获取或创建 Series
func (h *Head) getOrCreate(l Labels) (*MemSeries, error) {
    h.mtx.Lock()
    defer h.mtx.Unlock()
    
    // 1. 计算标签哈希,快速查找
    hash := l.Hash()
    
    // 2. 在 Hash Map 中查找
    if series, ok := h.seriesByHash[hash]; ok {
        return series, nil
    }
    
    // 3. 不存在则创建新 Series
    ref := h.nextRef()
    series := &MemSeries{
        ref:    ref,
        labels: l,
        chunks: newChunkRingBuf(),
    }
    
    // 4. 更新索引
    h.seriesByID[ref] = series
    h.seriesByHash[hash] = series
    
    return series, nil
}

4.3 Chunk 压缩编码

为节省内存,TSDB 使用多种压缩算法:

数据类型 压缩算法 压缩比
时间戳 XOR delta ~10x
浮点值 Gorilla 压缩 ~13x
标签 字典编码 + Snappy ~5x

Gorilla 压缩示例(Facebook 开源算法):

go 复制代码
// 文件: tsdb/chunks/chunk.go
// Chunk 存储 2 小时内的样本(默认 120 个样本/时序)
type Chunk struct {
    // 压缩后的字节
    data []byte
    
    // 样本数量
    numSamples int
    
    // 最小/最大时间戳(用于快速查询)
    minTime, maxTime int64
}

// EncodeChunk 使用 Gorilla 算法编码
func EncodeChunk(samples []Sample) ([]byte, error) {
    var buf bytes.Buffer
    
    // 1. 写入第一个样本(未压缩)
    buf.Write(writeFloat64(samples[0].value))
    buf.Write(writeInt64(samples[0].timestamp))
    
    prevValue := samples[0].value
    prevDelta := int64(0)
    
    // 2. 后续样本使用 XOR delta 编码
    for i := 1; i < len(samples); i++ {
        currValue := samples[i].value
        currDelta := samples[i].timestamp - samples[i-1].timestamp
        
        // 计算 XOR delta
        xorValue := math.Float64bits(currValue) ^ math.Float64bits(prevValue)
        
        // 写入压缩后的值
        buf.Write(encodeXorDelta(xorValue))
        buf.Write(encodeDelta(currDelta))
        
        prevValue = currValue
    }
    
    return buf.Bytes(), nil
}

4.4 内存占用估算

假设监控场景:

  • 10000 个时序

  • 每个时序每 15 秒一个样本

  • 每个 Chunk 存储 2 小时数据(480 个样本)

    单个时序内存占用:

    • Series 元数据: ~1 KB
    • Chunk (压缩后): ~1 KB
    • 索引: ~0.5 KB
      总计: ~2.5 KB/时序

    10000 时序总内存: 2.5 KB * 10000 = 25 MB


五、WAL 与数据持久化

5.1 WAL 工作原理

Write-Ahead Log(预写日志)保证数据持久化,防止崩溃丢失:
磁盘 WAL Head Block 写入请求 磁盘 WAL Head Block 写入请求 崩溃恢复时 从 WAL 重放数据 1. 写入内存 2. 同步写入 WAL 3. fsync() 落盘 4. 写入完成 5. 返回成功 6. 确认写入

WAL 核心代码(v2.55.0):

go 复制代码
// 文件: tsdb/wlog/wal.go
// WAL 管理预写日志
type WAL struct {
    dir        string          // WAL 目录
    segmentSize int64          // 单个 Segment 大小(128MB)
    curSegment  *segment       // 当前活跃 Segment
    encoder     *Encoder        // 编码器
    compressor  compress.Header // 压缩器(Snappy)
}

// Log 记录一条日志
func (w *WAL) Log(record *Record) error {
    // 1. 编码记录
    data, err := w.encoder.Encode(record)
    if err != nil {
        return err
    }
    
    // 2. 压缩数据
    compressed := w.compress(data)
    
    // 3. 追加到当前 Segment
    if err := w.curSegment.Append(compressed); err != nil {
        return err
    }
    
    // 4. 检查是否需要切换 Segment
    if w.curSegment.Size() >= w.segmentSize {
        w.rotateSegment()
    }
    
    return nil
}

// 记录类型
type Record struct {
    Series []Series  // 时序创建
    Samples []Sample // 样本写入
    Deletes []Delete // 删除操作
}

5.2 Checkpoint 机制

WAL 会定期执行 Checkpoint,将已固化的数据清除:

go 复制代码
// 文件: tsdb/head.go
// Checkpoint 将 Head Block 的快照写入磁盘
func (h *Head) Checkpoint() error {
    h.mtx.Lock()
    defer h.mtx.Unlock()
    
    // 1. 创建 Checkpoint 目录
    checkpointDir := filepath.Join(h.dir, "wal", "checkpoint")
    os.MkdirAll(checkpointDir, 0755)
    
    // 2. 持久化所有 Series
    checkpointFile := filepath.Join(checkpointDir, "checkpoint")
    f, _ := os.Create(checkpointFile)
    defer f.Close()
    
    enc := gob.NewEncoder(f)
    for _, series := range h.seriesByID {
        enc.Encode(series)
    }
    
    // 3. 删除已 Checkpoint 的 WAL 记录
    h.wal.Truncate()
    
    return nil
}

5.3 数据恢复流程

Prometheus 重启时从 WAL 恢复内存状态:

go 复制代码
// 文件: tsdb/head.go
// InitFromWAL 从 WAL 恢复数据
func (h *Head) InitFromWAL(wal *WAL) error {
    // 1. 读取最新的 Checkpoint
    checkpoint, err := wal.LoadCheckpoint()
    if err == nil {
        h.loadCheckpoint(checkpoint)
    }
    
    // 2. 重放 Checkpoint 之后的 WAL 记录
    reader := wal.NewReader()
    for reader.Next() {
        record := reader.Record()
        
        // 根据记录类型恢复数据
        switch record.Type {
        case RecordSeries:
            h.restoreSeries(record.Series)
        case RecordSample:
            h.restoreSample(record.Sample)
        case RecordDelete:
            h.restoreDelete(record.Delete)
        }
    }
    
    return nil
}

5.4 WAL 性能调优

参数 默认值 说明
--storage.tsdb.wal-segment-size 128MB 单个 WAL 文件大小
--storage.tsdb.retention.time 15d 数据保留时间
--storage.tsdb.retention.size 0 (无限制) 最大磁盘占用

优化建议

bash 复制代码
# 高频写入场景增大 WAL Segment
prometheus \
  --storage.tsdb.wal-segment-size=256MB \
  --storage.tsdb.min-block-duration=2h \
  --storage.tsdb.max-block-duration=2h

六、Block 压缩与查询优化

6.1 Block 压缩流程

Prometheus 定期将 Head Block 压缩为持久化 Block:
每 2 小时
累计多个
长期存储
Head Block

内存数据
Minor Compaction

生成 Level 1 Block
Major Compaction

合并为 Level 2 Block
Frozen Block

不可变
查询请求

压缩调度器源码(v2.55.0):

go 复制代码
// 文件: tsdb/db.go
type DB struct {
    dir     string
    head    *Head
    blocks  []*Block
    compact *compactor
}

// CompactBlocks 执行压缩
func (db *DB) CompactBlocks() error {
    // 1. 查找待压缩的 Blocks
    compactable := db.findCompactableBlocks()
    if len(compactable) < 2 {
        return nil
    }
    
    // 2. 执行合并压缩
    merged, err := db.compactor.Compact(compactable...)
    if err != nil {
        return err
    }
    
    // 3. 替换旧 Blocks
    db.replaceBlocks(compactable, merged)
    
    return nil
}

// findCompactableBlocks 查找可压缩的 Blocks
func (db *DB) findCompactableBlocks() []*Block {
    var blocks []*Block
    for _, block := range db.blocks {
        // 跳过已冻结的 Block
        if block.IsFrozen() {
            continue
        }
        blocks = append(blocks, block)
    }
    return blocks
}

6.2 索引结构查询优化

Prometheus 使用倒排索引加速多条件查询:

复制代码
查询示例:
http_requests_total{job="api", method="POST"}

索引结构:
  job="api" → [Series1, Series3, Series5]
  method="POST" → [Series1, Series2, Series3]

求交集:
  [Series1, Series3, Series5] ∩ [Series1, Series2, Series3] 
  = [Series1, Series3]

索引实现(v2.55.0):

go 复制代码
// 文件: tsdb/index/index.go
// Index 倒排索引
type Index struct {
    postings map[string]map[string][]Ref // label_name → label_value → []SeriesRef
    mutex    sync.RWMutex
}

// Postings 返回匹配的 Series 列表
func (idx *Index) Postings(name, value string) (Postings, error) {
    idx.mutex.RLock()
    defer idx.mutex.RUnlock()
    
    if vals, ok := idx.postings[name]; ok {
        if refs, ok := vals[value]; ok {
            return NewListPostings(refs), nil
        }
    }
    return EmptyPostings(), nil
}

// Intersect 求交集(用于多条件查询)
func Intersect(iters ...Postings) Postings {
    if len(iters) == 0 {
        return EmptyPostings()
    }
    
    // 使用堆排序算法求交集
    result := iters[0]
    for _, iter := range iters[1:] {
        result = intersect(result, iter)
    }
    return result
}

6.3 查询执行计划

PromQL 查询经过多个优化阶段:
优化规则
优化规则
优化规则
PromQL 查询
解析器

Parse
AST 语法树
类型检查

Type Check
优化器

Optimizer
物理计划

Physical Plan
执行引擎

Engine
查询结果
谓词下推
索引选择
剪枝

优化示例

promql 复制代码
# 原始查询
rate(http_requests_total[5m])

# 优化后的执行计划
1. 从索引中找到所有 http_requests_total 的 Series
2. 按 time 索引定位最近 5 分钟的 Chunks
3. 仅加载相关的 Chunks(避免全表扫描)
4. 计算 rate

6.4 查询性能对比

查询类型 优化前 优化后 提升
单标签查询 50ms 5ms 10x
多标签 AND 200ms 15ms 13x
范围查询 500ms 30ms 16x
正则匹配 1s 100ms 10x

七、性能优化最佳实践

7.1 抓取配置优化

yaml 复制代码
# prometheus.yml
global:
  # 全局抓取间隔(根据数据颗粒度调整)
  scrape_interval: 15s
  # 抓取超时
  scrape_timeout: 10s
  # 评估告警规则间隔
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'high-frequency'
    # 高频采集用于关键指标
    scrape_interval: 5s
    static_configs:
      - targets: ['localhost:9090']
  
  - job_name: 'low-frequency'
    # 低频采集减少负载
    scrape_interval: 60s
    static_configs:
      - targets: ['node-exporter:9100']

性能对比

采集间隔 存储增长 CPU 使用 查询延迟
5s 4x 3x -10%
15s 1x 1x 基准
60s 0.25x 0.3x +30%

7.2 存储优化配置

bash 复制代码
# prometheus 启动参数
prometheus \
  --config.file=prometheus.yml \
  --storage.tsdb.path=/data/prometheus \
  --storage.tsdb.retention.time=30d \
  --storage.tsdb.retention.size=500GB \
  --storage.tsdb.min-block-duration=2h \
  --storage.tsdb.max-block-duration=2h

磁盘空间估算

复制代码
单个样本大小: ~1-2 字节(压缩后)
10000 时序,每 15 秒一个样本:
  每小时样本数: 10000 * 240 = 240 万
  每天样本数: 240 万 * 24 = 5760 万
  每天磁盘占用: 5760 万 * 2 字节 = ~110 MB
  30 天占用: 110 MB * 30 = ~3.3 GB

7.3 高基数问题处理

什么是高基数

promql 复制代码
# 好的标签(低基数)
status_code: "200", "404", "500"  # 3 个值
method: "GET", "POST"              # 2 个值

# 坏的标签(高基数)
user_id: "123456"                  # 可能百万级值
request_id: "abc-xyz-123"          # 每次请求不同

解决方案

go 复制代码
// 使用 recording rules 预聚合
# prometheus.rules.yml
groups:
  - name: reduce_cardinality
    interval: 30s
    rules:
      # 丢弃 user_id 标签
      - record: job:http_requests_total:rate5m
        expr: sum without (user_id) (http_requests_total)
      
      # 仅保留关键维度
      - record: job:latency:p99
        expr: histogram_quantile(0.99, 
              sum without (instance) (http_request_duration_seconds_bucket))

7.4 分联邦集群方案

对于超大规模监控,可使用联邦架构:

yaml 复制代码
# global-prometheus (中心节点)
scrape_configs:
  - job_name: 'federate'
    scrape_interval: 15s
    honor_labels: true
    metrics_path: '/federate'
    params:
      'match[]':
        - '{job=~"kubernetes-.*"}'
        - '{__name__=~"job:.*"}'
    static_configs:
      - targets:
        - 'prometheus-1:9090'
        - 'prometheus-2:9090'
        - 'prometheus-3:9090'

中心 Prometheus
边缘 Prometheus
拉取
Prometheus 1

业务 A
Federate Endpoint
Prometheus 2

业务 B
Prometheus 3

业务 C
Global Prometheus
Alertmanager

7.5 监控 Prometheus 自身

promql 复制代码
# TSDB 性能指标
# 写入速率
rate(prometheus_tsdb_head_samples_appended_total[5m])

# 查询性能
histogram_quantile(0.99, rate(prometheus_http_request_duration_seconds_bucket[5m]))

# 内存使用
process_resident_memory_bytes{job="prometheus"}

# 磁盘 I/O
rate(node_disk_io_time_seconds_total[5m])

# WAL 大小
prometheus_tsdb_wal_size_bytes

总结

本文深入剖析了 Prometheus 监控体系的核心原理:

  1. Pull 模式:通过服务端主动拉取实现简单可靠的监控架构,配合 Pushgateway 支持短生命周期任务
  2. TSDB 时序数据库:基于 LSM-Tree 的存储引擎,结合 Head Block 内存存储与 WAL 预写日志保证性能与持久性
  3. Block 压缩机制:定期将内存数据压缩为不可变 Block,配合倒排索引实现高效查询
  4. 性能优化:合理配置抓取间隔、控制标签基数、使用联邦架构应对大规模监控场景

Prometheus 的成功证明了"简单设计"的力量------通过 Pull 模式、内置 TSDB、PromQL 查询语言三大核心设计,构建了一套强大且易用的云原生监控体系。


参考资料

标签Prometheus 监控 Pull模式 TSDB 时序数据库

相关推荐
何中应1 天前
Alertmanager设置邮件通知
运维·自动化·prometheus
lvbinemail1 天前
动环方案实践:温湿度传感器+串口服务器+Zabbix+Grafana
zabbix·监控·机房·动环
安审若无1 天前
运维监控及可视化工具Prometheus和grafana
运维·grafana·prometheus
倔强的石头1061 天前
时序数据库选型指南:可视化与分析协同怎么选?——以 Apache IoTDB + Grafana + 大数据引擎为例
apache·时序数据库·iotdb
todoitbo1 天前
时序数据库选型指南:从大数据场景出发
大数据·数据库·时序数据库
FinTech老王1 天前
时序数据库存储引擎解密:LSM-Tree vs B-Tree vs 倒排索引,谁最适合时序场景?
数据库·时序数据库·lsm-tree
A-刘晨阳1 天前
流批一体架构下的时序数据库选型:Apache IoTDB实时计算能力深度解析与国际化对比
架构·apache·时序数据库
却话巴山夜雨时i1 天前
互联网大厂Java面试实录:从Spring Boot到Kafka的场景应用深度解析
spring boot·kafka·prometheus·微服务架构·java面试·技术解析·互联网大厂
科技苑2 天前
告别付费枷锁:在家电脑自建大模型,Token自由不是梦
人工智能·时序数据库