2. 存储瓶颈根因分类:TSDB写入放大、WAL积压、Block合并延迟、内存Chunk溢出、磁盘IOPS打满等常见根因的归类与特征

Prometheus TSDB 的存储瓶颈并非单一故障,而是多种根因交织的结果。SRE 在复盘时,需要快速将现象归类到对应的根因类别,才能制定有效的恢复策略。本节将五大常见根因进行结构化分类,并给出每个类别的核心特征与判别指标。

2.1 根因分类全景图

以下 SVG 展示了五大根因的层级关系与数据流影响路径,帮助你在复盘时快速定位问题域。

存储瓶颈根因分类全景图 存储瓶颈根因分类全景图 TSDB 存储引擎 写入放大 WAL 积压 Block 合并延迟 内存 Chunk 溢出 磁盘 IOPS 打满 复盘要点: • 写入放大和 WAL 积压通常并发出现,表现为 CPU 和磁盘 IO 同时飙升。 • Block 合并延迟是慢性的性能劣化,往往在数小时甚至数天后才触发 OOM。 • 内存 Chunk 溢出是瞬时性的,通常伴随查询超时和远端写失败。 • 磁盘 IOPS 打满是所有根因的最终表现形式,也可能是独立硬件故障。 • 建议在 MTTR 复盘时,按“现象 → 根因 → 影响范围”三层模型归类。

2.2 根因归类与特征矩阵

下表从触发条件、核心指标、典型现象、恢复手段四个维度,对五大根因进行横向对比。

根因类别 触发条件 核心指标 典型现象 恢复手段
写入放大 高基数 label 组合、频繁的 label 变更 prometheus_tsdb_head_series
prometheus_tsdb_compactions_total
CPU 持续 80%+,磁盘写入量 > 采集量 5x 降低基数、启用 label 降维、调整压缩策略
WAL 积压 写入峰值超过 WAL 回放速度、磁盘 IO 抖动 prometheus_tsdb_wal_storage_size_bytes
prometheus_tsdb_wal_corruptions_total
WAL 目录大小持续增长,重启后回放时间 > 5min 限流写入、扩容磁盘、启用 WAL 压缩
Block 合并延迟 内存不足、压缩队列积压、Block 数量 > 100 prometheus_tsdb_compactions_skipped_total
prometheus_tsdb_blocks_loaded
查询延迟增加,Block 目录碎片化严重 增加内存、调整 --storage.tsdb.retention.size
内存 Chunk 溢出 瞬时高基数写入、head chunk 未及时落盘 prometheus_tsdb_head_chunks
process_resident_memory_bytes
OOM 重启、远端写失败、查询返回 503 限制 series 数量、启用 chunk 预分配
磁盘 IOPS 打满 大量 Block 合并、WAL 回放、查询扫描 node_disk_io_time_seconds_total
node_disk_reads_completed_total
iowait > 30%,所有读写操作排队 更换 SSD、分离数据与 WAL 磁盘、限流
复盘提示: 在 MTTR 复盘时,优先检查 prometheus_tsdb_head_series 和 prometheus_tsdb_wal_storage_size_bytes 两个指标。如果 series 数量超过 1000 万且 WAL 大小超过 10GB,基本可以判定为写入放大 + WAL 积压的组合根因。

2.3 根因特征详解

2.3.1 写入放大

写入放大是 Prometheus TSDB 最隐蔽的瓶颈。当 label 组合基数过高时,每个新 series 都会触发一次完整的 index 写入和压缩操作,导致实际磁盘写入量远大于采集数据量。

  • 特征指标: rate(prometheus_tsdb_compactions_total[5m]) 持续 > 10,且 rate(prometheus_tsdb_head_series_created_total[5m]) 与 rate(prometheus_tsdb_head_samples_appended_total[5m]) 比值 > 1:100。
  • 典型场景: 容器 label 中包含 pod IP、container_id 等高频变化字段。
  • 恢复策略: 使用 honor_labels: false 或 relabel 丢弃高基数 label。

2.3.2 WAL 积压

