文章总结: 本文对比分析了VictoriaMetrics与Thanos两种监控方案,在采集层均使用原生Prometheus的前提下,从架构设计、规则计算告警、运维复杂度和资源效率等维度进行深入比较。VictoriaMetrics采用Shared-nothing架构,查询延迟毫秒级,存储成本比Thanos节省3-7倍,运维更简单。文章还详细阐述了VictoriaMetrics的节点故障预防、数据迁移和秒级扩缩容实践方案。对于中小规模集群,VictoriaMetrics是更优选择。 综合评分: 88 文章分类: 解决方案,安全建设,产品介绍
VictoriaMetrics VS Thanos
原创
EBCloud EBCloud
EBCloud
2026年3月11日 16:00 北京
前言
本方案采集层都使用原生Prometheus且共用同一份Prometheus配置文件的前提下进行对比。
整体架构图如下:
一、基本介绍
01
VictoriaMetrics
VictoriaMetrics是一个高性能、可扩展的开源时序数据库和监控系统,专为大规模监控场景设计。其核心定位是Prometheus的高性能替代方案,完全兼容Prometheus生态(支持PromQL、Remote Write、Grafana等),但在性能、资源效率和扩展性方面实现了质的飞跃。其核心组件有vminsert、vmstorage、vmselect、vmalert。
vminsert:通过remote write API接收来自Prometheus的数据,数据由vminsert组件通过Jump Consistent Hash算法,基于指标名称和标签哈希值自动均衡分发到不同vmstorage节点。当节点增减或故障时,新数据自动重路由到健康节点。
Jump Consistent Hash(跳跃一致性哈希)是Google2014年提出的极简算法,用于把key均匀映射到编号0‥N-1的桶。它只有5行代码,却同时满足“一致性”与“零内存”两个极端诉求。
当桶数从n变为n+1时,只有1/(n+1)的key需要换桶,其余key原地不动;这一比例恰好等于“随机把key扔进新桶”的概率,因此期望负载始终严格均匀
桶数 1→2:50% key从0跳到1
桶数 2→3:1/3 key从{0,1}跳到2
桶数 3→4:1/4 key从{0,1,2}跳到3
…
intch(long key, int N){ long b = -1, j = 0; // b: 上次跳跃落点 while (j < N) { // j: 当前桶号 b = j; // 先假定不跳 key = key * 2862933555777941757L + 1; // LCG 生成下一个随机数。常数 2862933555777941757L 保证随机序列均匀 j = (long)((b + 1) * (double)(1L << 31) / (double)((key >>> 33) + 1)); } // 计算下一次跳跃位置 return (int)b;}
vmstorage:基于ClickHouse思想的高压缩比的有状态存储节点,支持水平扩展,通过增加节点数量线性提升集群容量和活跃时间序列处理能力。每个vmstorage实例完全独立,节点间不通信、不共享数据,彼此无感知。单个节点故障不影响其他节点,集群可用性由vminsert和vmselect的协调机制保障。不支持数据再均衡,即增加或删除节点时,历史数据不会自动迁移。
Vmselect:查询处理,聚合多节点结果。
vmalert:规则计算与告警,完全兼容Prometheus规则语法(YAML),100%兼容PromQL,且MetricsQL增强,如支持with语法。
vmauth/vmgateway:认证代理。
02
Thanos
Thanos是Prometheus的“增强套件”,而非独立数据库。它在保留Prometheus原有生态的基础上解决了三大核心痛点:由单点故障转成高可用架构,由本地存储限制转为无限期长期存储(对象存储),且将多集群查询场景转为全局视图聚合。Thanos采用模块化设计由多个独立组件构成,包括Sidecar、Query、Store Gateway、Compactor、Ruler、Receiver。
Sidecar:每个prometheus配套部署,实时查询代理,上传数据到对象存储。
Query:实现了Prometheus的查询API,将receive和对象存储提供的数据进行聚合最终返回给查询数据的客户端。Query组件的性能会受到性能最差的reveive或Store Gateway的影响。
Store Gateway:将对象存储的数据提供给Thanos Query查询。
Compactor:默认情况下,receive以2小时为单位将监控数据上传到对象存储中。Compactor会逐渐将这些数据块合并成更大的数据块,以提高查询效率,减少所需的存储大小。
Ruler:跨集群规则评估与告警。
Query-auth:认证代理。
Receiver:接收remote_write数据。
二、方案比较
01
规则计算和告警比对
| | | | | — | — | — | | 对比维度 | VM | Thanos | | 规则执行器 | Vmalert(远程查询vmselect) | Ruler(远程查询StoreAPI) | | 规则落盘 | vmalert → `- remoteWrite.url → vminsert | Ruler → 本地TSDB → Receive → 对象存储 | | 告警通知 | Alertmanager | Alertmanager | | 记录规则可见性 | 实时写入VM,立即查询 | 需等待2h块上传后才全局可见 | | 语法格式 | 两者完全兼容Prometheus规则语法(YAML) | 两者完全兼容Prometheus规则语法(YAML) | | 告警延迟 | 直连vmselect,延迟<0.5s | 通过Query,延迟5-10s |
Vmalert和Thanos其他差异点
◆
vmalert支持Prometheus不兼容的MetricsQL增强语法,以下查询在Thanos Ruler中无法执行。
# 不兼容:WITH 表达式(仅 VM 支持)- record: complex_calc expr: | WITH ( cpu = avg(rate(node_cpu_seconds_total[5m])), mem = avg(node_memory_MemTotal_bytes) ) cpu > 0.8 AND mem > 1073741824
# 不兼容:keep_metric_names 修饰符- record: metric_name_preserved expr: rate(http_requests_total[5m]) keep_metric_names
# 不兼容:Graphite 过滤器- alert: GraphiteMetric expr: {__graphite__="servers.*.cpu"} > 80 type: graphite # VM 特有的规则类型
◆
vmalert支持Prometheus/Thanos均无的查询控制参数。
groups:- name: vm-advanced # 不兼容:HTTP 查询参数(如禁用缓存、强制租户标签) params: nocache: ["1"] extra_label: ["team=platform"] # 不兼容:HTTP 自定义头(用于认证) headers: - "X-VM-Extra-Label: env=prod" # 不兼容:多租户(企业版) tenant: "123:456" rules: - alert: HighCPUexpr: cpu_usage > 80
◆
vmalert提供30+模板函数,远超Prometheus标准。
# 不兼容:VM 特有的模板函数annotations: # VM 支持查询结果注入 current_value: "{{ query \"sum(rate(errors[5m]))\" | first | value }}" # VM 支持时间计算 debug_time: "{{ ($activeAt.Add (parseDurationTime \"-1h\")).UnixMilli }}" # Prometheus/Thanos 仅支持基础变量($labels, $value
◆
Thanos Ruler支持跨集群查询容错,这是vmalert完全不具备的。
groups:- name: cross-cluster # 不兼容:vmalert 无此字段 partial_response_strategy: "warn" # 或 "abort" rules: - alert: GlobalErrorRate expr: sum(rate(http_errors[5m])) by (cluster) > 100
◆
Thanos Ruler允许全局或组级查询时间偏移,以应对数据延迟。
groups:- name: delayed-data # 不兼容:vmalert 不支持组级偏移 query_offset: 30s # Thanos 特有,对应 --rule-query-offset 标志 rules: - alert: SlowMetric expr: increase(slow_counter[5m]) > 0
◆
Thanos Ruler对外部标签的强制覆盖行为与vmalert不同。
# Thanos Ruler 行为:--label 强制覆盖,可能导致源数据标签丢失# vmalert 行为:-external.label 冲突时保留原标签并加 exported_ 前缀--label='cluster="monitoring"' # 强制所有规则结果为此标签
◆
计算链条不同
# 同一条规则,行为截然不同- alert: DiskFull expr: (disk_free / disk_total) < 0.1 # vmalert: 直连 vmselect,毫秒级返回,无网络依赖 # Thanos Ruler: 通过 Thanos Query → Store Gateway → S3,延迟 5-10 秒,任一环节失败则规则评估中断
02
运维级对比
| | | | | — | — | — | | 指标 | VM | Thanos | | 组件数 | 4个 vminsert / vmstorage / vmselect / vmalert | 4个 Receive / Query / StoreGW / Ruler | | 有状态组件 | 仅vmstorage | Prometheus、Receive、对象存储 | | 网络协议 | remote_write(HTTP/Protobuf) | StoreAPI(gRPC) | | 历史数据查询 | 本地磁盘→毫秒级 | 对象存储→百毫秒-秒级 | | 存储成本 | 本地盘,压缩率4-7倍,比Thanos省3-7倍 | S3+本地盘,长期保有成本低但流量高 | | 故障域 | vmstorage节点故障只丢该分片(可副本) | Receive宕机丢WAL最后时间到启动时间的数据,但重启后WAL重放、时间序列索引重建引起内存暴涨 | | 升级/回滚 | vmstorage滚动重启,秒级WAL恢复 | StoreGateway重建索引需10-30 min | | 多云/跨区带宽 | 仅复制压缩后的remote_write流量 | StoreGateway需全量拉取对象存储索引 |
03
资源效率对比
以scrape_samples_scraped 300万样本/秒架构配置估算Prometheus层(30-40实例):各4核8GB,共120-160核/240-320GB,本地保留2小时(~50GB SSD)。
(1)Thanos方案 Thanos Receive层(3-4副本):
- 各8-12核32-48GB,共24-48核/96-192GB
- 接收所有Remote Write流量
- 本地保留2小时,上传至S3
- 复制因子RF=1(生产建议RF=2,资源翻倍)
Store Gateway(4-6实例):
- 各4核8GB,共16-24核/32-48GB
- 缓存对象存储索引
Query(3-4实例):
- 各4核8GB,共12-16核/24-32GB
Ruler(2-3实例):
- 各4核8GB,共8-12核/16-24GB
总资源:
- CPU:180-260核
- 内存:400-620GB
- 本地磁盘:10TB SSD(临时)
- 对象存储:30天累积50-100TB
(2)VM方案
vminsert层(3-4实例):
- 各4核8GB,共12-16核/24-32GB
- 无状态,仅做负载均衡和路由
vmstorage层(6-8实例):
- 各16核32GB,共96-128核/192-256GB
- 30天全量数据(2-3TB/节点)
- 复制因子RF=2(跨节点)
vmselect层(2-3实例):
- 各8核16GB,共16-24核/32-48GB
vmalert(2-3实例):
- 各2核4GB,共4-6核/8-12GB
总资源:
- CPU:130-180核
- 内存:260-350GB
- 本地磁盘:20-30TB SSD(30天)
- 无对象存储费用
以上环境查询延迟对比结果:
| | | | | — | — | — | | 对比维度 | VM | Thanos | | 15天查询延迟 | 10-100ms(本地SSD) | 1-10s(对象存储限制) | | P99延迟 | <1s | 5-30s | | 首次查询惩罚 | 严重(冷数据从S3拉取) | 无(全热数据) | | 简单查询(单指标) | 5-20ms | 500ms-2s | | 聚合查询(sum/rate) | 20-100ms | 2-10s | | 并发查询(10+) | 线性扩展 | 性能急剧下降 |
04
对比总结
| | | | | — | — | — | | 对比维度 | VM | Thanos | | 架构简洁性 | 4-5个组件,单一技术栈,VM无共享架构规避了复杂的分布式一致性协议 | 6-7个组件,分布式联邦 | | 写入性能 | 实时写入,低延迟 | 实时写入,低延迟,2小时落盘 | | 查询性能 | 本地磁盘,毫秒级 | 对象存储,秒级 | | 资源效率 | 存储节省3-7倍,内存低5-7倍 | 依赖对象存储,成本较高 | | 运维复杂度 | 一键部署,故障排查简单 | 网络配置复杂,调优困难 | | 跨集群联邦 | 需数据汇聚,适合<100集群 | 原生Store API联邦,适合>50集群 | | 生态兼容性 | 100% Prometheus API,MetricsQL增强,如with语法 | 完全原生,无扩展语法 |
三、VM应用挑战
01
预防节点故障导致数据丢失
针对vmstorage单节点故障导致的数据丢失问题,需采用多层次防御体系。VictoriaMetrics的Shared-nothing架构决定了其不会自动迁移历史数据,因此必须主动设计冗余策略:
◆
第1层:应用层冗余(Replication Factor)
通过vminsert的复制因子实现应用级数据冗余。
机制:可通过-replicationFactor=N在vminsert实现数据副本,需至少2*N-1个节点,成本较高。
效果:允许N-1个节点同时故障,数据仍完整可用。
注意:
- 该机制仅保护开启后写入的新数据,对历史数据无效;副本解决的是“节点突然掉线,但稍后能恢复”这种临时故障——查询会降级到剩余副本,不会丢点。
- 副本不解决“节点被踢出集群”后的永久空洞——历史数据仍只在原节点,vmselect找不到它,就会告诉你结果不完整。
- 若中途开启或调整RF值,可能导致历史数据查询异常(vmselect会误判副本分布)。
- 无法防止OOM级联故障(所有节点同时过载)。
◆
第2层:基础设施层冗余
由于应用层复制成本高(存储翻倍),更推荐依赖底层存储的可靠性。
云盘快照(启用自动快照策略,RPO可达分钟级)、本地RAID(使用RAID 10或RAID 5,单盘故障不影响数据)、分布式存储(使用带冗余的分布式存储如Ceph、Longhorn作为PVC)。
◆
第3层:备份与恢复(对抗逻辑错误和大规模故障)
推荐策略:每6-24小时备份一次,保留7天。
vmselect向所有vmstorage节点并行发起查询,合并各节点返回的数据后响应客户端,通过-dedup.minScrapeInterval参数实现跨节点去重。
02
节点故障处置方案
方案A:自然过期(零拷贝,等待型)
把待下线节点A从所有vminsert的-storageNode列表里摘掉并滚动重启,新数据不再写A,但A的数据仍在本地盘。必须等“完整保留期”才能彻底下线;期间A的盘仍占机位。
等待-retentionPeriod足够长(例如30 d),确保A盘上的块文件全部“过期”被后台删除。
确认Grafana无断图后,再把A从所有vmselect的-storageNode列表里摘掉并下线机器。
方案B:主动迁移(vmctl导出/导入,快速型)
如果等不了保留期,可把A的数据重新灌回集群,让它按新哈希规则分散到剩余节点。同样先把A从vminsert列表摘掉,阻止新数据再写A。起一台临时vmselect,只把A的地址写进它的-storageNode,专门做“读源”。
用官方工具vmctl做native export/import:
bash# 从“只连 A”的 vmselect 导出vmctl native export --vm-native-src=http://temp-select:8481 \ --filter-time-start=30d \ --vm-native-dst=http://normal-insert:8480
导出过程就是把A的历史时间序列重新写回剩余的vminsert,vminsert会按当前最新Jump Has把它们散列到现存节点。并在vmselect侧打开-dedup.minScrapeInterval=1ms(或与你采集间隔相同),防止新旧副本重复。
无论选哪条,一定先摘vminsert,再摘vmselect,顺序反了会导致查询空洞。
另外,故障节点从vminsert列表摘掉,可以通过以下方式实现热加载:
(1)静态列表(命令行-storageNode=host1:8401,host2:8401 …) 必须重新启动vminser才能让新的-storageNode生效;因为VictoriaMetrics只在启动时解析一次该参数,运行期间不会轮询文件或信号量去重载。
(2)文件式动态发现(-storageNodeFile=/path/nodes.txt)
无需重启。把要摘掉的节点从文件里删除,保存后vminsert会在1-2s内自动重读该文件并立即把流量切走;这是官方推荐的“零中断”做法。
(3)Consul/DNS-SRV等“带缓存的服务发现”(推荐) 无需重启。vminsert会按-discoveryInterval(默认30s)重新解析,解析结果里不再出现的节点会被实时剔除。
03
实现“秒级”扩缩容
vminsert/vmselect两个组件的扩缩容就是“无状态服务”的标准玩法,即加机器→LB引流→完事;减机器→摘流量→停进程→完事。本段主要介绍而针对于vmstorage的扩缩容场景。
◆
服务注册与发现
所有VictoriaMetrics进程都以Consul-Client方式同节点部署,本地consul agent -client与Server集群Gossip互通。
(1)Consul侧:注册与健康检查
Service定义(以vmstorage为例)
service { name = "vmstorage" id = "vmstorage-${NODE}" # 本机唯一 port = 8400 tags = ["vmstorage", "dc1"]
check { tcp = "127.0.0.1:8400" interval = "5s" timeout = "2s" }}
同理再建vminsert/vmselect的service文件。consul reload后,UI能看到passing/failing状态。
健康检查要点:
- 用TCP或HTTP/health均可,TCP最轻量。
- 检查失败5次(约25s)后,Consul会把实例标为critical并自动从DNS/SRV里摘掉
- vmstorage若磁盘只读、IO Hang,TCP仍然能通,建议再加一条exec脚本检查磁盘可写。
(2)VictoriaMetrics侧:发现语法
vminsert/vmselect均支持Consul SRV语法,无需自己写脚本轮询:
# vminsert-storageNode=consul://127.0.0.1:8500/vmstorage?tag=vmstorage&dc=dc1# vmselect-storageNode=consul://127.0.0.1:8500/vmstorage?tag=vmstorage&dc=dc1
◆
场景及操作
(1)扩容
- 新节点启动vmstorage+consul-client。
- 注册service,5-30s后vminsert发现新地址,新数据立即按Jump Hash写入。旧数据不会重平衡,仍需3.2章节方案A/B处理。
(2)缩容
- consul services deregister vmstorage-xxx或停进程。
- 等critical状态。vminsert下一周期剔除该节点,新数据不再写入。历史数据仍在原机,需等过期或vmctl导出。
(3)故障
节点宕机→check失败→critical。vminsert下一周期剔除该节点,新数据不再写入。历史数据仍在原机,若设置了-replicationFactor=2,查询仍能从副本拿数据。
(4)注意点
DNS缓存:若用consul.service.consul域名而非SRV,需本地把TTL配置调到5s以下。
启动顺序:vminsert解析不到任何地址会直接退出;确保Consul先于VM启动。
Tag写错:如把vminsert自己也选进-storageNode会导致无限递归写自己,CPU瞬间飙满。
最后,Consul只负责“地址列表”,不负责“数据搬迁”。
欢迎关注EBCloud
文章作者丨徐信
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:EBCloud EBCloud EBCloud《VictoriaMetrics VS Thanos》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论