VictoriaMetrics 故障排查实战指南:查询异常、摄入缓慢、慢查询与集群不稳定的系统性定位方法
【免费下载链接】VictoriaMetricsVictoriaMetrics: fast, cost-effective monitoring solution and time series database项目地址: https://gitcode.com/GitHub_Trending/vi/VictoriaMetrics
本文基于 VictoriaMetrics 官方故障排查手册整理而成。它系统性地覆盖了使用 VictoriaMetrics(单机版与集群版)过程中最常遇到的五类问题——查询结果异常、数据摄入缓慢、慢查询、内存溢出(OOM)崩溃与集群不稳定,并给出磁盘空间异常与 ZFS 文件系统读取损坏等专项排查方案。读完本文,你将掌握一套"先查版本、再查参数、后看日志、配合监控与追踪"的标准化排查流程,能够借助vmui、查询追踪(query tracing)、Grafana 官方面板与告警规则,快速定位并解决线上问题。
通用排查清单:遇到任何问题的第一步
无论你遇到的是查询、摄入还是集群层面问题,VictoriaMetrics 官方都建议先按下面的清单逐项排查,避免在错误方向上浪费时间。
- 核对组件版本。检查出问题组件的版本号,并与 changelog 中记录的最新版本对比。如果你运行的是旧版本,问题很可能已经在新版本中被修复。升级前应重点阅读 changelog 顶部的Update notes部分,这里会标注升级时可能存在的破坏性变更与需要注意的特殊操作。
- 单机版升级见 Single-server-VictoriaMetrics.md 中的升级章节;
- 集群版升级见 Cluster-VictoriaMetrics.md 中的节点更新与重新配置章节。
- 其他组件的升级方式同样简单:向组件发送
SIGINT信号优雅停止,再启动新版本即可。
- 审查命令行参数。检查传给各组件(
victoria-metrics、vmstorage、vmselect、vminsert、vmagent、vmalert等)的 flag,删除任何你无法清晰说明其作用与影响的参数。VictoriaMetrics 各组件在设计上以默认参数运行即可表现良好——不必要的或理解不透彻的参数反而可能导致意外行为。 - 查看日志。日志往往直接包含根因与修复线索。若日志信息不足,可用错误信息的关键词进行搜索,很多问题都已在文档、社区问答与 GitHub issue 中被讨论过。
- 搜索已有讨论。使用与问题相关的多个关键词组合进行搜索;必要时在 VictoriaMetrics 的 GitHub issues 中查找(该渠道信噪比远低于通用搜索引擎,但在通用搜索失败时可能有用)。如果找到相关 issue 但缺少诊断细节,请在评论区补充,这会提高问题被尽快解决的几率。
- 搜索源码。VictoriaMetrics 集群版的源码位于仓库的
cluster分支,可在本地检出后搜索相关报错信息。GitHub 的代码搜索效果有限时,本地搜索更可靠。 - 上报新 issue。以上步骤都无效时,请携带尽可能详细的复现信息提交 issue。之后再在 VictoriaMetrics 的 Slack 频道发布 issue 链接(社区优先推荐先建 GitHub issue 再发 Slack,因为 GitHub issue 可被搜索引擎索引,便于后来者检索)。
- 四条 Pro tip:
- 若发现官方文档存在不完整或不准确之处,请提交 pull request 或新 issue 修正;
- 回答社区问题时优先直接给出链接而非大段复制粘贴原文;若链接资源本身信息不足,应先补充到原始资源再分享;
- 回答问题的最佳形式是"指向答案的直接链接",其次是"包含多个相关链接的简明消息",最差的是"误导性或完全错误的信息";
- 如果你能自己修复问题,欢迎直接提交 pull request。
查询结果异常:从简化查询到原始数据核对
遇到查询结果不符合预期时,VictoriaMetrics 官方建议按"由简到繁"的层次逐步收敛问题范围。
第一步:简化查询,逐层剥离聚合与函数
如果查询形如sum(rate(http_requests_total[5m])) by (job)结果异常,依次验证以下简化版本:
- 去掉最外层的
sum,执行rate(http_requests_total[5m])。聚合会掩盖缺失的序列、数据空洞与异常值; - 如果返回的序列过多,增加更具体的标签过滤。例如原查询在
job="foo"上结果异常,就改用rate(http_requests_total{job="foo"}[5m]),持续增加标签过滤直到返回的序列数量可控; - 去掉外层的
rate,直接执行http_requests_total,必要时同样用标签过滤来缩小序列范围。
如果最简查询仍然异常,说明查询本身可能构造不当。建议完整阅读 MetricsQL 文档,尤其重点理解其中的subqueries(子查询)与rollup functions(滚动聚合函数)章节——这两块是 MetricsQL 最容易用错、也最容易导致慢查询与异常结果的地方。
第二步:核对原始样本而非"评估后"的数据
注意,/api/v1/query(即时查询)与/api/v1/query_range(范围查询)返回的是经过评估计算的数据,并非存储的原始样本。在某些情况下,staleness(数据过时标记)、deduplication(数据去重) 或不规则的抓取行为都会影响评估结果。
验证原始数据的方法:
- 在
vmui(见 Single-server-VictoriaMetrics.md 中的 vmui 章节)的Raw Query标签页查看未经处理的样本; - 通过Export按钮或
/api/v1/export接口,按给定的[start..end]时间范围下载原始数据并核对:
# 单机版 curl http://victoriametrics:8428/api/v1/export -d 'match[]=http_requests_total' -d 'start=...' -d 'end=...' -d 'reduce_mem_usage=1' # 集群版(<vmselect> 为 vmselect 地址,<tenantID> 为租户 ID) curl http://<vmselect>:8481/select/<tenantID>/prometheus/api/v1/export -d 'match[]=http_requests_total' -d 'start=...' -d 'end=...' -d 'reduce_mem_usage=1'在 GitHub 上提交查询问题相关 issue 时,请一并附上这段原始数据,以便维护者在本机复现。
第三步:开启查询追踪(query tracing)
执行查询时开启 query tracing,追踪结果包含大量额外信息:查询执行各阶段耗时占比、序列匹配过程、缓存命中情况与内部改动。提交 issue 时附上 trace,维护者可以据此深入调查。查询追踪相关实现在app/vmselect的查询执行链路中,配合下述"慢查询"章节的-search.logSlowQueryDuration与查询执行统计一起使用效果更佳。
第四步:检查数据空洞与缓存
- 图中的数据空洞:这通常由采集间隔不规则导致(抓取时网络延迟或目标不可达、不规律的 push、时间戳不规则)。VictoriaMetrics 会基于数据样本的中位间隔自动填充空洞(见 keyConcepts 中范围查询与原始样本的说明)。对于不规则数据,中位数会被拉偏从而导致填充结果不正确。此时要么修复数据的不规则性,要么通过
-search.minStalenessInterval=5m参数强制使用静态间隔填充空洞(5m正是 Prometheus 的默认值)。该参数定义于 app/vmselect/promql/rollup.go,其用途正是"消除由时间戳间隔不规则导致的数据空洞"。同时还可参考同文件中的-search.maxStalenessInterval参数。 - 响应缓存干扰回填数据:当带有旧时间戳的样本被摄入(即 backfilling 回填)时,响应缓存可能返回异常结果。可尝试以下方式禁用缓存:
- 在 vmui 中点击Disable cache开关;
- 单机版传入
-search.disableCache参数,集群版对所有vmselect节点传入该参数; - 在每个
/api/v1/query与/api/v1/query_range请求上附加nocache=1查询参数;若使用 Grafana,可在 Prometheus 数据源的Custom Query Parameters字段中填写该参数。 - 若确认问题出在缓存,还可通过 url-examples 中描述的
internal/resetRollupResultCache处理器重置缓存。
第五步:集群版特有的响应一致性选项
- 默认情况下,当部分
vmstorage节点暂时不可用时,集群版会返回部分响应(partial response)。若你更看重查询一致性而非可用性,可给所有vmselect节点传入-search.denyPartialResponse参数——这样只要有一个vmstorage不可用,查询就会直接返回错误。另一个等价做法是在/api/v1/query与/api/v1/query_range请求上附加deny_partial_response=1查询参数(Grafana 中同样配置在Custom Query Parameters字段)。官方集群面板中还有"partial results"相关的可视化面板,见 dashboards/vm/victoriametrics-cluster.json。 - 如果给
vmselect传了-replicationFactor参数,建议移除——当vmstorage中数据的副本数少于该值时,可能导致响应不完整。 - 若发现刚写入的数据不能立即查询到,请阅读 keyConcepts 中关于查询延迟(query latency)行为的说明。
- 尝试升级到最新版本验证问题是否已修复。
- 再次检查传给各组件的所有命令行参数,删除意义不明者。
若以上步骤仍无法定位根因,请提交 bug 报告。不要只贴截图,建议通过 VMUI 分享查询语句、原始样本与 trace 结果。
数据摄入缓慢:最常见的原因与对策
VictoriaMetrics 摄入变慢通常可归因于以下几类问题。
内存不足导致storage/tsid缓存未命中(Slow inserts)
VictoriaMetrics(集群版中为vmstorage)会在内存中维护一个名为storage/tsid的缓存,用于为每个入站指标快速查找内部序列 ID。该缓存的最大容量由组件根据宿主机可用内存自动确定(相关实现见 lib/storage/storage.go 的SetTSIDCacheSize相关逻辑)。
当活动序列数量超过缓存容量时,VictoriaMetrics 必须去磁盘查找数据、解压、重建缺失的缓存条目再写回缓存,这会消耗额外 CPU 与磁盘读 I/O,直接拖慢摄入。
判断方法:官方 Grafana 面板中有Slow inserts曲线,展示摄入过程中storage/tsid缓存的未命中百分比。若该曲线超过 5% 且持续 10 分钟以上,基本可以断定活动序列数已超出缓存容量。
解决方案:
- 增加宿主机内存,直到 Slow inserts 降到 5% 以下。集群版需要增加所有
vmstorage节点的总可用内存——要么给每个节点加内存,要么增加vmstorage节点数来分摊负载; - 减少活动序列数量。使用官方面板中的活动序列数图表与 cardinality explorer(高基数浏览器) 定位高基数来源并修复。关于高基数概念见 FAQ;
- 保持标签顺序一致:同一时间序列若以不同顺序的标签到达,会降低摄入性能。Prometheus 与
vmagent抓取时天然保证标签顺序一致,但自定义或第三方客户端未必如此。兜底方案是为单机版或集群版vminsert开启-sortLabels=true参数,强制服务端归一化标签顺序(会略微增加摄入期 CPU 开销)。该参数定义于 app/vminsert/common/sort_labels.go。
高序列变动率(High churn rate)
遇到新序列的样本时,VictoriaMetrics 需要将该序列注册到内部索引(indexdb)中,以便查询时快速定位。注册新序列的过程比给已注册序列追加样本慢一个数量级。因此在高 churn rate 下,摄入速度会明显下降。
判断方法:官方面板提供Churn rate曲线,展示最近 24 小时内注册的新序列平均数。若该数字超过活动序列数,就需要定位并修复高 churn rate 的来源。最常见的根源是值频繁变化的标签(如timestamp、session_id),应尽量避免此类标签。cardinality explorer 可帮助识别这类标签。关于 churn rate 与 cardinality 的定义可参阅 FAQ。
资源不足(Resource shortage)
官方面板的Resource usage图表展示内存、CPU、磁盘 I/O 的使用情况。VictoriaMetrics 官方建议各组件在正常工作负载下保留以下余量,以优雅应对工作负载尖峰:
- 50% 的空闲 CPU
- 50% 的空闲内存
- 20% 的空闲磁盘空间
如果低于这些余量,负载稍有增加就可能导致显著的性能退化。例如:
- 空闲 CPU 接近 0 时,即便摄入速率轻微上升,也可能出现任意时长的摄入延迟;
- 空闲内存归零时,操作系统可能无法为 page cache 预留足够内存。VictoriaMetrics 依赖 page cache 加速对近期数据的查询——page cache 不足时系统必须从磁盘重读数据,磁盘读 I/O 会显著上升,拖慢查询与摄入;
- 空闲磁盘低于 20% 时,VictoriaMetrics 无法进行最优的后台数据合并,磁盘上的数据文件数量增多,进一步拖慢摄入与查询(见 Single-server-VictoriaMetrics.md 的存储章节)。
集群版:vminsert与vmstorage之间的网络延迟
集群版中,vminsert将入站数据打包成批量数据包,逐包发送给vmstorage,并在发送下一包之前等待vmstorage返回ack响应。若两者间网络延迟高(例如跨数据中心部署),这会成为摄入速度的瓶颈。
官方集群面板中vminsert的connection saturation面板可帮助判断:若该曲线接近 100%(1s),说明vminsert与vmstorage之间可能存在网络延迟问题,或vmstorage节点资源不足——后者需要增加vmstorage的资源(CPU、内存、磁盘 I/O)或增加节点数。
其他因素
- Noisy neighbor:确保 VictoriaMetrics 组件运行环境中没有其他资源密集型应用抢占内存、CPU、磁盘 I/O 与网络带宽。这类问题难以通过官方面板直接发现,需要在实例层面检查资源占用。
TooHighSlowInsertsRate告警但资源充足:当单机版或vmstorage有充足空闲 CPU 与内存仍触发该告警时,可将-cacheExpireDuration参数(单机版或vmstorage上)增大到**超过同一时间序列两次样本之间的间隔(即scrape_interval)**的值。- CPU 占用异常高:查看对应 Grafana 面板Resource usage部分的CPU spent on GC面板。若 GC 占用的 CPU 比例很高,可通过增大 GOGC 环境变量,以更高内存占用换取更低 CPU 占用。VictoriaMetrics 组件默认
GOGC=30,可尝试用GOGC=100运行观察是否降低 CPU 使用——注意更高的 GOGC 值可能增加内存占用。
慢查询:定位瓶颈与优化手段
VictoriaMetrics 会在查询执行时间超过-search.logSlowQueryDuration参数指定值时记录慢查询日志,该参数默认 5 秒,定义于 app/vmselect/main.go,传 0 可禁用慢查询日志。官方还提供:
- VMUI 中的top queries页面,展示执行时间最长的查询;
- query-stats 文档 中描述的查询执行统计,可将慢查询及其详细信息转储到日志。
常见的慢查询优化手段
- 用查询追踪定位瓶颈:query tracing 会展示每个执行步骤的耗时占比,帮助你理解处理的数据量级。
- 增加 CPU 与内存:为 VictoriaMetrics 增加资源可加速慢查询。集群版中,将
vmselect迁移到 CPU/内存更强的机器上即可提升查询速度——查询性能始终受处理该查询的那一个vmselect节点的资源上限约束。例如 2 vCPU 处理不过来时,迁移到 4 vCPU 可将重查询性能提升约 2 倍。官方集群面板中的concurrent select曲线接近上限时,优先增加vmselect节点数;有时增加vmstorage节点数也能提升慢查询速度。 - 重写慢查询。
慢查询的两大来源与优化
来源一:长回看窗口(lookbehind window)的告警/记录规则
实践中慢查询的主要来源是 vmalert 的 告警与记录规则 中方括号内带超长回看窗口的查询,这类查询常被用于 SLI/SLO 计算。例如:
avg_over_time(up[30d]) > 0.99该查询每次执行都需要读取并处理up序列过去 30 天的全部原始样本。若执行频繁,会占据大量 CPU、磁盘读 I/O、网络带宽与内存。优化方式:
- 缩小方括号内的回看窗口。例如
avg_over_time(up[10d])在 VictoriaMetrics 上消耗的计算资源比avg_over_time(up[30d])少约 3 倍; - 增大规则评估间隔,降低执行频率。例如把 vmalert 的
-evaluationInterval参数从1m提高到2m,可将相关计算资源消耗降低约 2 倍。
来源二:子查询(subquery)的误用
不深入理解子查询语义就很容易在不知情的情况下写出子查询。例如rate(sum(some_metric))会按照 MetricsQL 的隐式转换规则被转换为如下子查询:
rate( sum( default_rollup(some_metric[1i]) )[1i:1i] )这样的查询大概率不会返回预期结果,应改用sum(rate(some_metric))(业界共识是"先 rate 再 sum,绝不先 sum 再 rate")。关于如何识别与优化慢查询,MetricsQL 的隐式查询转换规则有详细说明。
内存溢出(OOM)崩溃:常见来源与预防
OOM 崩溃在 VictoriaMetrics 中最常见的三大来源如下。
不当的命令行参数
请审查传给各组件的 flag,删除任何作用不明的参数——不合理的参数值会推高内存与 CPU 占用,增加 OOM 风险。VictoriaMetrics 设计上以默认参数运行即可表现良好。
特别提醒:不建议手动调整 VictoriaMetrics 的缓存大小,这经常导致 OOM。官方 Single-server-VictoriaMetrics.md 的缓存调优(cache tuning)章节中列出了一批不推荐调整的参数。如果当前负载确实需要更大的缓存,更稳妥的做法是迁移到内存更大的宿主机,而非手动调缓存。
意外出现的重型查询
当查询需要选取并处理数百万个唯一时间序列时即属重型查询,可能触发 OOM——因为 VictoriaMetrics 需要在内存中保存每个序列的部分数据。应对措施:
- 使用 Single-server-VictoriaMetrics.md 中"资源使用限制"章节列出的各项设置来限制资源占用;
- 使用查询追踪定位重型查询来源;
- 结合查询执行统计(见 query-stats)记录慢查询详情。
缺乏应对负载尖峰的空闲内存
若组件在当前负载下几乎用尽全部内存,建议迁移到内存更大的宿主机,以抵御负载尖峰带来的 OOM 风险。官方建议至少保留 50% 的空闲内存来从容应对可能的负载尖峰。容量规划参考单机版的 capacity planning 与集群版的 capacity planning。
集群不稳定:资源、滚动重启与网络因素
VictoriaMetrics 集群在处理当前负载时若缺乏足够的空闲资源(CPU、内存、磁盘 I/O、网络带宽),就可能变得不稳定。最常见的诱因如下。
负载尖峰
例如活动序列数翻倍而集群没有足够空闲资源时,就可能不稳定。VictoriaMetrics 提供了多项配置来限制意外的负载尖峰,见 Cluster-VictoriaMetrics.md 的资源使用限制章节。
滚动升级 / 滚动重启
假设集群有N=3个vmstorage节点,逐一滚动重启时只有N-1=2个节点健康,健康节点上的负载至少增加100%/(N-1)=50%——它们要处理多 50% 的入站数据并在查询时多返回 50% 的数据。实际负载增幅更高,因为临时不可用的节点上的新序列会被重新路由给剩余节点注册。
若vmstorage在滚动重启前空闲资源(CPU、内存、磁盘 I/O)已不足 50%,就可能引发集群过载与不稳定。
缓解办法:增加vmstorage节点数。例如N=11个节点时,滚动重启造成的负载增幅为100%/(N-1)=10%。官方建议集群至少配置8 个vmstorage节点。若启用了复制,该推荐数量应乘以-replicationFactor,参见 Cluster-VictoriaMetrics.md 的复制与数据安全章节。
时间序列分片不均
vminsert会按时间序列名称与标签(并尊重其顺序)对入站序列进行一致性分片。若标签顺序不断变化,会导致分片计算错误,进而造成序列在vmstorage间分布不均。推送指标的客户端(如抓取时的 Prometheus 或vmagent)应保证标签顺序一致;若无法保证,可给vminsert设置-sortLabels=true参数(注意会略微增加vminsert的 CPU 占用)。
组件间网络不稳定
vminsert、vmselect、vmstorage之间的网络不稳定会导致错误率上升、超时或性能退化。排查方法:
- 检查官方集群 Grafana 面板上各组件的资源使用图。若 CPU 占用高,说明集群过载需要更多资源。注意:短时 100% 的 CPU 尖峰在 10–30 秒的典型抓取间隔下可能不可见,但仍会造成瞬时网络故障——此时需在操作系统层面用更高分辨率的工具检查 CPU;
- 可考虑增大
-vmstorageDialTimeout与-rpc.handshakeTimeout(后者自 v1.124.0 起可用)来缓解 CPU 尖峰的影响; - 若资源占用正常但网络问题依旧,根因很可能在 VictoriaMetrics 之外——例如不可靠或拥塞的网络链路(尤其是跨可用区或跨区域时)。多可用区部署可考虑 Cluster-VictoriaMetrics.md 描述的多级集群方案,用区域本地负载均衡器减少跨可用区连接;
- 若网络无法改善,增大
-vmstorageDialTimeout、-rpc.handshakeTimeout或-search.maxQueueDuration等超时参数可能有帮助,但应谨慎——过大的超时可能以其他方式损害集群稳定性(-search.maxQueueDuration的提示信息同样出现在 app/vmselect/main.go 的超时相关日志中); - 请牢记:VictoriaMetrics 假设组件间网络是可靠的。网络不稳定时,无论资源是否充足,集群整体稳定性都可能下降。
集群不稳定的根本解法是确保组件拥有足够的空闲资源来从容应对负载增长,具体参考 Cluster-VictoriaMetrics.md 的容量规划与集群扩容/伸缩章节。
磁盘空间占用异常:快照、indexdb 与高基数
若单机版 VictoriaMetrics 或集群版vmstorage占用磁盘空间过大,请按以下顺序检查。
清理旧快照
确保没有残留的旧快照占用磁盘空间。相关操作参见 Single-server-VictoriaMetrics.md 的快照管理章节、快照排查章节以及 vmbackup.md 的排查章节。
检查 indexdb 与 data 目录的相对大小
正常情况下,<-storageDataPath>/indexdb目录的大小应小于<-storageDataPath>/data目录(-storageDataPath为对应的命令行参数值)。若监控配置正确,可用如下 MetricsQL 查询校验:
sum(vm_data_size_bytes{type=~"indexdb/.+"}) without(type) / sum(vm_data_size_bytes{type=~"(storage|indexdb)/.+"}) without(type)若该查询返回值大于 0.5,则很可能存在高 churn rate 问题,导致indexdb与data目录同时占用过多磁盘空间。解决办法是用 cardinality explorer 定位并修复高 churn rate 的来源。
做好监控:预防绝大多数问题
完善的监控能帮助识别并预防上文列出的绝大多数问题:
- 官方 Grafana 面板包含反映 VictoriaMetrics 各组件健康状态、资源占用及其他关键指标的面板(单机版面板见 dashboards/victoriametrics.json,集群版见 dashboards/vm/victoriametrics-cluster.json,还可通过 dashboards 了解面板的构建与使用方式);
- 官方推荐了一组告警规则,配置方式见 deployment/docker 的 alerts 说明,可在问题发生时及时收到通知并获取解决建议;
- 官方团队内部重度依赖这些面板与告警并持续改进,保持它们及时更新非常重要。
ZFS 文件系统上的读损坏:-fs.disableMincore参数
在某些 ZFS 文件系统上,将内存映射文件(mmap)的读取与mincore()系统调用混用,可能触发 ZFS 内存缓存(ARC)中的缺陷,导致 VictoriaMetrics 进程出现数据读损坏。该场景已在 VictoriaMetrics 实例访问 ZFS 上的数据目录时被观察到。
典型症状:
- 访问 ZFS 数据时出现意外的读取错误;
- 查询结果损坏或不一致;
- 存储/查询组件从 ZFS 读取时崩溃或 panic。
缓解方法:使用-fs.disableMincore参数禁用mincore()系统调用:
./bin/victoria-metrics --storageDataPath /path/to/zfs/data --fs.disableMincore从源码看,该参数定义于 lib/fs/reader_at.go,用于控制是否通过mincore()检查mmap()文件的内存驻留状态;实际使用时会在 lib/fs/reader_at.go 处与平台是否支持mincore()共同决定是否启用该调用路径。若你的部署将 VictoriaMetrics 数据目录放在 ZFS 上并观察到上述症状,可启用该参数规避问题。
总结
VictoriaMetrics 的故障排查遵循"版本 → 参数 → 日志 → 监控/追踪 → 上报"的层次化方法论:查询异常时从简化查询、核对原始数据、开启追踪逐步收敛;摄入缓慢时优先排查storage/tsid缓存未命中、高 churn rate 与资源余量;慢查询则聚焦长回看窗口规则与子查询误用;OOM 与集群不稳定归根结底多与不合理的参数、不足的资源余量及不可靠的网络相关。配合官方 Grafana 面板、告警规则、vmui 的 Raw Query / top queries 与查询追踪,绝大多数问题都能在数分钟内定位根因。
【免费下载链接】VictoriaMetricsVictoriaMetrics: fast, cost-effective monitoring solution and time series database项目地址: https://gitcode.com/GitHub_Trending/vi/VictoriaMetrics
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考