WAL 积压通常发生在写入峰值超过磁盘写入能力时。WAL 文件无法及时被回放并转换为 Block,导致目录大小持续膨胀。

  • 特征指标: prometheus_tsdb_wal_storage_size_bytes 在 30 分钟内增长超过 2GB,且 prometheus_tsdb_wal_replay_duration_seconds 在重启时 > 300s。
  • 典型场景: 大规模集群同时推送数据,或远端写目标不可用导致本地缓存积压。
  • 恢复策略: 临时关闭部分采集任务,或扩容 WAL 所在磁盘的 IOPS。

2.3.3 Block 合并延迟

Block 合并是 TSDB 的后台任务,当内存不足或压缩队列积压时,合并操作被跳过,导致 Block 数量过多,查询性能下降。

  • 特征指标: prometheus_tsdb_compactions_skipped_total 非零,且 prometheus_tsdb_blocks_loaded > 200。
  • 典型场景: 长期运行未重启的 Prometheus 实例,且 retention 设置过大。
  • 恢复策略: 调整 --storage.tsdb.retention.size 为总磁盘的 60%,或手动触发 POST /api/v1/admin/tsdb/clean_tombstones。

2.3.4 内存 Chunk 溢出

内存 Chunk 溢出是瞬时性的致命瓶颈。当 head chunk 无法及时落盘时,内存持续增长直至 OOM。

  • 特征指标: prometheus_tsdb_head_chunks 在 1 分钟内增长超过 50%,且 process_resident_memory_bytes 接近内存上限。
  • 典型场景: 突发流量导致 series 数量在 10 秒内翻倍。
  • 恢复策略: 立即限流写入,并启用 --storage.tsdb.head-chunks-write-queue-size 参数。

2.3.5 磁盘 IOPS 打满

磁盘 IOPS 打满是所有根因的最终表现形式,也可能是独立的硬件故障。当 Block 合并、WAL 回放、查询扫描同时发生时,磁盘成为最薄弱的环节。

  • 特征指标: node_disk_io_time_seconds_total 的 rate > 0.8,且 node_disk_reads_completed_total 和 node_disk_writes_completed_total 均处于高位。
  • 典型场景: 使用 HDD 或低端 SSD 的 Prometheus 实例。
  • 恢复策略: 将数据目录迁移到高性能 SSD,或分离 WAL 与数据到不同磁盘。

2.4 根因判别流程

以下 SVG 展示了从现象到根因的判别决策树,帮助 SRE 在 5 分钟内完成初步归类。

根因判别决策树 根因判别决策树(5 分钟快速归类) 存储瓶颈告警触发 CPU 使用率 > 80% 且 iowait < 20%? 检查 series 数量 series > 1000 万 → 写入放大 series 突增 > 50% → 内存 Chunk 溢出 检查 WAL 大小和 Block 数量 WAL > 10GB → WAL 积压 Block > 200 → Block 合并延迟 以上均不满足 → 磁盘 IOPS 打满
常见误区: 不要将“磁盘 IOPS 打满”作为唯一根因。在大多数情况下,IOPS 打满是写入放大、WAL 积压或 Block 合并延迟的结果。如果只扩容磁盘而不解决上层根因,瓶颈会在 24 小时内再次出现。

2.5 根因归类检查清单

在 MTTR 复盘时,使用以下清单快速完成根因归类:

  1. 检查 CPU 和 iowait: 如果 CPU > 80% 且 iowait < 20%,优先排查写入放大和内存 Chunk 溢出。
  2. 检查 WAL 目录大小: 如果 wal 目录 > 10GB,直接归类为 WAL 积压。
  3. 检查 Block 数量: 如果 blocks 目录下子目录 > 200,归类为 Block 合并延迟。
  4. 检查 series 变化率: 如果 prometheus_tsdb_head_series 在 5 分钟内增长 > 50%,归类为内存 Chunk 溢出。
  5. 检查磁盘 IO 队列长度: 如果 node_disk_io_now 持续 > 10,且以上均不满足,归类为磁盘 IOPS 打满。
复盘最佳实践: 在 Prometheus 的告警规则中,提前为每个根因类别配置独立的告警。例如,当 prometheus_tsdb_wal_storage_size_bytes > 10GB 时触发“WAL 积压”告警,而不是笼统的“存储瓶颈”告警。这可以将 MTTR 缩短 40% 以上。