惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
SecWiki News
SecWiki News
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Forbes - Security
Forbes - Security
Schneier on Security
Schneier on Security
W
WeLiveSecurity
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Google Online Security Blog
Google Online Security Blog
O
OpenAI News
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Secure Thoughts
PCI Perspectives
PCI Perspectives
人人都是产品经理
人人都是产品经理
Blog — PlanetScale
Blog — PlanetScale
S
SegmentFault 最新的问题
Help Net Security
Help Net Security
G
GRAHAM CLULEY
Latest news
Latest news
V
Visual Studio Blog
The Cloudflare Blog
T
Troy Hunt's Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Stack Overflow Blog
Stack Overflow Blog
GbyAI
GbyAI
I
InfoQ
Know Your Adversary
Know Your Adversary
B
Blog RSS Feed
V2EX - 技术
V2EX - 技术
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
H
Heimdal Security Blog
Y
Y Combinator Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
The GitHub Blog
The GitHub Blog
P
Palo Alto Networks Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Tor Project blog
T
Threat Research - Cisco Blogs
博客园 - 三生石上(FineUI控件)
Cloudbric
Cloudbric
博客园 - Franky
博客园 - 叶小钗
S
Security @ Cisco Blogs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
阮一峰的网络日志
阮一峰的网络日志
WordPress大学
WordPress大学
T
Threatpost
MongoDB | Blog
MongoDB | Blog
V
Vulnerabilities – Threatpost
Martin Fowler
Martin Fowler

博客园 - 左扬

VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 与其他 TSDB 对比:Prometheus/InfluxDB/Thanos/VM VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 模块依赖图——从 import 语句看组件关系 VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— Goroutine 池/atomic/零拷贝/sync.Pool VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 多租户架构——accountID/projectID 与 tenant 隔离 VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 版本演进:1.146.0 LTS 重大更新解析 VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 整体数据流:一条监控数据的完整生命周期 VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 架构演进:从 TSDB 到 MergeSet 的设计取舍 VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— Single-Node vs Cluster 模式本质区别 VictoriaMetrics 1.146.0 源码【左扬精讲】—— 开篇总览 Rust 专题【左扬精讲】—— 从语法到灵魂:Ownership、Borrowing 与多语言对比 kubernetes 源码【左扬精讲】—— kube-scheduler 启动流程源码分析 Rust 专题【左扬精讲】—— 选择控制语句、运算符与格式化输出 Rust 专题【左扬精讲】—— 所有权详解 Rust 专题【左扬精讲】—— 作用域详解 Rust 专题【左扬精讲】—— 变量、常量与标量数据类型 kubernetes 源码 / Operator 专题【左扬精讲】—— Deployment Controller 源码分析:从对象创建到滚动更新 kubernetes 源码 / Operator 专题【左扬精讲】—— Operator 开发中的 Webhook:从准入控制到生产部署 Kubernetes源码 / Operator 专题【左扬精讲】—— 实现 Application Controller:从零构建生产级控制器 Kubernetes 编程 / Operator 专题【左扬精讲】—— 定义 Application 资源 + 添加自定义新 API 完整指南 Kubernetes 源码【左扬精讲】—— kube-scheduler(调度专题 · 八):内部架构与核心组件 Kubernetes 源码【左扬精讲】—— kube-scheduler(调度专题 · 八): —— 从入口到调度的全链路源码剖析(k8s v1.36.1) DeepSeek-R1 多模态 R1 / VLM-GRPO【左扬精讲】—— Qwen2-VL 微调与视觉推理强化学习实战 DeepSeek-R1 工业 RAG + 微调混合系统【左扬精讲】—— R1 系列收官之作:从 Prompt → RAG → 微调 选型决策树 DeepSeek-R1 推理时扩展【左扬精讲】—— o1 / R1 慢思考机制:Self-Consistency + ToT + PRM 详解 DeepSeek-R1 端侧 LLM 工程【左扬精讲】—— llama.cpp 调参与 Apple Silicon / 国产 NPU / Android 端侧落地全攻略 DeepSeek-R1 vLLM + k8s 生产部署【左扬精讲】—— 从单卡 7B 到 100 卡 671B MoE 集群的工业化部署实战 DeepSeek-R1 评估与系统(Evaluation & Systems)【左扬精讲】—— 从 GSM8K/MMLU 到 LLM-as-Judge 的工业级评估方法论 DeepSeek-R1 模型训练与算法【左扬精讲】—— GRPO 进阶算法:DAPO / PRIME / RLVR / PRM 四大 2025 前沿改进 DeepSeek-R1 模型训练与算法【左扬精讲】—— 数据蒸馏:用 DeepSeek-R1-671B 生成 800K 高质量 CoT 样本的完整流水线 DeepSeek-R1 优化与微调实战【左扬精讲】—— 从 R1 强化学习新范式到 GRPO 微调一站式入门 Kubernetes 源码【左扬精讲】—— kube-scheduler(调度专题 · 七):自定义插件开发实战 —— 手写一个 Score 插件并注册到集群 Kubernetes 源码【左扬精讲】—— kube-scheduler(调度专题 · 六):Scheduler Profile 与多调度器 —— 如何配置多个 profile 实现多租户、Coordinated LeaderElection Kubernetes 源码【左扬精讲】—— kube-scheduler(调度专题 · 五):SchedulingQueue 与 QueueingHint —— 三段队列的细节、v1.36 新引入的 QueueingHint 工作机制 Kubernetes 源码【左扬精讲】—— kube-scheduler(调度专题 · 四):抢占(Preemption)算法剖析 —— DefaultPreemption 如何选 victim、PodDisruptionBudget 如何约束 Kubernetes 源码【左扬精讲】—— kube-scheduler(调度专题 · 二):内置插件逐个精读 — NodeResourcesFit / NodeAffinity / TaintToleration / PodTopologySpread / VolumeBinding / InterPodAffinity Kubernetes 源码 / Operator 专题【左扬精讲】——kube-scheduler(调度专题):调度器内置插件 逐个精读 k8s 源码级精讲(二十六):调度器内置插件逐个精读 Kubernetes 源码 / Operator 专题【左扬精讲】——kube-scheduler(调度专题):调度器内置插件精读 — NodeResourcesFit / NodeAffinity / TaintToleration / PodTopologySpread / VolumeBinding / InterPodAffinity Kubernetes 源码 / Operator 专题【左扬精讲】——kube-scheduler(调度专题):Scheduling Framework 扩展点逐个源码拆解 Kubernetes 源码 / Operator 专题【左扬精讲】——kube-scheduler(调度专题):初识调度模型、内部架构与事件驱动机制 Kubernetes 编程 / client-go 专题【左扬精讲】—— 四种客户端:为什么、怎么选、怎么用 Kubernetes 编程 / Operator 专题【左扬精讲】—— controller-runtime、kubebuilder、operator-sdk 三大框架深度对比 Kubernetes 编程 / Operator 专题【左扬精讲】—— 深入理解 ManagedFields 字段冲突协调机制 Kubernetes 编程 / Operator 专题【左扬精讲】—— k8s Finalizers 深度解析:对象的生命周期与删除控制 Kubernetes 编程 / Operator 专题【左扬精讲】—— OwnerReference 字段与级联删除机制 Kubernetes 编程 / Operator 专题【左扬精讲】—— 深入学习 Server-Side Apply:managedFields 替代 last-applied-configuration 的演进方向 Kubernetes 编程 / Operator 专题【左扬精讲】—— k8s Annotations 与元数据体系(Operator 专题) Kubernetes 编程 / Operator 专题【左扬精讲】—— RESTMapper:把 Group / Version / Kind / Resource 四元组翻译成 REST 路径的"查字典"大师 Kubernetes 编程 / Operator 专题【左扬精讲】—— Converter 资源版本转换器 Kubernetes 编程 / Operator 专题【左扬精讲】—— Application 业务扩展:从单 Deployment 到多 Workload 的复合 Operator 演进 Kubernetes 编程 / Operator 专题【左扬精讲】—— OwnerReference / Finalizer / 准入控制:k8s 资源生命周期的三大支柱 Kubernetes 编程 / Operator 专题【左扬精讲】—— controller-runtime 框架内幕:从 Manager 到 Reconcile 的全栈拆解 Kubernetes 编程 / Operator 专题【左扬精讲】—— 生产级 Operator 最佳实践:并发安全、资源清理与高可用设计 Kubernetes 编程 / Operator 专题【左扬精讲】—— application-operator Reconcile 循环源码精讲:从 client-go Informer 到 workqueue 的全链路解剖 Kubernetes 编程 / Operator 专题【左扬精讲】—— 从零搭建一个 application-operator 新项目:脚手架、API 设计与基于原生 DeploymentStatus/ServiceStatus 的状态建模 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:生产级 Controller 实践:并发安全、资源清理与高可用设计 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析: Controller 调试与诊断工具:从日志分析到问题定位 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:DynamicClient 操作 CRD:无需代码生成的动态操作 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:控制器与 APIServer 完整交互流程:从 Watch 到缓存同步 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:错误处理与重试机制:WorkQueue 限速器详解 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:Leader 选举机制:高可用控制器的必备技能 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:Controller 开发模式完整实战 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:SharedInformerFactory 与等待缓存同步 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:从认证配置到 Deployment 操作 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:版本对应、架构组件与组件关系 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:Informer 源码深度解析:从底层原理到实战应用 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:Reflector 源码深度解析 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:ListWatcher 源码深度解析 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:Indexer 与 ThreadSafeStore 核心原理与源码深度剖析 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:DeltaFIFO 核心原理与源码深度剖析 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:workqueue 核心原理与实战 Kubernetes 编程 / Operator 专题【左扬精讲】—— runtime.Codec 资源编解码:serializer 与 codec 差异、编解码数据结构、codec 核心调用链路 Kubernetes 编程 / Operator 专题【左扬精讲】—— Scheme 资源注册机制全解 Kubernetes 编程 / Operator 专题【左扬精讲】—— Kubernetes 自定义资源的内部版本与外部版本:从源码看版本定义机制 Kubernetes 编程 / Operator 专题【左扬精讲】—— Kubernetes 1.36.1 核心 API 数据结构全解 Kubernetes 编程 / Operator 专题【左扬精讲】—— Kubernetes 构建过程 【AIOPS】一文读懂LLM【左扬精讲】:从诞生到普及,解锁大语言模型的核心密码 【AIOPS】AI Agent 专题【左扬精讲】核心功能篇:MCP-VictoriaMetrics Hooks 源码精讲:Hooks 可观测性的无侵入式实现 【AIOPS】AI Agent 专题【左扬精讲】核心功能篇:MCP-VictoriaMetrics Golang 配置解析源码精讲 ——SRE 自定义 Agent 核心技巧 【AIOPS】AI Agent 专题【左扬精讲】核心功能篇:MCP-VictoriaMetrics Golang 并发模型解析 ——SRE 应对高并发采集的调优思路 【AIOPS】AI Agent 专题【左扬精讲】基础架构篇:MCP-VictoriaMetrics Golang 源码整体架构拆解 ——SRE 必懂的核心模块与数据流 OpenTelemetry 开发实战【左扬精讲】—— 云原生可观测体系构建与分布式追踪二次开发 Kubernetes 编程 / Operator 专题【左扬精讲】—— Operator 开发实战项目 7 —— 基于流量预测模型的智能弹性扩缩容 Operator 实战(AIOps 模型训练与智能扩容(下篇)—— 预测式弹性扩缩容 Operator 落地实现) Kubernetes 编程 / Operator 专题【左扬精讲】—— Operator 开发实战项目 7 —— 基于流量预测模型的智能弹性扩缩容 Operator 实战(AIOps 模型训练与智能扩容(上篇)—— 时序预测模型构建与离线训练) Kubernetes 编程 / Operator 专题【左扬精讲】—— Operator 开发实战项目 6 —— 基于运维专家知识库的智能故障诊断与排查 Operator 实战 Kubernetes 编程 / Operator 专题【左扬精讲】—— Operator 开发实战项目 5 —— 基于大语言模型(LLM)的实时日志流智能监测 Operator 实现 Kubernetes 编程 / Operator 专题【左扬精讲】—— Operator 开发实战项目 4 —— 基于 Operator 实现大模型私有化部署与管理 Kubernetes 编程 / Operator 专题【左扬精讲】—— Operator 开发实战项目 3(上篇)—— 面向 AI / 算力调度场景:GPU 竞价实例资源池统一调度管理 Operator 开发 Kubernetes编程 / Operator专题【左扬精讲】—— Operator 开发实战项目 2 —— 面向零售 / 电商潮汐流量难题:多云多集群数据中心级全链路弹性伸缩 DataCenter Scaler Operator 从 0 到 1 全链路开发 Kubernetes编程 / Operator专题【左扬精讲】—— 深入理解Kubebuilder注解:为什么Operator开发离不开这些特殊注释 Kubernetes编程 / Operator专题【左扬精讲】—— Operator 开发实战项目1 —— Applicaion Operator(通用应用生命周期管理 Operator 实战) Pod 镜像拉取失败?kubectl edit pods修改镜像地址的底层原理与实操 (该方法仅为临时应急方案,并非长期解决方案) Kubernetes编程/Operator专题精讲—— 理解控制器模式 —— 控制器模式的核心原理与实现逻辑(从原理到实践) 【AIOPS】AI Agent 专题【左扬精讲】模型微调实战:一站式平台 LLaMA-Factory 【AIOPS】AI Agent 专题【左扬精讲】基于 k8s+vLLM+Ray 分布式部署全指南:架构设计、资源调度与性能优化 【AIOPS】AI Agent专题【左扬精讲】非量化版DeepSeek分布式部署全指南:精度保障、显存规划与Ollama/vLLM选型 【AIOPS】AI Agent 专题【左扬精讲】零开发框架实现 ReAct Agent(Go SRE友好)
VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 写入吞吐/查询延迟/内存占用的数学模型
左扬 · 2026-06-29 · via 博客园 - 左扬

VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 写入吞吐/查询延迟/内存占用的数学模型

当你需要评估 VictoriaMetrics 是否能满足业务需求时,如何量化其性能?写入吞吐量能达到多少?查询延迟的 P99 是多少?内存占用和时间序列数量是什么关系?理解了性能模型,你才能做出正确的容量规划。

读完本篇,你应该能回答:VictoriaMetrics 的写入吞吐模型是什么?查询延迟如何计算?内存占用和时间序列数量的关系是什么?硬件配置如何影响性能?

VictoriaMetrics 性能模型 容量规划 写入吞吐 查询延迟 内存模型 v1.146.0

学习重点提示建议先通读全文,再重点回顾标注内容

重点掌握(必须)

  • 写入吞吐模型:CPU 核数与写入速率的关系
  • 查询延迟模型:Part 数量与查询时间的关系
  • 内存占用模型:TSIDCache 37% 策略与内存需求
  • 容量规划公式:实际部署的计算方法

次重点(了解即可)

  • 压缩率的影响因素
  • 网络带宽的影响
  • 磁盘 I/O 的影响

文章目录

一、问题的起点:为什么需要性能模型?

思考记忆提示性能模型是容量规划的基础——没有模型就像盲人摸象

  • 性能模型帮助预测系统行为
  • 性能模型帮助容量规划
  • 性能模型帮助瓶颈定位
  • 面试高频提问:如何评估一个系统的性能上限?

