VictoriaMetrics高性能时序数据库:Prometheus远程存储方案
Prometheus单机存储在生产环境跑到一定规模就会碰壁——单节点磁盘容量有限,TSDB默认保留15天数据,想存半年以上的监控数据基本不现实。更麻烦的是Prometheus没有原生的高可用方案,两个Prometheus实例各采各的,数据不一致,查询时还得靠Thanos或者联邦来聚合。我们团队在2022年从Thanos迁移到VictoriaMetrics,集群稳定运行至今,存储成本降了约60%,查询延迟从秒级降到毫秒级。这篇文章把部署、对接、调优的完整流程写出来。
一、概述
1.1 背景介绍
Prometheus的本地TSDB设计目标是短期存储,官方建议保留时间不超过15-30天。一旦监控规模上去(比如我们的场景:200+节点、5万+活跃时间序列、每秒采集样本数约50万),单机Prometheus的内存和磁盘压力就很大。常见的解决思路有三种:
Thanos:Sidecar模式对接Prometheus,数据上传到对象存储。架构复杂,组件多(Sidecar、Store Gateway、Compactor、Query),运维成本高。
Cortex/Mimir:Grafana Labs的方案,依赖Consul/etcd做服务发现,还需要对象存储,部署门槛不低。
VictoriaMetrics:单二进制部署,兼容PromQL,压缩率比Prometheus高7-10倍,查询速度快,资源消耗低。
我们实测对比过:同样存储3个月的监控数据,Prometheus+Thanos占用约800GB磁盘,VictoriaMetrics只用了120GB左右。查询30天范围的聚合数据,Thanos需要3-5秒,VictoriaMetrics在200ms内返回。
1.2 技术特点
极高的压缩率:VictoriaMetrics使用自研的压缩算法,实测压缩比在10:1到15:1之间,比Prometheus的gorilla编码高出数倍。100万个时间序列、每15秒采集一次、存储1个月,磁盘占用约20-30GB。
完全兼容PromQL:支持MetricsQL(PromQL的超集),现有的Grafana Dashboard和告警规则可以直接迁移,不用改查询语句。额外支持了一些实用函数如range_median()、histogram_quantile()的优化版本。
部署运维简单:单机版就是一个二进制文件,启动参数配好就能跑。集群版也只有三个组件(vminsert、vmselect、vmstorage),没有外部依赖,不需要Consul、etcd、Kafka这些中间件。
1.3 适用场景
Prometheus长期存储:需要保留3个月以上监控数据的场景,直接用remote_write对接VictoriaMetrics,Prometheus只保留短期数据做热查询。
大规模监控集群:单集群超过500个节点、活跃时间序列超过1000万的场景,VictoriaMetrics集群版可以水平扩展,实测单集群支撑过5000万活跃序列。
多租户监控平台:集群版原生支持多租户,通过URL路径区分租户,不同业务线的数据隔离存储和查询,适合平台化的监控中台。
1.4 环境要求
| 组件 | 版本要求 | 说明 |
|---|---|---|
| 操作系统 | CentOS 7+ / Ubuntu 18.04+ / Debian 10+ | 推荐Ubuntu 22.04 LTS |
| VictoriaMetrics | v1.93.0+ | 本文基于v1.102.0,建议用最新稳定版 |
| Prometheus | v2.40+ | 需要支持remote_write协议 |
| Grafana | v9.0+ | 用于可视化查询,需要Prometheus数据源 |
| CPU | 单机版4核+,集群版每节点8核+ | vmstorage对CPU要求不高,vmselect查询时CPU消耗大 |
| 内存 | 单机版8GB+,集群版每节点16GB+ | 内存主要用于缓存和合并写入 |
| 磁盘 | SSD推荐,容量按压缩后估算 | HDD也能跑,但查询延迟会高2-3倍 |
二、详细步骤
2.1 准备工作
2.1.1 系统检查
# 检查系统版本 cat /etc/os-release # 检查CPU和内存 nproc free -h # 检查磁盘空间,数据盘建议预留200GB以上 df -h # 检查系统时间同步状态,时序数据库对时间敏感 timedatectl status # 如果时间不同步,配置chrony sudo apt install -y chrony sudo systemctl enable --now chrony chronyc tracking
2.1.2 创建用户和目录
# 创建专用用户,不给登录shell sudo useradd -r -s /sbin/nologin victoriametrics # 创建数据目录,生产环境建议挂载独立磁盘 sudo mkdir -p /data/victoriametrics sudo mkdir -p /etc/victoriametrics sudo mkdir -p /var/log/victoriametrics # 设置目录权限 sudo chown -R victoriametrics:victoriametrics /data/victoriametrics sudo chown -R victoriametrics:victoriametrics /var/log/victoriametrics
2.1.3 下载安装
# 设置版本号
VM_VERSION="v1.102.0"
# 下载单机版
cd /tmp
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/${VM_VERSION}/victoria-metrics-linux-amd64-${VM_VERSION}.tar.gz
# 解压安装
tar xzf victoria-metrics-linux-amd64-${VM_VERSION}.tar.gz
sudo mv victoria-metrics-prod /usr/local/bin/victoria-metrics
sudo chmod +x /usr/local/bin/victoria-metrics
# 验证安装
victoria-metrics --version
如果要部署集群版,需要额外下载集群组件:
# 下载集群版组件
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/${VM_VERSION}/victoria-metrics-linux-amd64-${VM_VERSION}-cluster.tar.gz
tar xzf victoria-metrics-linux-amd64-${VM_VERSION}-cluster.tar.gz
sudo mv vminsert-prod /usr/local/bin/vminsert
sudo mv vmselect-prod /usr/local/bin/vmselect
sudo mv vmstorage-prod /usr/local/bin/vmstorage
sudo chmod +x /usr/local/bin/vm{insert,select,storage}
# 下载vmagent(可选,替代Prometheus做采集)
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/${VM_VERSION}/vmutils-linux-amd64-${VM_VERSION}.tar.gz
tar xzf vmutils-linux-amd64-${VM_VERSION}.tar.gz
sudo mv vmagent-prod /usr/local/bin/vmagent
sudo mv vmctl-prod /usr/local/bin/vmctl
sudo chmod +x /usr/local/bin/vmagent /usr/local/bin/vmctl
2.2 核心配置
2.2.1 单机版部署
单机版适合中小规模场景(活跃时间序列500万以内),一个进程搞定读写存储。
# 创建systemd服务文件 sudo tee /etc/systemd/system/victoriametrics.service > /dev/null << 'EOF' [Unit] Description=VictoriaMetrics single-node After=network.target [Service] Type=simple User=victoriametrics Group=victoriametrics ExecStart=/usr/local/bin/victoria-metrics -storageDataPath=/data/victoriametrics -retentionPeriod=6 -httpListenAddr=:8428 -maxLabelsPerTimeseries=40 -search.maxUniqueTimeseries=5000000 -search.maxQueryDuration=60s -search.maxConcurrentRequests=32 -memory.allowedPercent=60 -dedup.minScrapeInterval=15s -loggerTimezone=Asia/Shanghai -loggerOutput=stderr ExecStop=/bin/kill -s SIGTERM $MAINPID Restart=always RestartSec=5 LimitNOFILE=65536 LimitNPROC=32000 [Install] WantedBy=multi-user.target EOF
参数说明(这些都是踩过坑调出来的):
-retentionPeriod=6:数据保留6个月,单位是月。改成6而不是180d,因为按月计算更直观。
-memory.allowedPercent=60:限制VictoriaMetrics使用系统60%的内存。默认不限制,在16GB内存的机器上跑,不设这个参数会把内存吃满导致OOM Killer干掉进程。生产环境必须设。
-dedup.minScrapeInterval=15s:去重间隔设为采集间隔。如果你跑了两个Prometheus做HA,两边都remote_write到VM,这个参数会自动去重,只保留一份数据。
-search.maxUniqueTimeseries=5000000:单次查询最大返回的时间序列数。默认30万,在大集群里查{__name__=~".+"}这种宽泛查询会报错,按需调大。
-maxLabelsPerTimeseries=40:每个时间序列最大标签数。默认30,有些业务自定义标签多的会超限,40基本够用。
2.2.2 集群版部署
集群版由三个组件组成,生产环境建议每个组件至少2个实例:
vmstorage:存储节点,负责数据持久化。部署在有SSD的机器上。
vminsert:写入网关,接收remote_write请求,按一致性哈希分发到vmstorage。无状态,可以随意扩缩。
vmselect:查询网关,接收PromQL查询,从所有vmstorage拉数据聚合。无状态。
假设我们有3台机器:
| 角色 | IP | 端口 |
|---|---|---|
| vmstorage-1 | 10.0.1.11 | 8482(http) / 8400(vminsert) / 8401(vmselect) |
| vmstorage-2 | 10.0.1.12 | 8482(http) / 8400(vminsert) / 8401(vmselect) |
| vmstorage-3 | 10.0.1.13 | 8482(http) / 8400(vminsert) / 8401(vmselect) |
| vminsert | 10.0.1.21 | 8480 |
| vmselect | 10.0.1.22 | 8481 |
vmstorage服务配置(三台存储节点都部署):
sudo tee /etc/systemd/system/vmstorage.service > /dev/null << 'EOF' [Unit] Description=VictoriaMetrics vmstorage After=network.target [Service] Type=simple User=victoriametrics Group=victoriametrics ExecStart=/usr/local/bin/vmstorage -storageDataPath=/data/vmstorage -retentionPeriod=6 -httpListenAddr=:8482 -vminsertAddr=:8400 -vmselectAddr=:8401 -dedup.minScrapeInterval=15s -memory.allowedPercent=60 -search.maxUniqueTimeseries=5000000 -loggerTimezone=Asia/Shanghai Restart=always RestartSec=5 LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF
vminsert服务配置:
sudo tee /etc/systemd/system/vminsert.service > /dev/null << 'EOF' [Unit] Description=VictoriaMetrics vminsert After=network.target [Service] Type=simple User=victoriametrics Group=victoriametrics ExecStart=/usr/local/bin/vminsert -httpListenAddr=:8480 -storageNode=10.0.1.11:8400,10.0.1.12:8400,10.0.1.13:8400 -replicationFactor=2 -maxLabelsPerTimeseries=40 -maxConcurrentInserts=32 -loggerTimezone=Asia/Shanghai Restart=always RestartSec=5 LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF
-replicationFactor=2表示每条数据写入2个存储节点。这样挂掉1个vmstorage不丢数据。代价是存储空间翻倍,但数据安全比省磁盘重要。
vmselect服务配置:
sudo tee /etc/systemd/system/vmselect.service > /dev/null << 'EOF' [Unit] Description=VictoriaMetrics vmselect After=network.target [Service] Type=simple User=victoriametrics Group=victoriametrics ExecStart=/usr/local/bin/vmselect -httpListenAddr=:8481 -storageNode=10.0.1.11:8401,10.0.1.12:8401,10.0.1.13:8401 -dedup.minScrapeInterval=15s -search.maxQueryDuration=120s -search.maxConcurrentRequests=32 -search.maxUniqueTimeseries=5000000 -replicationFactor=2 -loggerTimezone=Asia/Shanghai Restart=always RestartSec=5 LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF
vmselect的-replicationFactor=2要和vminsert一致,这样查询时vmselect知道数据有副本,会自动去重。
2.2.3 Prometheus remote_write对接
在Prometheus配置文件中添加remote_write段:
# /etc/prometheus/prometheus.yml global: scrape_interval:15s evaluation_interval:15s remote_write: -url:"http://10.0.1.21:8480/insert/0/prometheus/api/v1/write" queue_config: max_samples_per_send:10000 capacity:20000 max_shards:30 min_shards:1 batch_send_deadline:5s write_relabel_configs: -source_labels:[__name__] regex:"go_.*" action:drop # 如果是单机版VM,URL改为: # url: "http://VM_IP:8428/api/v1/write"
URL路径中的/insert/0/prometheus/里的0是租户ID。单租户场景用0就行,多租户按业务分配不同的数字。
queue_config的参数是调过的:
max_samples_per_send=10000:每批发送1万个样本,默认500太小,网络开销大。
max_shards=30:最大并发发送协程数。如果Prometheus采集量大(每秒超过10万样本),这个值要调到50以上。
batch_send_deadline=5s:批次发送超时。默认5s够用,网络差的环境调到10s。
write_relabel_configs用来过滤不需要远程存储的指标。go_*这类Go运行时指标一般不需要长期存储,直接drop掉能减少约10-15%的写入量。
2.2.4 vmagent替代Prometheus采集
如果你不需要Prometheus的告警功能(告警交给VMAlert或者独立的Alertmanager),可以用vmagent替代Prometheus做采集。vmagent内存占用只有Prometheus的1/3左右,支持同样的服务发现和relabel配置。
# vmagent配置文件
sudo tee /etc/victoriametrics/vmagent.yml > /dev/null << 'EOF'
global:
scrape_interval: 15s
external_labels:
cluster: prod-bj
env: production
scrape_configs:
- job_name: "node-exporter"
static_configs:
- targets:
- "10.0.1.11:9100"
- "10.0.1.12:9100"
- "10.0.1.13:9100"
relabel_configs:
- source_labels: [__address__]
regex: "(.+):.*"
target_label: instance
replacement: "${1}"
- job_name: "kubernetes-pods"
kubernetes_sd_configs:
- role: pod
api_server: "https://10.0.1.100:6443"
tls_config:
ca_file: /etc/victoriametrics/ca.crt
cert_file: /etc/victoriametrics/client.crt
key_file: /etc/victoriametrics/client.key
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
regex: ([^:]+)(?::d+)?;(d+)
replacement: $1:$2
target_label: __address__
EOF
# vmagent systemd服务 sudo tee /etc/systemd/system/vmagent.service > /dev/null << 'EOF' [Unit] Description=VictoriaMetrics vmagent After=network.target [Service] Type=simple User=victoriametrics Group=victoriametrics ExecStart=/usr/local/bin/vmagent -promscrape.config=/etc/victoriametrics/vmagent.yml -remoteWrite.url=http://10.0.1.21:8480/insert/0/prometheus/api/v1/write -remoteWrite.maxDiskUsagePerURL=1GB -remoteWrite.tmpDataPath=/data/vmagent-remotewrite-data -httpListenAddr=:8429 -loggerTimezone=Asia/Shanghai Restart=always RestartSec=5 LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF
-remoteWrite.maxDiskUsagePerURL=1GB这个参数很关键:当远端VM不可用时,vmagent会把数据缓存到本地磁盘,等VM恢复后自动重传。默认不限制,磁盘可能被写满。设成1GB,按每秒10万样本算,大约能缓存2-3小时的数据,足够覆盖大多数故障恢复时间。
2.3 启动和验证
2.3.1 启动服务
# 单机版启动 sudo systemctl daemon-reload sudo systemctl enable --now victoriametrics sudo systemctl status victoriametrics # 集群版启动(按顺序:先storage,再insert和select) # 在三台存储节点上执行 sudo systemctl daemon-reload sudo systemctl enable --now vmstorage sudo systemctl status vmstorage # 在vminsert节点执行 sudo systemctl enable --now vminsert sudo systemctl status vminsert # 在vmselect节点执行 sudo systemctl enable --now vmselect sudo systemctl status vmselect # 启动vmagent(如果使用) sudo systemctl enable --now vmagent
2.3.2 功能验证
# 1. 检查VM单机版健康状态
curl -s http://localhost:8428/health
# 预期输出:空响应,HTTP 200
# 2. 检查集群各组件
curl -s http://10.0.1.11:8482/health # vmstorage
curl -s http://10.0.1.21:8480/health # vminsert
curl -s http://10.0.1.22:8481/health # vmselect
# 3. 手动写入测试数据(单机版)
curl -d 'test_metric{job="test",instance="localhost"} 42'
http://localhost:8428/api/v1/import/prometheus
# 4. 查询验证
curl -s 'http://localhost:8428/api/v1/query?query=test_metric' | python3 -m json.tool
# 预期看到 test_metric 值为42
# 5. 集群版写入测试(通过vminsert)
curl -d 'test_metric{job="test"} 42'
http://10.0.1.21:8480/insert/0/prometheus/api/v1/import/prometheus
# 6. 集群版查询测试(通过vmselect)
curl -s 'http://10.0.1.22:8481/select/0/prometheus/api/v1/query?query=test_metric' | python3 -m json.tool
# 7. 检查Prometheus remote_write是否正常
# 在Prometheus的Web UI(:9090)查看 Status -> Runtime & Build Information
# 确认 remote_storage_samples_total 计数器在增长
# 8. 查看VM的内置监控指标
curl -s http://localhost:8428/metrics | grep vm_rows_inserted_total
# 这个计数器应该在持续增长
2.3.3 Grafana数据源配置
在Grafana中添加Prometheus类型的数据源:
单机版:URL填 http://VM_IP:8428
集群版:URL填 http://vmselect_IP:8481/select/0/prometheus
其他配置保持默认即可。添加完数据源后,导入一个Dashboard验证查询是否正常,推荐导入ID为11176的VictoriaMetrics官方Dashboard。
三、示例代码和配置
3.1 完整配置示例
3.1.1 集群版生产级部署配置
以下是我们线上跑了14个月的集群配置,3个vmstorage + 2个vminsert + 2个vmselect,承载约800万活跃时间序列,每秒写入约80万样本。
vmstorage启动参数(生产调优版):
# 文件路径:/etc/systemd/system/vmstorage.service [Unit] Description=VictoriaMetrics vmstorage - production After=network.target Wants=network-online.target [Service] Type=simple User=victoriametrics Group=victoriametrics ExecStart=/usr/local/bin/vmstorage -storageDataPath=/data/vmstorage -retentionPeriod=6 -httpListenAddr=:8482 -vminsertAddr=:8400 -vmselectAddr=:8401 -dedup.minScrapeInterval=15s -memory.allowedPercent=60 -search.maxUniqueTimeseries=10000000 -snapshotsMaxAge=72h -finalMergeDelay=10s -bigMergeConcurrency=2 -smallMergeConcurrency=4 -loggerTimezone=Asia/Shanghai -loggerOutput=stderr -loggerLevel=INFO Restart=always RestartSec=5 LimitNOFILE=131072 LimitNPROC=32000 # 防止OOM Killer杀掉进程 OOMScoreAdjust=-500 # 限制core dump大小 LimitCORE=0 [Install] WantedBy=multi-user.target
参数解释:
-bigMergeConcurrency=2:大合并并发数。默认值等于CPU核数的一半,在32核机器上会起16个合并线程,IO压力很大。设成2,合并速度慢一点但不影响读写性能。
-smallMergeConcurrency=4:小合并并发数。小合并频繁但每次数据量小,4个线程够用。
-snapshotsMaxAge=72h:快照最大保留时间。做备份时会创建快照,72小时后自动清理,防止忘记删快照撑爆磁盘。
-finalMergeDelay=10s:最终合并延迟。数据写入后等10秒再做最终合并,减少写放大。
vminsert生产配置:
# 文件路径:/etc/systemd/system/vminsert.service [Unit] Description=VictoriaMetrics vminsert - production After=network.target [Service] Type=simple User=victoriametrics Group=victoriametrics ExecStart=/usr/local/bin/vminsert -httpListenAddr=:8480 -storageNode=10.0.1.11:8400,10.0.1.12:8400,10.0.1.13:8400 -replicationFactor=2 -maxLabelsPerTimeseries=40 -maxConcurrentInserts=64 -insert.maxQueueDuration=30s -loggerTimezone=Asia/Shanghai Restart=always RestartSec=5 LimitNOFILE=131072 [Install] WantedBy=multi-user.target
vmselect生产配置:
# 文件路径:/etc/systemd/system/vmselect.service [Unit] Description=VictoriaMetrics vmselect - production After=network.target [Service] Type=simple User=victoriametrics Group=victoriametrics ExecStart=/usr/local/bin/vmselect -httpListenAddr=:8481 -storageNode=10.0.1.11:8401,10.0.1.12:8401,10.0.1.13:8401 -dedup.minScrapeInterval=15s -search.maxQueryDuration=120s -search.maxConcurrentRequests=64 -search.maxUniqueTimeseries=10000000 -search.maxSamplesPerQuery=500000000 -search.cacheTimestampOffset=5m -replicationFactor=2 -selectNode=10.0.1.22:8481 -loggerTimezone=Asia/Shanghai Restart=always RestartSec=5 LimitNOFILE=131072 [Install] WantedBy=multi-user.target
-search.maxSamplesPerQuery=500000000:单次查询最大样本数。默认10亿,但如果有人写了个查全量数据的PromQL,会把vmselect内存打爆。5亿是个比较安全的上限。
3.1.2 vmagent生产级采集配置
# 文件路径:/etc/victoriametrics/vmagent-prod.yml # 这个配置在我们的K8s集群上跑了10个月,采集200+节点 global: scrape_interval:15s scrape_timeout:10s external_labels: cluster:prod-bj-01 env:production region:cn-north-1 scrape_configs: # 节点监控 -job_name:"node-exporter" file_sd_configs: -files: -/etc/victoriametrics/targets/nodes/*.yml refresh_interval:30s metric_relabel_configs: # 丢弃不需要的高基数指标 -source_labels:[__name__] regex:"node_scrape_collector_duration_seconds|node_scrape_collector_success" action:drop # 丢弃不需要的文件系统指标(tmpfs等) -source_labels:[__name__,fstype] regex:"node_filesystem_.+;(tmpfs|devtmpfs|rootfs)" action:drop # Kubernetes API Server -job_name:"kubernetes-apiservers" kubernetes_sd_configs: -role:endpoints scheme:https tls_config: ca_file:/var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file:/var/run/secrets/kubernetes.io/serviceaccount/token relabel_configs: -source_labels:[__meta_kubernetes_namespace,__meta_kubernetes_service_name,__meta_kubernetes_endpoint_port_name] action:keep regex:default;kubernetes;https # kubelet和cAdvisor -job_name:"kubelet" kubernetes_sd_configs: -role:node scheme:https tls_config: ca_file:/var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecure_skip_verify:true bearer_token_file:/var/run/secrets/kubernetes.io/serviceaccount/token relabel_configs: -action:labelmap regex:__meta_kubernetes_node_label_(.+) -job_name:"cadvisor" kubernetes_sd_configs: -role:node scheme:https tls_config: ca_file:/var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecure_skip_verify:true bearer_token_file:/var/run/secrets/kubernetes.io/serviceaccount/token metrics_path:/metrics/cadvisor metric_relabel_configs: # cAdvisor指标非常多,只保留核心的 -source_labels:[__name__] regex:"container_cpu_usage_seconds_total|container_memory_working_set_bytes|container_memory_rss|container_network_receive_bytes_total|container_network_transmit_bytes_total|container_fs_usage_bytes|container_fs_limit_bytes" action:keep # 自动发现带prometheus注解的Pod -job_name:"kubernetes-pods" kubernetes_sd_configs: -role:pod relabel_configs: -source_labels:[__meta_kubernetes_pod_annotation_prometheus_io_scrape] action:keep regex:true -source_labels:[__meta_kubernetes_pod_annotation_prometheus_io_scheme] action:replace target_label:__scheme__ regex:(https?) -source_labels:[__meta_kubernetes_pod_annotation_prometheus_io_path] action:replace target_label:__metrics_path__ regex:(.+) -source_labels:[__address__,__meta_kubernetes_pod_annotation_prometheus_io_port] action:replace regex:([^:]+)(?::d+)?;(d+) replacement:$1:$2 target_label:__address__ -action:labelmap regex:__meta_kubernetes_pod_label_(.+) -source_labels:[__meta_kubernetes_namespace] action:replace target_label:namespace -source_labels:[__meta_kubernetes_pod_name] action:replace target_label:pod
3.1.3 vmctl数据迁移脚本
从Prometheus迁移历史数据到VictoriaMetrics:
#!/bin/bash # 文件名:migrate_prometheus_to_vm.sh # 功能:将Prometheus历史数据迁移到VictoriaMetrics # 实测迁移200GB Prometheus数据耗时约4小时 set -euo pipefail PROM_URL="http://10.0.1.50:9090" VM_URL="http://10.0.1.21:8480/insert/0/prometheus" # 迁移时间范围:最近90天 START_TIME=$(date -d "90 days ago" +%s) END_TIME=$(date +%s) LOG_FILE="/var/log/victoriametrics/migration_$(date +%Y%m%d_%H%M%S).log" echo"[$(date)] 开始迁移 Prometheus -> VictoriaMetrics" | tee -a "$LOG_FILE" echo"[$(date)] 时间范围: $(date -d @$START_TIME) -> $(date -d @$END_TIME)" | tee -a "$LOG_FILE" # vmctl native模式迁移,速度最快 /usr/local/bin/vmctl prometheus --prom-snapshot="/data/prometheus/snapshots/$(ls -t /data/prometheus/snapshots/ | head -1)" --vm-addr="$VM_URL" --vm-concurrency=8 --vm-batch-size=200000 2>&1 | tee -a "$LOG_FILE" # 如果没有快照,用API模式迁移(速度慢但不需要停Prometheus) # /usr/local/bin/vmctl prometheus # --prom-addr="$PROM_URL" # --vm-addr="$VM_URL" # --prom-start="$START_TIME" # --prom-end="$END_TIME" # --vm-concurrency=4 # --prom-concurrency=4 # 2>&1 | tee -a "$LOG_FILE" EXIT_CODE=$? if [ $EXIT_CODE -eq 0 ]; then echo"[$(date)] 迁移完成" | tee -a "$LOG_FILE" else echo"[$(date)] 迁移失败,退出码: $EXIT_CODE" | tee -a "$LOG_FILE" exit$EXIT_CODE fi # 验证迁移结果:对比源和目标的时间序列数 PROM_SERIES=$(curl -s "$PROM_URL/api/v1/label/__name__/values" | python3 -c "import sys,json; print(len(json.load(sys.stdin)['data']))") VM_SERIES=$(curl -s "http://10.0.1.22:8481/select/0/prometheus/api/v1/label/__name__/values" | python3 -c "import sys,json; print(len(json.load(sys.stdin)['data']))") echo"[$(date)] Prometheus指标数: $PROM_SERIES, VictoriaMetrics指标数: $VM_SERIES" | tee -a "$LOG_FILE"
3.2 实际应用案例
案例一:多租户监控平台
场景描述:公司有5个业务线,每个业务线有独立的Prometheus集群,需要统一存储和查询。用VictoriaMetrics集群版的多租户功能,每个业务线分配一个租户ID。
实现配置:
# 业务线A的Prometheus配置 # 租户ID: 1 remote_write: -url:"http://vminsert-lb:8480/insert/1/prometheus/api/v1/write" queue_config: max_samples_per_send:10000 max_shards:20 # 业务线B的Prometheus配置 # 租户ID: 2 remote_write: -url:"http://vminsert-lb:8480/insert/2/prometheus/api/v1/write" queue_config: max_samples_per_send:10000 max_shards:20 # 业务线C的Prometheus配置 # 租户ID: 3 remote_write: -url:"http://vminsert-lb:8480/insert/3/prometheus/api/v1/write" queue_config: max_samples_per_send:10000 max_shards:15
Grafana中为每个业务线配置独立的数据源:
业务线A数据源URL: http://vmselect-lb:8481/select/1/prometheus 业务线B数据源URL: http://vmselect-lb:8481/select/2/prometheus 业务线C数据源URL: http://vmselect-lb:8481/select/3/prometheus # 如果需要跨租户查询(运维团队全局视图): 全局数据源URL: http://vmselect-lb:8481/select/multitenant/prometheus
跨租户查询需要vmselect启动时加-search.tenantCacheExpireDuration=10s参数。实测跨5个租户查询聚合数据,延迟在500ms以内。
案例二:Prometheus HA + VictoriaMetrics去重
场景描述:两个Prometheus实例采集相同的目标做高可用,都remote_write到VictoriaMetrics。VM自动去重,Grafana只查VM。
架构:
Prometheus-A (10.0.1.51) ──remote_write──> VictoriaMetrics ↑ Prometheus-B (10.0.1.52) ──remote_write──────┘ │ Grafana <─┘ (查询)
Prometheus-A配置:
# /etc/prometheus/prometheus.yml (Prometheus-A) global: scrape_interval:15s external_labels: replica:prom-a cluster:prod remote_write: -url:"http://10.0.1.21:8480/insert/0/prometheus/api/v1/write" queue_config: max_samples_per_send:10000 max_shards:30
Prometheus-B配置(只有replica标签不同):
# /etc/prometheus/prometheus.yml (Prometheus-B) global: scrape_interval:15s external_labels: replica:prom-b cluster:prod remote_write: -url:"http://10.0.1.21:8480/insert/0/prometheus/api/v1/write" queue_config: max_samples_per_send:10000 max_shards:30
VictoriaMetrics端配置-dedup.minScrapeInterval=15s,VM会按时间戳对齐去重,两个Prometheus写入的相同指标只保留一份。去重后存储量和单Prometheus一样,但任何一个Prometheus挂了数据都不会断。
我们线上用这个方案跑了一年多,中间Prometheus-A因为机器故障重启过3次,每次都是Prometheus-B无缝接管,Grafana上看不到任何数据断点。
四、最佳实践和注意事项
4.1 最佳实践
4.1.1 存储容量规划
容量规划是上线前必须做的事,算错了要么磁盘爆满丢数据,要么浪费钱买了用不上的SSD。
计算公式:
磁盘用量 = 活跃时间序列数 × 每个样本压缩后大小 × 每天采样次数 × 保留天数 × 副本数 实际例子: - 活跃时间序列:500万 - 采集间隔:15秒(每天5760次采样) - 每个样本压缩后大小:约0.5-1.5字节(VM的压缩率) - 保留6个月(180天) - 副本数:2 磁盘用量 = 5,000,000 × 1.0 × 5,760 × 180 × 2 = 约10.4TB
实际使用中,VM的压缩率会随数据特征变化。我们的经验值:
计数器类指标(Counter):压缩后每样本约0.4字节
仪表盘类指标(Gauge):压缩后每样本约1.0-1.5字节
直方图类指标(Histogram):压缩后每样本约0.8字节
# 查看当前VM的实际压缩率 curl -s http://localhost:8428/api/v1/status/tsdb | python3 -m json.tool # 查看磁盘使用详情 curl -s http://localhost:8428/internal/force_flush du -sh /data/victoriametrics/data/
生产环境建议磁盘预留30%的余量,因为合并操作会临时占用额外空间。
4.1.2 降采样(Downsampling)配置
长期存储的数据不需要保持原始精度。比如3个月前的数据,1分钟一个点就够了,没必要保留15秒的原始精度。VictoriaMetrics企业版支持降采样,开源版可以用vmalert做recording rules实现类似效果。
# vmalert降采样规则
# 文件路径:/etc/victoriametrics/downsampling_rules.yml
groups:
-name:downsampling_5m
interval:5m
rules:
# 将CPU使用率降采样为5分钟平均值
-record:cpu_usage_avg:5m
expr:avg_over_time(node_cpu_seconds_total{mode!="idle"}[5m])
# 将内存使用降采样为5分钟平均值
-record:memory_usage_avg:5m
expr:avg_over_time(node_memory_MemAvailable_bytes[5m])
# 将网络流量降采样为5分钟速率
-record:network_receive_rate:5m
expr:rate(node_network_receive_bytes_total[5m])
-name:downsampling_1h
interval:1h
rules:
# 1小时粒度的聚合,用于月度报表
-record:cpu_usage_avg:1h
expr:avg_over_time(cpu_usage_avg:5m[1h])
-record:memory_usage_avg:1h
expr:avg_over_time(memory_usage_avg:5m[1h])
4.1.3 去重策略
跑双Prometheus HA时,去重配置不对会导致数据翻倍或者查询结果不稳定。
# VM端去重配置(单机版或vmstorage) -dedup.minScrapeInterval=15s # vmselect端也要配(集群版) -dedup.minScrapeInterval=15s
去重的原理:VM按时间戳对齐,同一个时间序列在同一个时间窗口(15秒)内只保留一个样本。两个Prometheus采集同一个target,时间戳可能差几百毫秒,但在15秒窗口内会被合并。
踩坑经验:-dedup.minScrapeInterval的值必须等于或大于Prometheus的scrape_interval。如果Prometheus是15秒采集,这里设成10秒,会导致部分数据没被去重,查询时出现毛刺。
4.1.4 性能调优
# 1. 调整系统参数 # 增大文件描述符限制 echo"victoriametrics soft nofile 131072" >> /etc/security/limits.conf echo"victoriametrics hard nofile 131072" >> /etc/security/limits.conf # 调整内核参数 cat >> /etc/sysctl.conf << 'EOF' # VictoriaMetrics优化 vm.max_map_count = 262144 net.core.somaxconn = 65535 net.ipv4.tcp_max_syn_backlog = 65535 net.core.netdev_max_backlog = 65535 EOF sudo sysctl -p # 2. 磁盘IO优化(如果用的是SSD) echo none > /sys/block/sda/queue/scheduler echo 256 > /sys/block/sda/queue/nr_requests
4.1.5 安全加固
# 1. 用Nginx做反向代理,加上基础认证
sudo apt install -y nginx apache2-utils
# 创建认证文件
sudo htpasswd -bc /etc/nginx/.htpasswd vmuser 'StrongP@ssw0rd'
# Nginx配置
cat > /etc/nginx/conf.d/victoriametrics.conf << 'NGINX_EOF'
upstream vmselect {
server 10.0.1.22:8481;
keepalive 32;
}
upstream vminsert {
server 10.0.1.21:8480;
keepalive 32;
}
server {
listen 443 ssl;
server_name vm.example.com;
ssl_certificate /etc/nginx/ssl/vm.crt;
ssl_certificate_key /etc/nginx/ssl/vm.key;
# 查询接口 - 需要认证
location /select/ {
auth_basic "VictoriaMetrics";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://vmselect;
proxy_set_header Host $host;
proxy_read_timeout 120s;
}
# 写入接口 - 用IP白名单替代认证(Prometheus不支持basic auth的remote_write)
location /insert/ {
allow 10.0.1.0/24;
deny all;
proxy_pass http://vminsert;
proxy_set_header Host $host;
}
# 禁止访问管理接口
location /internal/ {
deny all;
}
}
NGINX_EOF
# 2. 限制VM的监听地址(不要监听0.0.0.0) # 在systemd服务文件中修改 -httpListenAddr=10.0.1.11:8482 # 只监听内网IP # 3. 关闭不需要的API端点 # vmselect启动参数加上 -search.resetCacheAuthKey=your-secret-key # 重置缓存需要密钥 -deleteAuthKey=your-delete-key # 删除数据需要密钥 -snapshotAuthKey=your-snapshot-key # 创建快照需要密钥
# 4. 配置防火墙规则 # 只允许特定IP访问VM端口 sudo ufw allow from 10.0.1.0/24 to any port 8428 sudo ufw allow from 10.0.1.0/24 to any port 8480 sudo ufw allow from 10.0.1.0/24 to any port 8481 sudo ufw allow from 10.0.1.0/24 to any port 8482 sudo ufw deny 8428 sudo ufw deny 8480 sudo ufw deny 8481 sudo ufw deny 8482
4.2 注意事项
4.2.1 配置注意事项
改retentionPeriod之前先算好磁盘:把保留时间从3个月改成12个月,磁盘用量会翻4倍。改之前先用上面的公式算一下,确认磁盘够用再改。改完重启VM,旧数据不会立即删除,要等到过期时间才会清理。
-retentionPeriod改小不会立即释放空间,VM的数据按月份分目录存储,只有整个月份过期后才会删除对应目录。比如从6个月改成3个月,要等3个月后才能看到空间释放。
集群版扩容vmstorage节点后,新节点不会自动均衡旧数据。新数据会均匀分布到所有节点,但旧数据还在原来的节点上。如果需要均衡,得用vmctl做数据迁移。
vminsert的-storageNode列表顺序很重要,改变顺序会导致数据分布变化。扩容时只在末尾追加新节点,不要调整已有节点的顺序。
4.2.2 常见错误
| 错误现象 | 原因分析 | 解决方案 |
|---|---|---|
| cannot allocate memory VM进程被OOM Kill | 没设-memory.allowedPercent,VM吃满了系统内存 | 设置-memory.allowedPercent=60,同时检查是否有大范围查询 |
| too many open files | 文件描述符限制太低 | systemd配置LimitNOFILE=131072,同时改/etc/security/limits.conf |
| Prometheus remote_write报context deadline exceeded | VM写入队列满了或网络延迟高 | 增大vminsert的-maxConcurrentInserts,检查网络延迟 |
| 查询返回the number of unique timeseries exceeds | 查询命中的时间序列数超过限制 | 调大-search.maxUniqueTimeseries,或优化PromQL缩小查询范围 |
| 集群版查询数据不一致 | vmselect的-replicationFactor和vminsert不一致 | 确保两端的-replicationFactor值相同 |
| 磁盘空间持续增长不释放 | 快照没清理或合并操作积压 | 检查/data/vmstorage/snapshots/目录,清理过期快照 |
4.2.3 兼容性问题
PromQL兼容性:VictoriaMetrics兼容99%的PromQL语法,但有少数边界情况行为不同。比如rate()函数在数据有间断时,VM和Prometheus的插值逻辑略有差异。迁移后建议对比关键告警规则的查询结果。
remote_write协议版本:VM支持Prometheus remote_write v1和v2协议。Prometheus 2.47+默认用v2,如果VM版本低于1.93.0不支持v2,需要在Prometheus端强制用v1:remote_write.protocol_version: 1。
Grafana版本:Grafana 9.x以上对VM的兼容性最好。8.x版本在使用$__rate_interval变量时可能有问题,建议升级到9.x+。
五、故障排查和监控
5.1 故障排查
5.1.1 日志查看
# 查看VM单机版日志 sudo journalctl -u victoriametrics -f --no-pager # 查看集群各组件日志 sudo journalctl -u vmstorage -f --no-pager sudo journalctl -u vminsert -f --no-pager sudo journalctl -u vmselect -f --no-pager # 查看最近的错误日志 sudo journalctl -u victoriametrics --since "1 hour ago" | grep -i "error|warn|fatal" # 查看vmagent日志 sudo journalctl -u vmagent -f --no-pager # 如果配置了日志文件输出 tail -f /var/log/victoriametrics/vm.log | grep -v "DEBUG"
5.1.2 常见问题排查
问题一:数据写入延迟,Prometheus remote_write队列积压
# 在Prometheus端查看remote_write队列状态 curl -s http://localhost:9090/api/v1/query?query=prometheus_remote_storage_pending_samples | python3 -m json.tool # 如果pending_samples持续增长,说明写入速度跟不上 # 检查vminsert的写入延迟 curl -s http://10.0.1.21:8480/metrics | grep vm_http_request_duration # 检查vmstorage的磁盘IO iostat -x 1 5 # 检查网络延迟 ping -c 10 10.0.1.21
解决方案:
增大Prometheus的max_shards(从30调到50)
检查vmstorage所在机器的磁盘IO,如果IO util超过80%,考虑换SSD或增加存储节点
检查vminsert到vmstorage的网络延迟,超过5ms就需要排查网络问题
用write_relabel_configs过滤掉不需要的指标,减少写入量
问题二:查询慢,Grafana Dashboard加载超时
# 查看vmselect的查询延迟分布 curl -s http://10.0.1.22:8481/metrics | grep vm_request_duration_seconds # 查看慢查询日志(需要启动时加参数) # -search.logSlowQueryDuration=5s 记录超过5秒的查询 sudo journalctl -u vmselect | grep "slow query" # 查看当前正在执行的查询 curl -s http://10.0.1.22:8481/api/v1/status/active_queries | python3 -m json.tool
解决方案:
优化PromQL查询,避免{__name__=~".+"}这种全量匹配
缩小查询时间范围,30天的数据用step=5m而不是默认的15s
增加vmselect实例数,用Nginx做负载均衡
检查是否有高基数标签(比如把request_id作为标签),用/api/v1/status/tsdb查看top标签
问题三:磁盘空间不足,VM拒绝写入
# 查看磁盘使用 df -h /data/victoriametrics/ # 查看各月份数据目录大小 du -sh /data/victoriametrics/data/big/*/ du -sh /data/victoriametrics/data/small/*/ # 检查是否有未清理的快照 ls -la /data/victoriametrics/snapshots/ # 强制清理过期数据(谨慎操作) curl -s http://localhost:8428/internal/force_merge?partition_prefix=2024_01
解决方案:
清理过期快照:curl http://localhost:8428/snapshot/delete_all
缩短保留时间(临时措施):改-retentionPeriod后重启
扩容磁盘或增加存储节点
检查是否有异常的高基数指标占用大量空间
问题四:集群节点故障恢复
# 检查集群状态 # vminsert会自动跳过不可用的vmstorage节点 curl -s http://10.0.1.21:8480/metrics | grep vm_rpc_connection # 查看哪些存储节点不可用 curl -s http://10.0.1.21:8480/metrics | grep "vm_rpc_dial_errors_total" # 节点恢复后,检查数据完整性 # 如果replicationFactor=2,单节点故障不丢数据 # 节点恢复后自动重新加入集群,不需要手动操作
5.1.3 调试模式
# 开启详细日志 # 在systemd服务文件中修改启动参数 -loggerLevel=INFO # 改为 -loggerLevel=DEBUG(排查完记得改回来) # 开启慢查询日志 -search.logSlowQueryDuration=5s # 开启HTTP请求日志(会产生大量日志,只在排查时开启) -httpLogRequests # 查看内部状态 curl -s http://localhost:8428/api/v1/status/tsdb | python3 -m json.tool curl -s http://localhost:8428/api/v1/status/active_queries | python3 -m json.tool # 查看内存使用详情 curl -s http://localhost:8428/metrics | grep process_resident_memory_bytes curl -s http://localhost:8428/metrics | grep go_memstats_alloc_bytes
5.2 性能监控
5.2.1 关键指标监控
# 写入速率(每秒插入的行数) curl -s http://localhost:8428/metrics | grep vm_rows_inserted_total # 查询速率 curl -s http://localhost:8428/metrics | grep vm_http_requests_total # 活跃时间序列数 curl -s http://localhost:8428/metrics | grep vm_cache_entries.*metricName # 磁盘使用 curl -s http://localhost:8428/metrics | grep vm_data_size_bytes # 合并操作状态 curl -s http://localhost:8428/metrics | grep vm_merges
5.2.2 监控指标说明
| 指标名称 | 正常范围 | 告警阈值 | 说明 |
|---|---|---|---|
| vm_rows_inserted_total rate | 根据采集量而定 | 突降50%以上 | 写入速率突降说明数据源异常 |
| vm_slow_queries_total | 0-5/min | >10/min | 慢查询过多说明需要优化查询或扩容 |
| process_resident_memory_bytes |
|
>80%系统内存 |
内存使用过高有OOM风险 |
|
| vm_free_disk_space_bytes | >20%总容量 | <10%总容量 | 磁盘空间不足会导致拒绝写入 |
| vm_merge_need_free_disk_space | 0 | >0 | 合并操作因磁盘不足被阻塞 |
| vm_http_request_duration_seconds p99 | <1s | >5s | 查询延迟过高影响用户体验 |
5.2.3 Prometheus监控规则
# 文件路径:/etc/prometheus/rules/victoriametrics.yml
groups:
-name:victoriametrics_alerts
interval:30s
rules:
# 写入速率突降
-alert:VMWriteRateDrop
expr:|
rate(vm_rows_inserted_total[5m]) < 0.5 * rate(vm_rows_inserted_total[5m] offset 1h)
for:10m
labels:
severity:warning
annotations:
summary:"VictoriaMetrics写入速率下降超过50%"
description:"当前写入速率: {{ $value | humanize }}/s"
# 磁盘空间不足
-alert:VMDiskSpaceLow
expr:|
vm_free_disk_space_bytes / vm_available_disk_space_bytes < 0.15
for:5m
labels:
severity:critical
annotations:
summary:"VictoriaMetrics磁盘剩余空间不足15%"
description:"剩余空间: {{ $value | humanize1024 }}B"
# 查询延迟过高
-alert:VMSlowQueries
expr:|
histogram_quantile(0.99, rate(vm_request_duration_seconds_bucket[5m])) > 5
for:10m
labels:
severity:warning
annotations:
summary:"VictoriaMetrics P99查询延迟超过5秒"
# 内存使用过高
-alert:VMHighMemoryUsage
expr:|
process_resident_memory_bytes{job="victoriametrics"} / node_memory_MemTotal_bytes > 0.8
for:5m
labels:
severity:critical
annotations:
summary:"VictoriaMetrics内存使用超过80%"
# vmstorage节点不可用(集群版)
-alert:VMStorageNodeDown
expr:|
up{job="vmstorage"} == 0
for:2m
labels:
severity:critical
annotations:
summary:"vmstorage节点 {{ $labels.instance }} 不可用"
# 合并操作积压
-alert:VMMergeQueueFull
expr:|
vm_assisted_merges_total > 0
for:15m
labels:
severity:warning
annotations:
summary:"VictoriaMetrics合并操作积压,可能影响查询性能"
5.3 备份与恢复
5.3.1 备份策略
#!/bin/bash
# 文件名:vm_backup.sh
# VictoriaMetrics备份脚本
# 利用VM的快照功能做一致性备份
set -euo pipefail
VM_URL="http://localhost:8428"
BACKUP_DIR="/backup/victoriametrics"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_PATH="${BACKUP_DIR}/${DATE}"
RETENTION_DAYS=7
LOG_FILE="/var/log/victoriametrics/backup_${DATE}.log"
log() {
echo"[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log"开始VictoriaMetrics备份"
# 1. 创建快照
SNAPSHOT_RESPONSE=$(curl -s "${VM_URL}/snapshot/create")
SNAPSHOT_NAME=$(echo"$SNAPSHOT_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['snapshot'])")
log"创建快照: $SNAPSHOT_NAME"
SNAPSHOT_PATH="/data/victoriametrics/snapshots/${SNAPSHOT_NAME}"
# 2. 用rsync备份快照目录
mkdir -p "$BACKUP_PATH"
rsync -a --progress "$SNAPSHOT_PATH/""$BACKUP_PATH/" 2>&1 | tee -a "$LOG_FILE"
log"备份完成: $BACKUP_PATH"
# 3. 删除快照(释放空间)
curl -s "${VM_URL}/snapshot/delete?snapshot=${SNAPSHOT_NAME}" | tee -a "$LOG_FILE"
log"快照已删除: $SNAPSHOT_NAME"
# 4. 清理过期备份
find "$BACKUP_DIR" -maxdepth 1 -type d -mtime +${RETENTION_DAYS} -exec rm -rf {} ;
log"已清理${RETENTION_DAYS}天前的备份"
# 5. 记录备份大小
BACKUP_SIZE=$(du -sh "$BACKUP_PATH" | awk '{print $1}')
log"备份大小: $BACKUP_SIZE"
5.3.2 恢复流程
# 1. 停止VictoriaMetrics服务
sudo systemctl stop victoriametrics
# 2. 备份当前数据目录(以防恢复出问题)
sudo mv /data/victoriametrics /data/victoriametrics.bak.$(date +%Y%m%d)
# 3. 恢复备份数据
sudo mkdir -p /data/victoriametrics
sudo rsync -a /backup/victoriametrics/20250115_020000/ /data/victoriametrics/
# 4. 修复权限
sudo chown -R victoriametrics:victoriametrics /data/victoriametrics
# 5. 启动服务
sudo systemctl start victoriametrics
# 6. 验证数据完整性
sleep 10
curl -s 'http://localhost:8428/api/v1/query?query=count({__name__=~".+"})' | python3 -m json.tool
# 对比恢复前后的时间序列总数
# 7. 确认恢复成功后删除旧数据备份
# sudo rm -rf /data/victoriametrics.bak.*
六、总结
6.1 技术要点回顾
单机版一个二进制搞定:中小规模(500万活跃序列以内)用单机版就够了,部署简单,运维成本低。别一上来就搞集群,单机版的性能已经超过大多数场景的需求。
集群版三组件架构:vminsert/vmselect/vmstorage各司其职,vminsert和vmselect无状态可以随意扩缩,vmstorage有状态需要谨慎操作。扩容vmstorage时只在storageNode列表末尾追加,不要改变已有节点顺序。
去重机制是HA的基础:-dedup.minScrapeInterval必须等于或大于Prometheus的采集间隔,vminsert和vmselect两端都要配。双Prometheus HA + VM去重的方案经过生产验证,稳定可靠。
内存限制必须设:-memory.allowedPercent=60是生产环境必配参数,不设的话VM会吃满内存被OOM Killer干掉。这个坑我们踩过两次。
压缩率决定存储成本:实测压缩比在10:1到15:1之间,同样的数据量,VM的磁盘占用只有Prometheus的1/7到1/10。做容量规划时按每样本1字节估算比较安全。
remote_write调优不能忽略:Prometheus端的queue_config参数直接影响写入性能,max_shards和max_samples_per_send要根据实际采集量调整,默认值在大规模场景下不够用。
6.2 进阶学习方向
VMAlert + 告警管理:用VMAlert替代Prometheus的告警评估,支持从VictoriaMetrics直接查询数据做告警判断,减少对Prometheus的依赖。VMAlert支持recording rules和alerting rules,语法和Prometheus完全兼容。
学习资源:https://docs.victoriametrics.com/vmalert/
实践建议:先把现有的Prometheus告警规则迁移到VMAlert,验证告警结果一致后再下线Prometheus的告警功能
VictoriaMetrics Operator(K8s部署):如果你的基础设施跑在Kubernetes上,用VM Operator可以通过CRD声明式管理VM集群,自动处理扩缩容、滚动更新、备份等操作。
学习资源:https://docs.victoriametrics.com/operator/
实践建议:先在测试集群部署VMCluster CRD,熟悉各参数后再迁移生产环境
VictoriaLogs(日志存储):VictoriaMetrics团队推出的日志存储方案,和VictoriaMetrics指标存储配合使用,可以在Grafana中实现指标和日志的关联查询。目前还在快速迭代中,适合技术预研。
学习资源:https://docs.victoriametrics.com/victorialogs/
6.3 参考资料
VictoriaMetrics官方文档 - 最权威的参考,更新及时
VictoriaMetrics GitHub - 源码和Issue讨论
Prometheus remote_write配置 - remote_write协议和参数说明
VictoriaMetrics vs Thanos性能对比 - 官方的Benchmark数据
附录
A. 命令速查表
# 单机版启停
sudo systemctl start victoriametrics
sudo systemctl stop victoriametrics
sudo systemctl restart victoriametrics
sudo systemctl status victoriametrics
# 集群版启停(按顺序)
sudo systemctl start vmstorage && sudo systemctl start vminsert && sudo systemctl start vmselect
sudo systemctl stop vmselect && sudo systemctl stop vminsert && sudo systemctl stop vmstorage
# 健康检查
curl -s http://localhost:8428/health # 单机版
curl -s http://localhost:8480/health # vminsert
curl -s http://localhost:8481/health # vmselect
curl -s http://localhost:8482/health # vmstorage
# 查看TSDB状态
curl -s http://localhost:8428/api/v1/status/tsdb | python3 -m json.tool
# 查看活跃查询
curl -s http://localhost:8428/api/v1/status/active_queries | python3 -m json.tool
# 创建快照(备份用)
curl -s http://localhost:8428/snapshot/create
# 删除所有快照
curl -s http://localhost:8428/snapshot/delete_all
# 强制合并(减少磁盘碎片)
curl -s http://localhost:8428/internal/force_merge
# 手动写入测试数据
curl -d 'test{job="test"} 123' http://localhost:8428/api/v1/import/prometheus
# 查询测试
curl -s 'http://localhost:8428/api/v1/query?query=up' | python3 -m json.tool
# 查看标签值
curl -s 'http://localhost:8428/api/v1/label/__name__/values' | python3 -m json.tool
# 删除时间序列(需要配置deleteAuthKey)
curl -d 'match[]={job="test"}' http://localhost:8428/api/v1/admin/tsdb/delete_series
B. 配置参数详解
| 参数 | 默认值 | 建议值 | 说明 |
|---|---|---|---|
| -retentionPeriod | 1(月) | 按需设置 | 数据保留时间,支持月(数字)和天(如180d) |
| -memory.allowedPercent | 不限制 | 60 | 内存使用上限百分比,生产必设 |
| -dedup.minScrapeInterval | 0(不去重) | 等于scrape_interval | HA场景必设 |
| -search.maxUniqueTimeseries | 300000 | 5000000-10000000 | 单次查询最大时间序列数 |
| -search.maxQueryDuration | 30s | 60s-120s | 单次查询最大执行时间 |
| -search.maxConcurrentRequests | 16 | 32-64 | 最大并发查询数 |
| -maxLabelsPerTimeseries | 30 | 40 | 每个时间序列最大标签数 |
| -replicationFactor | 1 | 2 | 集群版数据副本数 |
| -bigMergeConcurrency | CPU/2 | 2 | 大合并并发数,降低IO压力 |
| -smallMergeConcurrency | CPU/2 | 4 | 小合并并发数 |
| -search.logSlowQueryDuration | 5s | 5s | 慢查询日志阈值 |
| -remoteWrite.maxDiskUsagePerURL | 不限制 | 1GB | vmagent本地缓存上限 |
C. 术语表
| 术语 | 英文 | 解释 |
|---|---|---|
| 时间序列 | Time Series | 由指标名和标签集唯一标识的一组按时间排列的数据点 |
| 活跃序列 | Active Time Series | 最近一个采集周期内有新数据写入的时间序列 |
| 远程写入 | Remote Write | Prometheus将采集的数据通过HTTP协议发送到远端存储的机制 |
| 去重 | Deduplication | 多个数据源写入相同时间序列时,只保留一份数据的机制 |
| 降采样 | Downsampling | 将高精度数据聚合为低精度数据以节省存储空间 |
| 高基数 | High Cardinality | 某个标签的取值种类非常多(如用户ID),导致时间序列数爆炸 |
| 合并 | Merge/Compaction | 将多个小数据块合并为大数据块,提高查询效率和压缩率 |
| 租户 | Tenant | 集群版中用于隔离不同业务数据的逻辑单元,通过URL路径中的数字ID区分 |
| 快照 | Snapshot | 数据目录的只读副本,用于一致性备份 |
| MetricsQL | MetricsQL | VictoriaMetrics扩展的查询语言,兼容PromQL并增加了额外函数 |
全部0条评论
快来发表一下你的评论吧 !