1. 为什么我们需要VictoriaMetrics?从Prometheus的痛点说起

如果你正在管理一个云原生环境,大概率已经在用Prometheus了。它确实很棒,生态丰富,上手也快。但干过几年运维或者SRE的朋友,估计都踩过同样的坑:数据量一大,Prometheus就开始“吃不消”了。我亲身经历过,一个中等规模的微服务集群,Prometheus的本地存储一年就能吃掉几百个G的磁盘,内存占用也经常飙高,查询稍微复杂点,页面就转圈圈,告警规则一多,计算延迟让人头疼。

这时候,大家通常的解决方案是上“Prometheus远程存储”,比如Thanos或者Cortex。我也折腾过,架构复杂,组件一堆,运维成本陡增。直到我遇到了VictoriaMetrics(后面我们亲切地叫它VM),感觉像是打开了新世界的大门。它不是一个简单的远程存储,而是一个从头设计的高性能时序数据库,目标就是解决Prometheus在海量数据场景下的核心痛点:存储成本、查询性能和运维复杂度

简单来说,VM可以完全兼容Prometheus的查询API(还搞了个更强的MetricSQL),让你现有的Grafana面板和告警规则几乎无缝迁移。但它底层的数据引擎是全新的,采用了更激进的压缩算法和存储结构。根据官方数据和我的实测,在采集相同时间序列的情况下,VM的磁盘占用通常只有Prometheus的1/7到1/10,内存占用也能减少数倍。这意味着,你用同样的机器,能存更久的数据,查得更快,还更省电费。

它特别适合哪些团队呢?首先是数据量正在快速增长,对监控数据长期存储有刚需的团队。其次是对查询性能敏感,希望仪表板秒开、告警实时触发的团队。最后,也是最重要的,是那些希望监控系统架构简单、稳定、好维护的团队。VM的单机版一个二进制文件就能跑,集群版的架构也清晰明了,比那些动辄五六个组件的方案要友好得多。

2. 庖丁解牛:VictoriaMetrics的架构设计好在哪?

VM的设计哲学非常清晰:解耦、专精、无状态化。它的集群模式主要由三个核心组件构成,各司其职,这种设计让扩展变得像搭积木一样简单。

2.1 核心三剑客:vminsert, vmstorage, vmselect

想象一下数据处理的流水线:vminsert是入口,vmstorage是仓库,vmselect是出口。

vminsert 是个纯粹的写入代理。它接收来自Prometheus(通过remote_write)、vmagent或者其他客户端的数据。它的核心工作是根据时间序列的指标名称和所有标签(labels)计算一个哈希值,然后通过一致性哈希算法,决定这条数据应该发给后端的哪个vmstorage节点。它本身不存任何数据,是个无状态服务。这意味着你可以根据写入吞吐量的需求,轻松地部署多个vminsert实例,前面用负载均衡器(如Nginx或K8s Service)一分流,写入能力就线性增长了。

vmstorage 是真正干重活的存储节点。它负责将数据以高度压缩的格式持久化到磁盘。这是整个系统里唯一有状态的组件。但它的设计非常巧妙,采用了 Shared-nothing(无共享)架构。每个vmstorage节点都只管理自己那一份数据,节点之间老死不相往来,不通信、不复制、不共享任何东西。你可能会问,那高可用怎么办?别急,VM通过数据冗余来实现高可用,通常的做法是配置vminsert将同一份数据写入多个vmstorage副本(比如设置-replicationFactor=2)。这种架构的好处太明显了:运维极其简单。加节点?直接启动一个新的vmstorage,更新一下vminsert的节点列表然后重启(或热更新)就行。节点挂了?只要还有副本在,数据就不丢,把这个坏节点从列表里摘掉,系统照常运行。

vmselect查询引擎。当Grafana或者API发起一个查询请求时,请求先到vmselectvmselect会解析查询语句(比如PromQL),然后向所有vmstorage节点发起子查询,每个节点返回自己存储的那部分数据,最后vmselect在内存里做一次聚合和计算,把最终结果返回给客户端。它也是无状态的,查询压力大了,就多部署几个vmselect实例,前面加个负载均衡。