在生产环境中,容量规划是至关重要的工作。如果配置不足,会导致性能下降甚至 OOM;如果配置过剩,会造成资源浪费。VictoriaMetrics 官方提供了基准测试数据,但理解这些数据背后的原理,才能更好地应用它们。

我理解源码的意思是说

性能模型可以类比为汽车油耗与速度的关系

没有模型 = 不知道油耗

买了一辆车,不知道油耗是多少。开了 100 公里才发现油耗是 15L/100km,太高了。或者你计划跑 1000 公里,不知道要加多少油。

有模型 = 知道油耗曲线

你知道了油耗模型:

  • 时速 60km/h → 油耗 5L/100km(经济时速)
  • 时速 120km/h → 油耗 8L/100km(高速巡航)
  • 时速 180km/h → 油耗 12L/100km(激烈驾驶)

这样你可以:

  • 根据行程估算油耗(容量规划)
  • 选择合适的时速(性能调优)
  • 发现油耗异常时检查问题(瓶颈定位)

VM 性能模型同理

  • 知道写入吞吐与 CPU 核数的关系
  • 知道查询延迟与 Part 数量的关系
  • 知道内存占用与时间序列数量的关系

1.1 VictoriaMetrics 官方基准测试

以下是 VictoriaMetrics 官方公布的基准测试数据(Single-Node 模式):

