



















当你需要评估 VictoriaMetrics 是否能满足业务需求时,如何量化其性能?写入吞吐量能达到多少?查询延迟的 P99 是多少?内存占用和时间序列数量是什么关系?理解了性能模型,你才能做出正确的容量规划。
读完本篇,你应该能回答:VictoriaMetrics 的写入吞吐模型是什么?查询延迟如何计算?内存占用和时间序列数量的关系是什么?硬件配置如何影响性能?
VictoriaMetrics 性能模型 容量规划 写入吞吐 查询延迟 内存模型 v1.146.0
学习重点提示 — 建议先通读全文,再重点回顾标注内容
重点掌握(必须)
- 写入吞吐模型:CPU 核数与写入速率的关系
- 查询延迟模型:Part 数量与查询时间的关系
- 内存占用模型:TSIDCache 37% 策略与内存需求
- 容量规划公式:实际部署的计算方法
次重点(了解即可)
- 压缩率的影响因素
- 网络带宽的影响
- 磁盘 I/O 的影响
文章目录
思考记忆提示 — 性能模型是容量规划的基础——没有模型就像盲人摸象
在生产环境中,容量规划是至关重要的工作。如果配置不足,会导致性能下降甚至 OOM;如果配置过剩,会造成资源浪费。VictoriaMetrics 官方提供了基准测试数据,但理解这些数据背后的原理,才能更好地应用它们。
我理解源码的意思是说
性能模型可以类比为汽车油耗与速度的关系:
没有模型 = 不知道油耗
买了一辆车,不知道油耗是多少。开了 100 公里才发现油耗是 15L/100km,太高了。或者你计划跑 1000 公里,不知道要加多少油。
有模型 = 知道油耗曲线
你知道了油耗模型:
这样你可以:
VM 性能模型同理:
以下是 VictoriaMetrics 官方公布的基准测试数据(Single-Node 模式):
| 指标 | 基准测试结果 | 测试条件 |
|---|---|---|
| 写入吞吐 | ~500K samples/s | 8 核 CPU,SSD |
| 查询 P99 延迟 | <50ms | 100 万 series,随机查询 |
| 内存占用 | Prometheus 的 1/7 | 相同数据量,相同查询模式 |
| 压缩率 | 10x-50x | 取决于数据特征 |
注意
基准测试数据是在特定硬件和数据集条件下得出的,实际生产环境可能有所不同。以下公式是基于基准测试数据推导的经验公式,用于容量规划参考。
思考记忆提示 — 写入吞吐主要由 CPU 决定——Goroutine 池设计让写入近乎线性扩展
VictoriaMetrics 的写入吞吐可以表示为:
写入吞吐公式:
T_write = N_cpu × C_write × E_parallel × F_protocol
其中:
T_write - 写入吞吐(samples/s)
N_cpu - CPU 核数
C_write - 每核每秒处理样本数(常数,~50K samples/s per core)
E_parallel - 并行效率因子(0.7-0.9,经验值)
F_protocol - 协议解析效率(0.8-0.95,取决于协议复杂度)
简化公式:
T_write ≈ N_cpu × 50K × 0.8
≈ N_cpu × 40K samples/s
示例:
4 核 → ~160K samples/s
8 核 → ~320K samples/s
16 核 → ~640K samples/s
32 核 → ~1.28M samples/s
以下是影响写入吞吐的关键因素:
| 因素 | 影响 | 说明 |
|---|---|---|
| CPU 核数 | 正相关 | 更多核数 = 更高吞吐(近乎线性) |
| 磁盘 I/O | 瓶颈 | SSD 建议;HDD 会限制吞吐 |
| 数据复杂度 | 负相关 | 标签越多、metric name 越长,解析越慢 |
| 网络带宽 | 瓶颈 | 10Gbps 网络下,1Gbit 约等于 125MB/s |
| 压缩开销 | 负相关 | NearestDelta + ZSTD 需要额外 CPU |
// 写入路径的性能瓶颈分析
// 写入流程及每个步骤的时间占比(估算):
// ┌─────────────────────────────────────────────────────────────┐
// │ 步骤 │ 时间占比 │ 瓶颈因素 │
// ├─────────────────────────────────────────────────────────────┤
// │ 1. HTTP 解析 │ 5% │ 网络、CPU │
// │ 2. 协议解析 │ 15% │ CPU │
// │ 3. TSID 查询/创建 │ 20% │ TSIDCache命中率 │
// │ 4. 数据写入 InMemory │ 15% │ 内存带宽 │
// │ 5. 索引更新 │ 25% │ indexDB写入 │
// │ 6. 锁竞争 │ 20% │ rawRowsShards分片数 │
// └─────────────────────────────────────────────────────────────┘
// 优化方向:
// 1. 增加 rawRowsShards 分片数(减少锁竞争)
// 2. 提高 TSIDCache 命中率(减少 indexDB 查询)
// 3. 使用 NVMe SSD(加速 indexDB 写入)
// 4. 调整合并策略(减少写入抖动)
小贴士 — 如何测试写入吞吐
可以使用 vmagent 或专业压测工具测试写入吞吐:
vmagent:抓取真实数据写入 VMvictoria-metrics-datasource:Grafana 数据源压测wrk:HTTP 基准测试工具思考记忆提示 — 查询延迟主要由 Part 数量决定——合并策略是控制延迟的关键
查询延迟公式:
T_query = T_index + T_scan + T_merge
其中:
T_index - 索引查询时间
= f(series_count) × (1 - cache_hit_rate)
≈ N_series × 100ns × (1 - cache_hit_rate)
T_scan - 数据扫描时间
= N_parts × T_part_scan
= N_parts × (data_size_per_part / disk_throughput)
T_merge - 结果归并时间
= O(N_parts × log(N_parts))
简化公式(无缓存命中):
T_query ≈ N_parts × 1ms + N_series × 100ns
示例:
10 个 Part → ~10-20ms
50 个 Part → ~50-100ms
100 个 Part → ~100-200ms
| 因素 | 影响 | 说明 |
|---|---|---|
| Part 数量 | 正相关 | 更多 Part = 更高扫描开销 |
| blockCache 命中率 | 负相关 | 命中缓存 → 避免磁盘 I/O |
| 查询范围 | 正相关 | 更大时间范围 → 更多 Part |
| 标签过滤器 | 正相关 | 正则匹配 → 额外计算 |
| 磁盘类型 | 瓶颈 | NVMe SSD >> SATA SSD >> HDD |
┌─────────────────────────────────────────────────────────────────────────┐
│ Part 数量与查询延迟的关系 │
│ │
│ Part 数量 │ 查询延迟(P99) │ 状态 │
│ ────────────────────────────────────────────────────────────────────── │
│ 1-10 │ < 50ms │ 理想状态 │
│ 10-50 │ 50-200ms │ 可接受 │
│ 50-100 │ 200ms-1s │ 警告,需要合并 │
│ > 100 │ > 1s │ 严重,需要立即合并 │
│ │
│ 控制 Part 数量的方法: │
│ 1. 调整 -defaultPartsToMerge 参数(默认 15) │
│ 2. 监控 active_merges 指标 │
│ 3. 使用 /internal/force_merge 手动触发合并 │
│ 4. 调整 -retentionPeriod 清理旧数据 │
└─────────────────────────────────────────────────────────────────────────┘
设计精髓
VM 查询性能优于 Prometheus 的核心原因:
思考记忆提示 — 内存占用是 VM 最引以为傲的指标——"省 7x RAM"是有数学支撑的
内存占用公式:
M_total = M_workingsetcache + M_blockcache + M_indexdb + M_os
其中:
M_workingsetcache - 工作集缓存
= memory.Allowed() × 75%
= RAM × 75%
M_blockcache - 数据块缓存
= M_workingsetcache × 25%
= RAM × 75% × 25% = RAM × 18.75%
M_indexdb - 索引缓存
= TSIDCache + MetricIDCache + MetricNameCache
= M_workingsetcache × 75%
= RAM × 56.25%
M_os - 操作系统开销
≈ 1-2GB(取决于 OS 和其他进程)
简化公式:
M_total ≈ RAM × 0.75 + 2GB
每百万 series 的内存需求:
M_per_million_series ≈ 300MB - 500MB
示例:
100 万 series → ~300-500MB
500 万 series → ~1.5-2.5GB
1000 万 series → ~3-5GB
| 因素 | 影响 | 说明 |
|---|---|---|
| series 数量 | 正相关 | 核心因素,每百万 series 约 300-500MB |
| 标签数量 | 正相关 | 更多标签 = 更大 metric name = 更大索引 |
| 查询模式 | 影响 | 热点查询 → 高缓存命中率 → 低内存需求 |
| memory.Allowed() | 控制 | 限制 VM 可用内存 |
┌─────────────────────────────────────────────────────────────────────────┐
│ VM 省 7x RAM 的原因分析 │
│ │
│ Prometheus 内存模型: │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 索引策略:全量 mmap │ │
│ │ - 所有索引常驻内存(通过 mmap) │ │
│ │ - 查询时内核加载 Page Cache │ │
│ │ - 缓存命中率不可控 │ │
│ │ │ │
│ │ 每百万 series 内存占用:~2-3GB │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ VictoriaMetrics 内存模型: │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 索引策略:按需缓存(TSIDCache 37%) │ │
│ │ - 只缓存热点索引 │ │
│ │ - 冷数据从磁盘读取 │ │
│ │ - 缓存命中率可控 │ │
│ │ │ │
│ │ 每百万 series 内存占用:~300-500MB │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ 节省比例:2.5GB / 0.4GB ≈ 6.25x ≈ 7x │
│ │
└─────────────────────────────────────────────────────────────────────────┘
思考记忆提示 — 压缩是 VM 高效存储的关键——NearestDelta + ZSTD 组合拳
压缩率公式:
CR = CR_timestamp × CR_value × CR_index
其中:
CR - 总压缩率
CR_timestamp - 时间戳压缩率(NearestDelta 算法)
≈ 10x-30x(取决于采样间隔稳定性)
CR_value - 值压缩率(NearestDelta + ZSTD)
≈ 2x-10x(取决于值的变化幅度)
CR_index - 索引压缩率(倒排索引 + commonPrefix)
≈ 2x-5x(取决于标签基数)
典型压缩率:
- Counter 类型(平滑变化):20x-50x
- Gauge 类型(波动较大):10x-20x
- Histogram 类型(稀疏):5x-10x
原始数据 vs 压缩后:
1 个样本(16 bytes)→ 压缩后 ~0.5-2 bytes
1 天数据(86400 秒采样)→ 约 40KB - 170KB
存储空间公式:
S_storage = S_samples + S_index + S_overhead
其中:
S_samples - 样本数据存储
= N_samples / CR_samples × sample_size
= N_samples × 1 byte(平均)
S_index - 索引存储
= N_series × avg_metric_name_length × 2
= N_series × 100 bytes(平均)
S_overhead - 系统开销
= S_samples × 10%(Part 元数据、BloomFilter 等)
简化公式:
S_per_million_series_per_day ≈ 500MB - 2GB(压缩后)
示例(100 万 series,30 天,10 秒采样):
样本数 = 1M × 8640 = 8.64B samples
样本存储 = 8.64B × 1 byte ≈ 8.6GB
索引存储 = 1M × 100 bytes ≈ 100MB
总存储 ≈ 8.6GB + 100MB + 0.9GB ≈ 9.6GB
小贴士 — 磁盘空间规划建议
生产环境磁盘空间规划:
思考记忆提示 — 容量规划是性能和成本之间的权衡——理解模型才能做出正确决策
┌─────────────────────────────────────────────────────────────────────────┐
│ 容量规划检查清单 │
│ │
│ 1. 确定业务需求 │
│ □ series 数量:当前 N,当前增长速率 │
│ □ 写入吞吐:samples/s 或 samples/day │
│ □ retention:90 天 / 180 天 / 1 年 │
│ □ 查询 QPS:查询频率和复杂度 │
│ │
│ 2. 计算资源需求 │
│ □ 内存 = series × 400 bytes × 安全系数 │
│ □ CPU = 吞吐 / 40K samples per core │
│ □ 磁盘 = 存储需求 × 2.0 安全系数 │
│ │
│ 3. 选择部署模式 │
│ □ Single-Node:< 500 万 series │
│ □ Cluster 模式:> 500 万 series 或高可用需求 │
│ │
│ 4. 验证配置 │
│ □ 吞吐测试:能否满足写入需求 │
│ □ 延迟测试:P99 延迟是否可接受 │
│ □ 内存测试:OOM 是否发生 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
案例:1000 万 series,90 天 retention,500K samples/s 写入
1. 内存计算:
M = 10M × 400 bytes × 1.5(安全系数)
= 6GB
建议:16GB RAM
2. CPU 计算:
N_cpu = 500K / 40K
= 12.5 cores
建议:16 核 CPU
3. 磁盘计算:
样本数 = 500K/s × 86400s × 90 days
= 3.89 trillion samples
存储(压缩后)= 3.89T × 1 byte
= 3.89 TB
安全系数 = 3.89TB × 2.0 = 7.78TB
建议:8TB - 10TB NVMe SSD
4. 部署模式:
1000 万 series > 500 万 series → Cluster 模式
Cluster 配置建议:
- 3 个 vmstorage 节点,每个 32GB RAM
- 2 个 vminsert 节点
- 2 个 vmselect 节点
注意
以上计算是简化模型,实际需求可能因数据特征、查询模式、硬件配置等因素而有所不同。建议在生产部署前进行实际压测验证。
思考记忆提示 — FAQ 是全篇的"临考前速背"模块,20 组覆盖全链路
近似线性,但不是完美的线性关系。由于锁竞争、内存带宽、缓存一致性等开销,实际吞吐约为线性值的 70-90%。
可能的原因:磁盘 I/O 瓶颈、网络瓶颈、数据复杂度高、配置不当。建议使用 pprof 分析 CPU 和内存使用,找出瓶颈。
正常情况下,每个分区应有 10-50 个 Part。超过 100 个 Part 会显著影响查询延迟,需要触发合并。
通过 /metrics 端点的 vm_parts_count 指标监控。也可以使用 vm_storage_parts 指标查看详细分类。
active_merges 表示当前正在进行的合并任务数量。如果长时间为 0,说明合并可能积压。
正常情况下命中率应高于 90%。如果命中率低于 80%,可能需要增加内存或调整缓存大小。
正常情况下命中率应高于 80%。命中率受查询模式和数据集大小影响。
典型压缩率 10x-50x,取决于数据特征。Counter 类型(平滑变化)压缩率高,Histogram 类型压缩率低。
公式:存储 = 样本数 × 1 byte × 2.0(安全系数)。示例:90 天 retention,500K samples/s ≈ 6.5TB 原始数据 → 约 8TB 磁盘空间。
存储空间与 retention 成正比。90 天 = 30 天 × 3,存储空间也约为 3 倍。
建议设置为机器总内存的 70-80%。剩余内存用于操作系统和 Page Cache。
内存不足会导致 OOM 或性能急剧下降。建议监控 vm_memory_frees 和 process_resident_memory_ bytes 指标。
通过 -workingsetcacheSize 参数调整。默认使用 memory.Allowed() 的 75% 作为 workingsetcache 总大小。
因为 VM 使用 TSIDCache 37% 策略,只缓存热点索引,而不是全量 mmap。这减少了约 7 倍的内存占用。
高基数标签、全量查询、blockCache 未命中等场景。建议避免高基数标签,控制查询范围。
官方建议 < 500 万 series,理论上限取决于可用内存。每百万 series 约需 500MB 内存。
支持水平扩展、高可用、租户隔离。适合 > 500 万 series 或需要高可用的场景。
生产环境强烈建议使用 NVMe SSD。HDD 的随机 I/O 性能严重影响查询延迟。
会,特别是 Cluster 模式下。建议使用 10Gbps 网络,避免网络成为瓶颈。
使用本文的公式计算:内存 = series × 400 bytes,CPU = 吞吐 / 40K,磁盘 = 存储需求 × 2.0。建议预留 50% 余量。
全篇必记总纲
VictoriaMetrics 的性能模型核心是三个经验公式:写入吞吐 ≈ CPU核数 × 40K samples/s、查询延迟 ≈ Part数量 × 1ms、内存占用 ≈ series数量 × 400 bytes。理解这三个公式,才能做好容量规划、性能调优、瓶颈定位。
本篇覆盖了 VictoriaMetrics 的性能模型,但还有很多细节尚未展开:
本文参考与源码链接:
• VictoriaMetrics 官方 FAQ
• VictoriaMetrics Cluster 文档
• lib/storage/ · 存储核心
• lib/mergeset/ · MergeSet 存储
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。