17.9.1 指标基数与TSDB容量估算方法

指标基数与TSDB容量估算方法#

1. 原理与关键概念#

  • 时间序列定义:指标名 + 标签集合(name+labels)= 1 条 time series
  • 基数(Cardinality):同一指标的不同标签组合数量
  • TSDB存储:样本 → WAL(写前日志)→ 内存 Head → Block 文件 + Index
  • 影响容量的核心变量:series 数量、抓取频率、保留天数、压缩后样本字节数

原理草图(TSDB写入路径)#

文章图片

2. 指标基数来源与识别#

  • 高基数常见来源
  • 动态标签:pod、container、request_id、user_id、ip、url
  • 指标爆炸:单指标维度过多
  • 服务发现不稳定:实例标签频繁变化

现场检查命令(解释+预期)#

# 1) 查看当前 head 中 series 总量(直接反映基数)
# 预期:输出当前 Prometheus 的 series 数量
curl -s http://localhost:9090/api/v1/query \
  --data-urlencode 'query=prometheus_tsdb_head_series' | jq -r '.data.result[0].value'

# 2) 查看 head chunk 数(反映活跃样本量)
# 预期:输出 head chunks 数量
curl -s http://localhost:9090/api/v1/query \
  --data-urlencode 'query=prometheus_tsdb_head_chunks' | jq -r '.data.result[0].value'

3. 基数估算步骤(含示例)#

  1. 梳理指标清单:按 job/exporter 分类统计
  2. 估算标签维度:为每个指标估计各标签唯一值
  3. 单指标基数:标签值数量乘积
  4. 总基数:所有指标基数求和
  5. 验证与修正:用 Prometheus 自监控指标校验

示例:单指标基数估算#

  • 指标:http_requests_total
  • 标签:method(4) * code(10) * instance(20)
  • 基数:4 * 10 * 20 = 800 series

可执行示例:统计 Top 指标基数(PromQL)#

# 统计每个指标名当前的 series 数量(Top 10)
topk(10, count by (__name__)({__name__!=""}))

4. TSDB 容量估算方法(含公式与计算)#

  • S:总 series 数
  • F:抓取频率(秒)
  • R:保留时间(天)
  • B:样本平均字节数(经验值 1.5~2.0 bytes)

计算公式#

  • samples_per_series = (86400 / F) * R
  • total_samples = S * samples_per_series
  • disk_size ≈ total_samples * B
  • 额外开销:WAL/Index/Meta 建议 +30%~50%

示例估算(含完整计算)#

  • S=200,000F=15sR=30天B=1.7
  • samples_per_series = (86400/15) * 30 = 172,800
  • total_samples = 200,000 * 172,800 = 34,560,000,000
  • disk_size = 34.56e9 * 1.7 ≈ 58.8 GB
  • 预留 50%:≈ 90 GB

5. 命令化估算示例(脚本+输出)#

#!/usr/bin/env bash
# 文件:/opt/prom-tools/estimate_tsdb.sh
# 用法:./estimate_tsdb.sh 200000 15 30 1.7
S=$1   # series
F=$2   # scrape interval (s)
R=$3   # retention (days)
B=$4   # bytes per sample

samples_per_series=$(( (86400 / F) * R ))
total_samples=$(( S * samples_per_series ))

# 使用 bc 计算容量(GB)
disk_size_gb=$(echo "scale=2; $total_samples * $B / 1024 / 1024 / 1024" | bc)

echo "samples_per_series=$samples_per_series"
echo "total_samples=$total_samples"
echo "disk_size≈${disk_size_gb} GB (未含WAL/Index预留)"

预期输出示例

samples_per_series=172800
total_samples=34560000000
disk_size58.80 GB (未含WAL/Index预留)

6. 降低基数与容量治理(含配置示例)#

6.1 Relabel 过滤高基数标签#

# 文件:/etc/prometheus/prometheus.yml
scrape_configs:
  - job_name: "kubernetes-pods"
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      # 删除高变动标签(如 pod_uid)
      - action: labeldrop
        regex: 'pod_uid|request_id|trace_id'

解释:减少动态标签,降低 series 爆炸。
预期效果prometheus_tsdb_head_series 下降或增长速度变慢。

6.2 记录规则聚合降维#

# 文件:/etc/prometheus/rules/agg.yml
groups:
- name: http_agg
  rules:
  - record: job:http_requests_total:rate5m
    expr: sum by (job) (rate(http_requests_total[5m]))

解释:使用聚合后的记录规则替代高维原始指标。

7. 安装与工具准备(promtool/tsdb)#

# 安装 Prometheus(含 promtool)
wget -O /tmp/prometheus.tar.gz https://github.com/prometheus/prometheus/releases/download/v2.49.1/prometheus-2.49.1.linux-amd64.tar.gz
tar -zxvf /tmp/prometheus.tar.gz -C /opt/
ln -s /opt/prometheus-2.49.1.linux-amd64 /opt/prometheus

# 检查工具
/opt/prometheus/promtool --version

用途:promtool 用于规则与配置校验,TSDB 工具用于块检查。

8. 排错与验证清单(带命令)#

  • 症状:磁盘增长过快
  • 检查当前基数
    bash curl -s http://localhost:9090/api/v1/query \ --data-urlencode 'query=prometheus_tsdb_head_series' | jq -r '.data.result[0].value'
  • 症状:Prometheus 重启后数据短期内暴涨
  • 检查服务发现是否频繁变更实例标签
    promql count by (job) (up)
  • 症状:WAL 过大/写入延迟
  • 查看磁盘与 WAL 目录占用
    bash du -sh /var/lib/prometheus/wal df -h /var/lib/prometheus

9. 练习(可验证结果)#

  1. 基数识别练习
    - 用 PromQL 找出 top5 的指标基数
    - 期望输出包含指标名与 series 数
  2. 容量估算练习
    - 设 S=500k, F=30s, R=15天, B=1.7,计算容量
  3. 治理验证练习
    - 添加 labeldrop 配置后,重启 Prometheus
    - 对比 prometheus_tsdb_head_series 前后变化并记录差值