指标基准测试结果测试条件
写入吞吐 ~500K samples/s 8 核 CPU,SSD
查询 P99 延迟 <50ms 100 万 series,随机查询
内存占用 Prometheus 的 1/7 相同数据量,相同查询模式
压缩率 10x-50x 取决于数据特征

注意

基准测试数据是在特定硬件和数据集条件下得出的,实际生产环境可能有所不同。以下公式是基于基准测试数据推导的经验公式,用于容量规划参考。

二、写入吞吐模型:CPU 核数与写入速率

思考记忆提示写入吞吐主要由 CPU 决定——Goroutine 池设计让写入近乎线性扩展

  • 写入吞吐与 CPU 核数 近似线性关系
  • rawRowsShards 分片实现了并行写入
  • 面试高频提问:VM 的写入性能如何随 CPU 核数扩展?

2.1 写入吞吐公式

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

2.2 影响写入吞吐的因素

以下是影响写入吞吐的关键因素:

因素影响说明
CPU 核数 正相关 更多核数 = 更高吞吐(近乎线性)
磁盘 I/O 瓶颈 SSD 建议;HDD 会限制吞吐
数据复杂度 负相关 标签越多、metric name 越长,解析越慢
网络带宽 瓶颈 10Gbps 网络下,1Gbit 约等于 125MB/s
压缩开销 负相关 NearestDelta + ZSTD 需要额外 CPU

2.3 写入路径的性能分析

// 写入路径的性能瓶颈分析

// 写入流程及每个步骤的时间占比(估算):
// ┌─────────────────────────────────────────────────────────────┐
// │ 步骤                    │ 时间占比  │ 瓶颈因素              │
// ├─────────────────────────────────────────────────────────────┤
// │ 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:抓取真实数据写入 VM
  • victoria-metrics-datasource:Grafana 数据源压测
  • wrk:HTTP 基准测试工具

三、查询延迟模型:Part 数量与扫描时间

思考记忆提示查询延迟主要由 Part 数量决定——合并策略是控制延迟的关键

  • 查询延迟与 Part 数量 近似线性关系
  • blockCache 命中率显著影响缓存命中延迟
  • 面试高频提问:为什么 VM 的查询延迟比 Prometheus 低?

3.1 查询延迟公式

查询延迟公式:

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

3.2 影响查询延迟的因素

