4. 存储层故障排查:时序数据库写入瓶颈、查询超时、磁盘IO打满的排查方法
时序数据库(TSDB)是监控系统的核心存储组件,其性能直接决定告警延迟、查询响应与数据完整性。本章聚焦 Prometheus 与 InfluxDB 两类主流 TSDB,从写入瓶颈、查询超时、磁盘 IO 打满三个维度,给出架构视角的排查路径与根因定位方法。
核心原则:时序数据库的故障通常表现为“写入积压 → 查询排队 → IO 过载”的连锁反应。排查时应先确认故障面(写入/查询/IO),再逐层下钻至具体组件(WAL、Compaction、索引、分片)。
4.1 写入瓶颈排查
写入瓶颈的典型现象:指标数据出现断点、Prometheus remote write 报 503、InfluxDB 写入延迟飙升。排查路径分为三层:客户端限速 → 服务端队列 → 存储引擎背压。
| 排查层 | 关键指标 | Prometheus 命令/端点 | InfluxDB 命令/端点 |
|---|---|---|---|
| 客户端限速 | 写入速率 vs 配置上限 | rate(prometheus_tsdb_out_of_order_samples_total[5m]) |
SHOW STATS FOR 'write' |
| 服务端队列 | WAL 积压、Appender 等待 | prometheus_tsdb_wal_queue_size |
_internal.monitor.shard.write_points_ok |
| 存储引擎背压 | Compaction 延迟、内存映射压力 | prometheus_tsdb_compactions_failed_total |
SHOW STATS FOR 'engine' |
快速定位技巧:若
prometheus_tsdb_head_series 持续增长但 prometheus_tsdb_head_chunks 不增长,说明写入被 WAL 阶段阻塞,优先检查磁盘 IO 与 WAL 目录挂载类型(推荐 XFS 或 ext4,避免 NFS)。
4.2 查询超时排查
查询超时通常由索引扫描过大、全表扫描或并发查询排队引起。Prometheus 与 InfluxDB 的查询路径差异较大,需分别对待。
4.2.1 Prometheus 查询链路
- Step 1:检查查询范围与时间跨度。大跨度查询(如 30d)会触发大量 block 合并扫描。
- Step 2:查看
prometheus_tsdb_queries_total与prometheus_tsdb_query_duration_seconds分位数。 - Step 3:确认是否命中
--query.max-concurrency限制(默认 20)。
# 查看当前活跃查询
curl http://localhost:9090/api/v1/status/active_queries
# 查看查询延迟分布
prometheus_tsdb_query_duration_seconds{quantile="0.99"}
4.2.2 InfluxDB 查询链路
- Step 1:检查查询是否触发全表扫描(无时间范围或 tag 过滤)。
- Step 2:查看
SHOW QUERIES识别慢查询。 - Step 3:确认
max-concurrent-queries与query-timeout配置。
# 查看当前运行中的查询
SHOW QUERIES
# 终止超时查询
KILL QUERY <query_id>
常见陷阱:InfluxDB 的
SELECT * 且无 WHERE time 子句会触发全表扫描,导致内存溢出。建议在查询中始终指定时间范围,并使用 LIMIT 限制返回行数。
4.3 磁盘 IO 打满排查
磁盘 IO 打满是 TSDB 故障中最具破坏性的场景,通常由 Compaction 风暴、WAL 写入放大或查询临时文件溢出引起。排查需区分读写 IO 与IO 等待。
| IO 类型 | 根因 | 排查命令 | 缓解措施 |
|---|---|---|---|
| 写 IO 打满 | WAL 写入 + Compaction 合并 | iostat -x 1 观察 %util 与 await |
调整 storage.tsdb.retention.size 限制总数据量 |
| 读 IO 打满 | 大查询扫描多个 block | iotop -o 定位进程 |
增加 --query.max-samples 限制扫描样本数 |
| IO 等待高 | 磁盘性能不足或 RAID 降级 | sar -d 1 查看 svctm |
升级 SSD / 分离 WAL 与数据盘 |
4.4 典型故障场景与根因对照
| 故障现象 | 根因 | 快速验证 | 修复动作 |
|---|---|---|---|
| 写入延迟持续上升 | WAL 队列积压,磁盘 IO 成为瓶颈 | prometheus_tsdb_wal_queue_size > 1000 |
增加 WAL 批量写入大小,或分离 WAL 到独立 SSD |
| 查询返回超时 | 查询扫描过多 series,触发 OOM | prometheus_tsdb_series_fetched_total 突增 |
添加更精确的 label 过滤,或降低 query.max-samples |
| 磁盘 IO 100% 但写入量不大 | Compaction 线程数过高,或数据碎片严重 | iostat -x 显示 await > 50ms |
降低 Compaction 并发,或手动执行 OPTIMIZE 合并分片 |
InfluxDB 写入报 engine: cache snapshot too big |
内存中缓存积压,触发写入背压 | SHOW STATS FOR 'cache' 查看 snapshotSize |
增加 cache-max-memory-size,或减少写入并发 |
4.5 架构级优化建议
- 存储分离:将 WAL 目录与数据目录分别挂载到不同磁盘(WAL 使用低延迟 NVMe,数据使用大容量 SSD)。
- 写入限速:在采集端(如 Prometheus Agent 或 Telegraf)配置
max_samples_per_send与capacity,避免突发写入压垮 TSDB。 - 查询超时兜底:设置合理的
query-timeout(Prometheus 默认 2m,InfluxDB 默认 30s),并启用慢查询日志。 - Compaction 窗口:在业务低峰期(如凌晨)手动触发 Compaction,避免与写入高峰重叠。
监控自愈建议:在告警规则中加入
prometheus_tsdb_wal_corruptions_total 与 influxdb_tsm1_filestore_disk_bytes,实现存储层故障的提前发现。