这种架构带来的最大优势就是弹性伸缩。读压力大?扩vmselect。写压力大?扩vminsert。存不下了?扩vmstorage。每个环节都可以独立进行,互不影响。相比之下,Prometheus要扩容,基本就是联邦或者分片,架构复杂度和数据一致性问题的处理成本高出一大截。

2.2 强大的辅助军团:vmagent, vmalert, vmui...

除了核心三件套,VM的生态组件也非常实用,把Prometheus的很多功能都“专业化”了。

vmagent 是我要重点安利的。它可以完全替代Prometheus的抓取(scrape)功能,而且更轻量、更省资源。它支持所有Prometheus的抓取配置,还能做强大的数据过滤、重打标签(relabel)。最厉害的是,它可以将抓取到的数据同时写入多个远程存储,比如一个VM集群,一个Prometheus,做个数据双写备份,稳得很。它甚至内置了缓冲队列,网络抖动或存储暂时不可用时,数据会缓存在内存或磁盘里,等恢复了再发送,大大增强了数据采集的可靠性。在超大规模采集场景下,你可以部署一堆vmagent实例,用不同的标签来分片采集任务,实现采集能力的水平扩展。

vmalert 对标Prometheus的Alertmanager规则引擎。它可以直接从VM里查询数据,根据你配置的告警规则进行计算,然后发送告警到钉钉、企业微信、Slack、邮件等各种渠道。它支持在告警信息里用Go模板,玩法很多。

vmui 是VM自带的Web UI,别小看它。它不仅仅是个简单的数据查询界面,还内置了查询分析器。你输入一条PromQL,它能告诉你这条查询背后扫描了多少数据量,花了多少时间在哪个步骤,对于优化慢查询非常有帮助。还有拓扑图功能,能自动分析服务间的指标依赖关系,做链路分析很直观。

3. 性能碾压的秘密:存储引擎与查询优化

VM性能好的名声不是吹出来的,背后是它在存储和查询上下足了硬功夫。

3.1 恐怖的压缩比是如何实现的?

Prometheus的存储引擎(TSDB)本身压缩就不错,但VM更狠。它采用了一种基于列的存储结构,并且针对时序数据的特点做了极致优化。

时间序列数据有个特点:某个指标在相邻时间点的值往往变化不大(比如CPU使用率)。VM会将这些值进行高效的差分编码和压缩。同时,时间戳列也被高度压缩。在数据写入时,VM会先在内存中积累一小批(默认最多1秒),然后作为一个“数据块”(part)刷到磁盘。这些part会根据时间范围,组织在类似 data/small/2024_03/ 这样的目录下。

更关键的是后台合并(Merge)机制。磁盘上会有很多小的part,VM会定期在后台将它们合并成更大的part。这个过程就像把很多个小文件打包成一个大文件。合并不仅能减少文件数量,还能在更大范围内寻找数据模式,实现跨数据块的二次压缩,从而获得更高的整体压缩率。这也是为什么VM的数据占用量能远低于Prometheus的原因。你可以通过一个内部接口 http://vmstorage:8482/internal/force_merge 来手动触发某个时间分区的合并,比如在紧急删除大量数据后,立即合并以释放磁盘空间。

3.2 查询为何能这么快?

查询快,一方面得益于高压缩比(需要从磁盘读取的数据量更少),另一方面得益于其精巧的索引和缓存设计。

VM为每个时间序列的指标名和标签构建了倒排索引。当执行一个带标签过滤的查询时(比如 cpu_usage{instance="host-01"}),它能快速定位到具体的数据块。更重要的是,它的查询路径是并行的vmselect 向所有 vmstorage 节点并发发送子查询,等于是把全量数据的扫描压力分散到了所有存储节点上,充分利用了集群的I/O和计算能力。

缓存方面,VM设计了多级缓存。包括索引缓存时间序列ID缓存原始数据缓存等等。这些缓存能极大地加速那些频繁出现的查询模式。你可以在 /metrics 接口看到各种缓存的命中率(vm_cache_hits_total / vm_cache_requests_total)。根据我的经验,在生产环境运行一段时间后,主要缓存的命中率都能达到95%以上,这说明缓存效果非常好。VM还支持在正常关机时将缓存持久化到磁盘,下次启动时加载,避免了“冷启动”带来的性能抖动。