因素影响说明
Part 数量 正相关 更多 Part = 更高扫描开销
blockCache 命中率 负相关 命中缓存 → 避免磁盘 I/O
查询范围 正相关 更大时间范围 → 更多 Part
标签过滤器 正相关 正则匹配 → 额外计算
磁盘类型 瓶颈 NVMe SSD >> SATA SSD >> HDD

3.3 Part 数量对查询的影响

┌─────────────────────────────────────────────────────────────────────────┐
│                    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 的核心原因:

  • blockCache 按需缓存:只缓存命中的数据块,避免无关数据
  • MergeSet 无分层:查询只需扫描相关 Part,不需要跨层合并
  • 倒排索引:标签查询直接定位 series,不需要扫描全量数据
  • PromQL 优化:并行执行、rollup 缓存、streaming 算子

四、内存占用模型:时间序列数量与 RAM

思考记忆提示内存占用是 VM 最引以为傲的指标——"省 7x RAM"是有数学支撑的

  • 内存占用与 series 数量 近似线性关系
  • TSIDCache 37% 策略是核心设计
  • 面试高频提问:VM 为什么能省 7x RAM?

4.1 内存占用公式

内存占用公式:

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

4.2 影响内存占用的因素

因素影响说明
series 数量 正相关 核心因素,每百万 series 约 300-500MB
标签数量 正相关 更多标签 = 更大 metric name = 更大索引
查询模式 影响 热点查询 → 高缓存命中率 → 低内存需求
memory.Allowed() 控制 限制 VM 可用内存

4.3 省 7x RAM 的原理

┌─────────────────────────────────────────────────────────────────────────┐
│                    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 组合拳

  • 压缩率与数据特征强相关
  • NearestDelta 对时序数据特别有效
  • 面试高频提问:VM 的压缩率是多少?

5.1 压缩率公式

压缩率公式:

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

5.2 存储空间计算

存储空间公式:

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.5-2.0 安全系数
  • 预留 20% 空余空间(减少磁盘碎片)
  • 考虑 90 天 retention → 90/30 × 基础存储

六、容量规划:实际部署的计算方法

思考记忆提示容量规划是性能和成本之间的权衡——理解模型才能做出正确决策

  • 容量规划需要考虑三个维度:吞吐、延迟、存储
  • 瓶颈往往是木桶效应:最弱的环节决定整体
  • 面试高频提问:如何为 1000 万 series 规划 VM 集群?

6.1 容量规划模板

┌─────────────────────────────────────────────────────────────────────────┐
│                    容量规划检查清单                                        │
│                                                                          │
│  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 是否发生                                             │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

6.2 实际案例计算

案例: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:常见疑问

思考记忆提示FAQ 是全篇的"临考前速背"模块,20 组覆盖全链路

  • Q1-Q5 围绕写入吞吐:CPU 核数与写入速率的关系
  • Q6-Q10 围绕查询延迟:Part 数量与延迟的关系
  • Q11-Q15 围绕内存占用:series 数量与 RAM 的关系
  • Q16-Q20 围绕容量规划:实际部署的计算方法

Q1. VM 的写入吞吐与 CPU 核数是线性关系吗?

近似线性,但不是完美的线性关系。由于锁竞争、内存带宽、缓存一致性等开销,实际吞吐约为线性值的 70-90%。

Q2. 为什么我的 VM 写入吞吐达不到官方基准?

可能的原因:磁盘 I/O 瓶颈、网络瓶颈、数据复杂度高、配置不当。建议使用 pprof 分析 CPU 和内存使用,找出瓶颈。

Q3. Part 数量多少算正常?

正常情况下,每个分区应有 10-50 个 Part。超过 100 个 Part 会显著影响查询延迟,需要触发合并。

Q4. 如何监控 Part 数量?

通过 /metrics 端点的 vm_parts_count 指标监控。也可以使用 vm_storage_parts 指标查看详细分类。

