强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

15 - 故障排查

15 · 故障排查

本章目标

  • 掌握常见问题的诊断方法
  • 学会分析 VictoriaMetrics 日志
  • 了解关键 API 用于故障排查
  • 建立系统化的排错思路

15.1 排错流程

遇到问题
    │
    ▼
检查服务状态 ──▶ 是否在运行?
    │                 │
    │ 是               │ 否
    ▼                 ▼
检查日志         查看 systemd 日志
    │            journalctl -u victoria-metrics
    ▼
检查 API ──▶ /health /metrics /api/v1/status/*
    │
    ▼
检查资源 ──▶ CPU / 内存 / 磁盘
    │
    ▼
检查网络 ──▶ 端口 / 防火墙 / DNS
    │
    ▼
定位问题 ──▶ 查阅对应章节

15.2 常见问题速查

15.2.1 服务启动失败

问题:VictoriaMetrics 无法启动

# 查看日志
journalctl -u victoria-metrics -n 100 --no-pager

# 常见原因:
错误信息原因解决方案
bind: address already in use端口被占用lsof -i :8428 查看并停止冲突进程
permission denied权限不足检查数据目录权限
not enough memory内存不足减少 -memory.allowedPercent
storageDataPath is empty未指定数据路径添加 -storageDataPath 参数
invalid flag参数拼写错误检查配置文件或启动参数
# 排查端口冲突
sudo lsof -i :8428
# 或
sudo ss -tlnp | grep 8428

# 排查权限问题
ls -la /var/lib/victoria-metrics/
# 确保用户与 systemd 服务配置一致

# 排查内存问题
free -h
cat /proc/$(pgrep victoria-metrics)/status | grep VmRSS

15.2.2 数据查询返回空结果

问题:查询表达式正确但无数据返回

# 1. 检查数据是否写入成功
curl -s 'http://localhost:8428/api/v1/label/__name__/values' | python3 -m json.tool

# 2. 检查时间范围
# 确认查询的时间范围覆盖数据的时间戳
curl -s 'http://localhost:8428/api/v1/status/tsdb' | python3 -c "
import json, sys
data = json.load(sys.stdin)
print(f\"Total series: {data['data']['totalSeries']}\")
for m in data['data']['seriesCountByMetricName'][:5]:
    print(f\"  {m['name']}: {m['value']}\")
"

# 3. 检查时间戳是否合理
curl -s 'http://localhost:8428/api/v1/query?query=my_metric&time=0' | python3 -m json.tool
# 如果时间戳是 0 或很旧,数据可能在查询范围之外

# 4. 检查 stale 数据
# VictoriaMetrics 默认 staleness 为 5 分钟
# 如果最后一次写入超过 staleness 窗口,查询可能返回空
curl -s "http://localhost:8428/api/v1/query?query=my_metric&step=1m"

15.2.3 查询超时

问题:查询执行超时

# 1. 检查并发查询数
curl -s 'http://localhost:8428/metrics' | grep concurrent_select

# 2. 减少查询复杂度
# - 缩短时间范围
# - 增加标签过滤
# - 使用聚合减少序列数

# 3. 增加超时限制
# 单节点版
victoria-metrics -search.maxQueryDuration=60s

# 集群版
vmselect -search.maxQueryDuration=60s

# 4. 查看慢查询日志
journalctl -u victoria-metrics | grep "slow query" | tail -20

15.2.4 写入被拒绝

问题:客户端收到 429 Too Many Requests 或写入失败

# 1. 检查并发写入数
curl -s 'http://localhost:8428/metrics' | grep concurrent_insert

# 2. 增加并发限制
victoria-metrics -maxConcurrentInserts=64

# 3. 检查磁盘空间
df -h /var/lib/victoria-metrics/
# 低于 -storage.minFreeDiskSpaceBytes 会拒绝写入

# 4. 检查内存使用
free -h
# 内存接近 -memory.allowedPercent 限制时可能降速

# 5. 检查集群版 vminsert 到 vmstorage 的连接
curl http://vminsert:8480/health

15.2.5 磁盘空间不足

问题:磁盘即将耗尽

# 1. 查看磁盘使用详情
du -sh /var/lib/victoria-metrics/data/*

# 2. 查看活跃序列数
curl -s 'http://localhost:8428/api/v1/status/tsdb' | python3 -c "
import json, sys
data = json.load(sys.stdin)
total = data['data']['totalSeries']
print(f'Active series: {total}')
"

# 3. 减少保留期(临时应急)
# 需要重启服务
# -retentionPeriod=30d  (原来是 90d)

# 4. 清理高基数标签
# 查看 label 基数
curl -s 'http://localhost:8428/api/v1/status/tsdb' | python3 -c "
import json, sys
data = json.load(sys.stdin)
print('Top labels by cardinality:')
for item in data['data']['seriesCountByLabelName'][:10]:
    print(f\"  {item['name']:30s} {item['value']}\")
"

# 5. 查看高基数指标
curl -s 'http://localhost:8428/api/v1/status/tsdb' | python3 -c "
import json, sys
data = json.load(sys.stdin)
print('Top metrics by series:')
for item in data['data']['seriesCountByMetricName'][:10]:
    print(f\"  {item['name']:40s} {item['value']}\")
"

15.2.6 集群组件通信故障

问题:vminsert 或 vmselect 无法连接 vmstorage

# 1. 检查各组件健康状态
curl http://vminsert:8480/health
curl http://vmselect:8481/health
curl http://vmstorage:8482/health

# 2. 检查网络连通性
telnet vmstorage 8400
telnet vmstorage 8401

# 3. 检查防火墙规则
sudo iptables -L -n | grep 840

# 4. 查看 vmstorage 日志
journalctl -u vmstorage | grep "connection refused"

# 5. 检查 vminsert 的 storageNode 配置
# 确保所有 vmstorage 地址正确且可达

15.3 日志分析

15.3.1 日志级别配置

# 日志级别设置
# -loggerLevel: INFO, WARN, ERROR, FATAL
victoria-metrics -loggerLevel=INFO

# 日志输出到文件
victoria-metrics -loggerOutput=file -loggerFilePath=/var/log/victoria-metrics/vm.log

# 日志格式
victoria-metrics -loggerFormat=json  # JSON 格式(便于 ELK 等收集)
victoria-metrics -loggerFormat=default  # 文本格式

15.3.2 关键日志信息

日志关键字含义排查方向
slow query慢查询优化查询或增加资源
slow insert慢写入检查磁盘 I/O 或减少写入量
out of memory内存不足增加内存或减少活跃序列
disk space磁盘空间清理空间或增加存储
connection refused连接被拒检查目标服务状态
too many open filesfd 耗尽增加文件描述符限制
permission denied权限问题检查文件/目录权限

15.3.3 日志分析命令

# 查看最近的错误日志
journalctl -u victoria-metrics -p err -n 50

# 按时间范围查看
journalctl -u victoria-metrics --since "2024-01-15 10:00" --until "2024-01-15 11:00"

# 实时跟踪日志
journalctl -u victoria-metrics -f

# 搜索慢查询
journalctl -u victoria-metrics | grep "slow query" | tail -20

# 搜索 OOM
journalctl -u victoria-metrics | grep -i "memory\|oom" | tail -20

# 统计错误数量
journalctl -u victoria-metrics -p err --since today | wc -l

# JSON 格式日志分析(如果启用了 JSON 格式)
journalctl -u victoria-metrics -o json | python3 -c "
import json, sys
for line in sys.stdin:
    entry = json.loads(line)
    msg = entry.get('MESSAGE', '')
    if 'error' in msg.lower():
        print(entry.get('__REALTIME_TIMESTAMP', ''), msg[:200])
"

15.4 诊断 API

15.4.1 健康检查

# 基础健康检查
curl http://localhost:8428/health
# 返回: {"status":"ok"}

# 集群版健康检查
curl http://vminsert:8480/health
curl http://vmselect:8481/health
curl http://vmstorage:8482/health

15.4.2 状态 API

# 构建信息(版本等)
curl -s http://localhost:8428/api/v1/status/buildinfo | python3 -m json.tool

# TSDB 状态(序列数、标签基数等)
curl -s http://localhost:8428/api/v1/status/tsdb | python3 -m json.tool

# 活跃查询列表
curl -s http://localhost:8428/api/v1/status/active_queries | python3 -m json.tool

# 运行时内存统计
curl -s http://localhost:8428/metrics | grep -E "^go_memstats_"

15.4.3 详细指标查询

# 写入速率
curl -s 'http://localhost:8428/api/v1/query?query=rate(vm_rows_inserted_total[5m])' | \
    python3 -c "
import json, sys
data = json.load(sys.stdin)
for r in data.get('data', {}).get('result', []):
    print(f\"{r['metric']}: {r['value'][1]}\")
"

# 活跃序列数
curl -s 'http://localhost:8428/api/v1/query?query=vm_active_timeseries' | \
    python3 -c "
import json, sys
data = json.load(sys.stdin)
for r in data.get('data', {}).get('result', []):
    print(f\"Active series: {r['value'][1]}\")
"

# 慢查询速率
curl -s 'http://localhost:8428/api/v1/query?query=rate(vm_slow_queries_total[5m])' | \
    python3 -c "
import json, sys
data = json.load(sys.stdin)
for r in data.get('data', {}).get('result', []):
    print(f\"Slow query rate: {r['value'][1]}/s\")
"

# 缓存命中率
curl -s 'http://localhost:8428/api/v1/query?query=vm_cache_hits_total/(vm_cache_hits_total+vm_cache_misses_total)' | \
    python3 -c "
import json, sys
data = json.load(sys.stdin)
for r in data.get('data', {}).get('result', []):
    cache_type = r['metric'].get('type', 'unknown')
    hit_rate = float(r['value'][1]) * 100
    print(f\"Cache {cache_type}: {hit_rate:.1f}% hit rate\")
"

15.5 性能问题排查

15.5.1 高 CPU 使用

# 1. 查看 CPU 使用率
top -b -n 1 | grep victoria-metrics

# 2. 查看并发查询数
curl -s http://localhost:8428/metrics | grep vm_concurrent

# 3. 限制查询并发
# 添加参数: -search.maxConcurrentRequests=8

# 4. 查看查询统计
curl -s 'http://localhost:8428/api/v1/status/active_queries'

15.5.2 高内存使用

# 1. 查看进程内存
ps aux | grep victoria-metrics
cat /proc/$(pgrep victoria-metrics)/status | grep -E "VmRSS|VmSize"

# 2. 查看活跃序列数(主要内存消耗)
curl -s 'http://localhost:8428/api/v1/status/tsdb' | python3 -c "
import json, sys
data = json.load(sys.stdin)
print(f\"Total series: {data['data']['totalSeries']}\")
print(f\"Label values: {data['data']['totalLabelValuePairs']}\")
"

# 3. 找出高基数标签
curl -s 'http://localhost:8428/api/v1/status/tsdb' | python3 -c "
import json, sys
data = json.load(sys.stdin)
for item in data['data']['seriesCountByLabelName']:
    if item['value'] > 10000:
        print(f\"WARNING: Label '{item['name']}' has {item['value']} values\")
"

# 4. 调整内存限制
# -memory.allowedPercent=50  (降低允许的内存百分比)

15.5.3 高磁盘 I/O

# 1. 检查磁盘 I/O 使用
iostat -x 1 5

# 2. 查看 Part 数量(过多会导致 I/O 压力)
ls /var/lib/victoria-metrics/data/big/ | wc -l
ls /var/lib/victoria-metrics/data/small/ | wc -l

# 3. 检查合并状态
curl -s http://localhost:8428/metrics | grep merge

# 4. 优化措施
# - 使用 SSD
# - 减少活跃序列数
# - 增加采集间隔(减少写入频率)

15.6 集群问题排查

15.6.1 数据不一致

# 检查各 vmstorage 节点的序列数
for port in 8482 8483 8484; do
    echo "vmstorage :${port}:"
    curl -s "http://localhost:${port}/api/v1/status/tsdb" | python3 -c "
import json, sys
data = json.load(sys.stdin)
print(f\"  Series: {data['data']['totalSeries']}\")
"
done

# 如果某个节点序列数明显不同,可能是:
# 1. 分片不均匀(check vminsert 路由)
# 2. 某个节点曾经不可用
# 3. 数据删除(retention)进度不同

15.6.2 vmstorage 节点不可用

# 1. 检查 vmstorage 健康状态
curl http://vmstorage1:8482/health

# 2. 查看 vminsert 的路由日志
journalctl -u vminsert | grep "unavailable" | tail -20

# 3. 检查 vmstorage 磁盘空间
# 低于 -storage.minFreeDiskSpaceBytes 时 vmstorage 会拒绝写入

# 4. 重启 vmstorage(如果有副本)
sudo systemctl restart vmstorage
# 新加入的节点会自动同步数据

15.7 数据恢复

15.7.1 从损坏中恢复

# 如果数据目录部分损坏
# 1. 停止 VictoriaMetrics
sudo systemctl stop victoria-metrics

# 2. 删除损坏的 Part
# 识别损坏的 Part(通常日志中会有报错)
ls /var/lib/victoria-metrics/data/big/
# 删除包含损坏 Part 的目录

# 3. 重启(VictoriaMetrics 会跳过损坏的 Part)
sudo systemctl start victoria-metrics

# 4. 从备份恢复丢失的数据
vmrestore \
    -src=s3://my-bucket/vm-backup/latest/ \
    -storageDataPath=/var/lib/victoria-metrics/data

15.7.2 强制合并

# 强制触发 Part 合并(通常不需要手动操作)
# 可以通过临时调整参数实现
# 注意:强制合并会增加 I/O 和 CPU 负载

# 查看当前合并状态
curl -s http://localhost:8428/metrics | grep merge

15.8 排错检查清单

#检查项命令期望结果
1服务运行curl localhost:8428/health{"status":"ok"}
2版本victoria-metrics --version最新稳定版
3日志journalctl -u vm -n 50无 ERROR
4磁盘df -h /var/lib/vm/> 20% 剩余
5内存free -h可用 > 10%
6CPUtop -b -n 1< 80%
7序列数curl /api/v1/status/tsdb稳定
8写入速率rate(vm_rows_inserted[5m])正常
9慢查询rate(vm_slow_queries[5m])接近 0
10缓存缓存命中率> 80%

本章小结

要点内容
排错流程服务状态 → 日志 → API → 资源 → 网络
日志分析journalctl + 关键字过滤
诊断 API/health/api/v1/status/*/metrics
性能问题CPU → 查询并发;内存 → 序列数;I/O → 磁盘/Part
数据恢复从备份恢复,或删除损坏的 Part

扩展阅读