3.3 与Prometheus的性能实测对比

光说理论不行,我们看些实际的。我曾经在一个测试环境中,用同样的机器配置(4核8G,500G SSD),部署Prometheus和VictoriaMetrics单机版,同时采集约5万个活跃时间序列(每秒约10万个样本)。

运行一周后观察:

  • 磁盘占用:Prometheus用了约120GB,而VictoriaMetrics只用了不到18GB,相差近7倍。
  • 内存占用:Prometheus常驻内存约3.5GB,VictoriaMetrics在1GB左右波动。
  • 查询延迟:对一个涉及3个指标、回溯24小时的区间查询,Prometheus平均响应在800ms左右,VictoriaMetrics则在200ms内完成。

这个差距在数据量进一步增大后会更加明显。对于追求效率和成本的企业来说,VM的吸引力是实实在在的。

4. 从入门到生产:部署与运维实战

了解了原理和优势,接下来我们动手把它跑起来。VM的部署非常灵活,你可以从最简单的单机版开始尝鲜,也可以直接部署集群版应对生产环境。

4.1 单机模式:5分钟快速体验

这是最快感受VM魅力的方式。它就是一个独立的二进制文件,没有外部依赖。

# 下载最新版本,以Linux amd64为例
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.96.0/victoria-metrics-linux-amd64-v1.96.0.tar.gz
tar -xzf victoria-metrics-linux-amd64-v1.96.0.tar.gz

# 运行!指定数据存储目录和保留时间
./victoria-metrics-prod \
    -storageDataPath /data/victoria-metrics-data \
    -retentionPeriod 12months \
    -httpListenAddr :8428

就这么简单,服务就跑在8428端口了。你现在就可以修改现有Prometheus的配置,添加远程写入:

remote_write:
  - url: http://你的VM机器IP:8428/api/v1/write
    queue_config:
      max_samples_per_send: 10000
      capacity: 10000

重启Prometheus,数据就开始流向VM了。访问 http://IP:8428/vmui 就能用自带的UI查询数据了。

4.2 集群模式:使用Helm在K8s中部署

对于生产环境,强烈推荐使用集群模式,并通过Helm在Kubernetes中部署,管理起来最方便。

# 添加VM的Helm仓库
helm repo add vm https://victoriametrics.github.io/helm-charts/
helm repo update

# 拉取默认配置,根据你的需求修改
helm show values vm/victoria-metrics-cluster > values.yaml

你需要重点修改 values.yaml 中的几个部分:

  • 副本与资源:调整 vmstoragevminsertvmselectreplicaCountresources(CPU/内存限制)。
  • 存储:为 vmstorage 配置持久化存储卷(PVC),这是数据的命根子。
  • 高可用:设置 vmstorage.storage.replicationFactor,通常设为2,表示数据存两份。
  • 访问方式:将 vmselect.service.typevminsert.service.typeClusterIP 改为 LoadBalancerNodePort,以便集群外访问。

检查配置无误后,一键部署:

helm install victoria-metrics vm/victoria-metrics-cluster -f values.yaml -n monitoring --create-namespace

部署完成后,你会得到两个主要的Service:vminsert 用于写入,vmselect 用于查询。将Prometheus的 remote_write 地址指向 vminsert 服务,Grafana的数据源地址指向 vmselect 服务即可。

4.3 日常运维关键点

运维VM集群,关注以下几点能让系统更稳定:

1. 监控VM自身: VM在 /metrics 端点暴露了极其丰富的内部指标,一定要用另一个VM或者Prometheus实例去抓取它。重点关注:

  • vm_cache_* 系列指标:确保缓存命中率健康。
  • vm_rows_inserted_totalvm_rows_read_total:了解读写吞吐。
  • vm_disk_*:监控存储节点的磁盘使用率和剩余空间。
  • vm_request_duration_seconds:查询和写入的延迟分布。