Q5. 什么是 active_merges?

active_merges 表示当前正在进行的合并任务数量。如果长时间为 0,说明合并可能积压。

Q6. TSIDCache 命中率多少算正常?

正常情况下命中率应高于 90%。如果命中率低于 80%,可能需要增加内存或调整缓存大小。

Q7. blockCache 命中率多少算正常?

正常情况下命中率应高于 80%。命中率受查询模式和数据集大小影响。

Q8. VM 的压缩率是多少?

典型压缩率 10x-50x,取决于数据特征。Counter 类型(平滑变化)压缩率高,Histogram 类型压缩率低。

Q9. 磁盘空间如何计算?

公式:存储 = 样本数 × 1 byte × 2.0(安全系数)。示例:90 天 retention,500K samples/s ≈ 6.5TB 原始数据 → 约 8TB 磁盘空间。

Q10. retention 对存储空间的影响是什么?

存储空间与 retention 成正比。90 天 = 30 天 × 3,存储空间也约为 3 倍。

Q11. memory.Allowed() 如何设置?

建议设置为机器总内存的 70-80%。剩余内存用于操作系统和 Page Cache。

Q12. 内存不足会发生什么?

内存不足会导致 OOM 或性能急剧下降。建议监控 vm_memory_freesprocess_resident_memory_ bytes 指标。

Q13. 如何调整 TSIDCache 大小?

通过 -workingsetcacheSize 参数调整。默认使用 memory.Allowed() 的 75% 作为 workingsetcache 总大小。

Q14. 为什么 VM 比 Prometheus 省内存?

因为 VM 使用 TSIDCache 37% 策略,只缓存热点索引,而不是全量 mmap。这减少了约 7 倍的内存占用。

Q15. 什么场景下 VM 内存占用会很高?

高基数标签、全量查询、blockCache 未命中等场景。建议避免高基数标签,控制查询范围。

Q16. Single-Node 模式支持多少 series?

官方建议 < 500 万 series,理论上限取决于可用内存。每百万 series 约需 500MB 内存。

Q17. Cluster 模式的优势是什么?

支持水平扩展、高可用、租户隔离。适合 > 500 万 series 或需要高可用的场景。

Q18. 如何选择 SSD 还是 HDD?

生产环境强烈建议使用 NVMe SSD。HDD 的随机 I/O 性能严重影响查询延迟。

Q19. 网络带宽会影响性能吗?

会,特别是 Cluster 模式下。建议使用 10Gbps 网络,避免网络成为瓶颈。

Q20. 如何进行容量规划?

使用本文的公式计算:内存 = series × 400 bytes,CPU = 吞吐 / 40K,磁盘 = 存储需求 × 2.0。建议预留 50% 余量。

全篇必记总纲

VictoriaMetrics 的性能模型核心是三个经验公式:写入吞吐 ≈ CPU核数 × 40K samples/s、查询延迟 ≈ Part数量 × 1ms、内存占用 ≈ series数量 × 400 bytes。理解这三个公式,才能做好容量规划、性能调优、瓶颈定位。

八、Roadmap:后续预告

本篇覆盖了 VictoriaMetrics 的性能模型,但还有很多细节尚未展开:

  • #10 与其他 TSDB 对比:Prometheus/InfluxDB/Thanos/VM——理解 VM 在竞品中的定位
  • #11 开源生态:VM 在 CNCF 生态中的位置——理解 VM 的生态位
  • #147 写入吞吐极限:100 万 samples/s 写入调优——性能优化专题
  • #148 查询延迟 P99:50ms 内返回的查询优化策略——性能优化专题
  • #107 内存调优:memory.Allowed() 与 cache 大小规划——排障调优专题

本文参考与源码链接:
  • VictoriaMetrics 官方 FAQ
  • VictoriaMetrics Cluster 文档
  • lib/storage/ · 存储核心
  • lib/mergeset/ · MergeSet 存储