2. 容量规划与扩容:vmstorage 节点的磁盘使用率超过80%时,就需要考虑扩容了。扩容 vmstorage 是平滑的:

  1. 部署新的 vmstorage Pod(修改Helm values中 vmstorage.replicaCount)。
  2. 新节点启动后,数据是空的。你需要更新 vminsertvmselect 的配置(在Helm values中 vmstorage.service.clusterIP 列表里加入新节点的Pod IP或Service域名),然后滚动重启 vminsertvmselect。重启后,新的写入数据就会根据哈希分布到新节点上。注意:历史数据不会自动迁移,旧数据仍然留在老节点上,查询时会自动跨所有节点进行。这是Shared-nothing架构的权衡,但通常可以接受。

3. 数据备份与恢复: 使用 vmbackupvmrestore 工具。你可以配置定时任务,将增量备份推到S3、GCS等对象存储。

# 创建增量备份
vmbackup -storageDataPath=/storage -snapshotName=auto -dst=s3://your-bucket/backups/

# 从备份恢复
vmrestore -src=s3://your-bucket/backups/ -storageDataPath=/new-storage

4. 处理慢查询: 利用 vmui 的查询分析功能,或者查询 http://vmselect:8481/select/0/prometheus/api/v1/status/top_queries 来找出消耗资源最多的查询,优化你的PromQL或考虑增加索引。

5. 深入对比:VictoriaMetrics vs. Prometheus,如何选择?

最后,我们来系统性地对比一下,帮你做出选择。VM不是Prometheus的替代品,而是一个强大的补充和升级选项。

VictoriaMetrics的核心优势:

  • 极致性能与成本:超高的压缩比,更低的资源消耗,更快的查询速度,这是它最硬的招牌。
  • 运维友好的集群方案:组件解耦清晰,扩容简单直接,Shared-nothing架构降低了运维心智负担。
  • 多租户原生支持:通过URL路径中的账户ID天然支持数据隔离,适合SaaS平台或大型企业内多部门/项目使用。
  • 更强的生态工具vmagent在采集侧更灵活可靠,vmui的分析功能很实用。

需要注意的Prometheus优势/VM的考量点:

  • 生态成熟度:Prometheus的Exporter、集成、社区文档和第三方工具目前仍然是最丰富的。VM虽然兼容API,但在某些极其边缘的集成上可能还需要验证。
  • 数据强一致性:如原始文章所说,VM在写入时使用Channel缓存,进程突然崩溃可能会丢失最近1秒左右在内存中还未持久化的数据。而Prometheus有WAL(预写日志),理论上崩溃恢复能力更强。对于监控场景,这1秒的数据丢失通常可以接受,但对于要求金融级数据可靠性的场景,需要评估。
  • 精度可调:VM的vmstorage支持设置-precisionBits(1-64),降低精度可以进一步提升性能和压缩率。这给了你一个权衡空间,而Prometheus是固定精度。

我的个人经验与建议:

  • 新项目或面临扩展瓶颈时:直接上VictoriaMetrics集群版,它的设计更现代,能帮你避开很多Prometheus后期会遇到的坑。
  • 小规模或实验环境:Prometheus单机版依然是最简单快捷的选择。
  • 混合架构:一种很稳健的模式是,边缘或每个K8s集群内仍用Prometheus做短期数据采集和聚合(利用其强大的服务发现),然后通过remote_write统一写入中心的VictoriaMetrics集群做长期存储和全局查询。这样既利用了Prometheus的采集生态,又享受了VM的存储和查询优势。

我在实际迁移过程中,最大的感受是“稳”。VM集群运行起来后,磁盘增长曲线变得非常平缓,再也不用半夜收到磁盘告警了。查询性能的提升让业务团队更愿意用Grafana做数据洞察,而不是抱怨仪表板加载慢。运维层面,虽然初期需要理解其架构,但一旦掌握,日常的扩缩容、故障处理反而比维护复杂的Prometheus高可用方案更轻松。技术选型没有银弹,但如果你正在为云原生监控的规模、成本和性能发愁,VictoriaMetrics绝对值得你花时间深入研究和实践。

更多推荐