作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!


1.背景

在可观测领域的 metrics 解决方案中,VictoriaMetrics 整个产品体系的性能非常高。两年前,我们团队用这个组件来代替 kafka+druid 实现的旧版监控系统。其中一个群集扛住了鹅厂内部一个达到 9000 万/s datapoint 的业务所产生的 metrics 数据,vm 部分用了不到 1000 核,成本相比 kafka+druid 低了很多。

美中不足是 VictoriaMetrics 并未提供类似历史群集的解决方案,虽然提供了免费的 vmbackup 和 vmrestore 工具,但是数据的备份和恢复与历史群集相比仍然是不够的。

历史群集的难题是这样的:

  1. 与历史群集相对的实时群集,默认情况下实时群集仅保存最近 30 天的数据;如果需要读取 30 一天,以及更长周期的数据,就需要把备份数据恢复出来形成历史群集;

  2. 实时群集一般会部署多个 sharding 节点:

    • 如果 vm-insert 上的 -replicationFactor=1,则数据不重复,每个 sharding 上的数据完全重复,每个节点是全量数据的 n 分之一。
    • 如果 vm-insert 上的 -replicationFactor=2, 则各个 sharding 上的数据有一部分与其他 sharding 节点是重复的。
  3. vm-backup 的备份功能是针对 vm-storage 的 sharding 节点的,如果 vm-storage 群集有 n 个节点,则每个节点都需要独立使用 vm-backup 来备份。

    • vm-backup 的原理是先使用 http 协议访问 vm-storage 的 http 服务,访问 /snapshot/create 来创建一个所有磁盘上数据文件的快照。
    • 数据文件的快照是文件系统的 hardlink,意味着只是在 vfs 上增加对数据文件的引用计数,不会产生拷贝。这一步非常快。
    • vm-backup 将数据文件备份到 s3 中;
    • 备份完成后,调用 vm-storage http 中的 /snapshot/delete?snapshot=<id> 来删除快照
  4. 备份完成后:

    • s3 上每个 sharding 对应着一个数据的文件夹

    • 每个数据文件夹的数据包含从创建快照开始,倒数 30 天的数据;(如果默认的数据存储周期是 30 天的话)

    • 如果需要每天都全新备份,则还需要产生以日期命名的文件夹

    • 下面是一个 s3 上备份目录的例子:

          s3://bucket_name:
      metrics_data/
      daily/
      2024-01-26/
      sharding-0/
      sharding-1/
      sharding-2/
  5. 如果需要直接根据历史的备份数据来启动历史群集,则:

    • 有多少个 sharding, 就要启动多少个 vm-storage 实例;
    • 假设从昨天的备份数据开始启动 vm-storage,则这一组 vm-storage 支持 -1 天到 -31 天的历史数据查询;
    • 当过去了 24 小时,之前的 vm-storage 群集支持的数据变成了 -2 天到 -32 天。如果需要始终从-1 天开始,则需要在每天半夜重新下载最新的备份,然后重启 vm-storage;
    • 如果需要支持更长周期,例如 -31 天到 -61 天,则需要从 -31 天开始的备份数据里,再启动一组 vm-storage 群集。假设需要支持过去 300天的历史数据查询,则需要部署十组 vm-storage.

通过以上的描述,应该可以了解到通过目前的工具,支持历史群集很麻烦。

实际上,我已经通过已有的工具做出来了对应的部署脚本,请看:https://github.com/ahfuzhang/deploy_VictoriaMetrics_cluster/tree/main/terraform/historical_cluster

2.vmfile

从官方的文档(https://docs.victoriametrics.com/vmbackupmanager.html)看,vmbackupmanager 对备份数据有更强大的功能,不过也仍然没有提如何部署历史群集。

收费购买企业版套件,有可能让部署历史群集变得简单。

如果有一个工具,能够从多个 sharding 中导出 metrics 数据,然后再导入到一个包含所有数据的文件夹中,那么部署历史群集就会非常简单了。

因此,我花了两周时间写出了这个可能节约 2 万美元的小工具:vmfile,对离线的 vm-storage 的数据文件进行处理。

vmfile 的相关链接是:

下面介绍一下这个工具的几个基本功能:

2.1 count_index 统计数据文件的索引信息

  • 通过 -storageDataPath 来指向某个 vm-storage 的数据(或者通过 vm-restore 恢复的)文件夹。
vmfile \
-action=count_index \
-storageDataPath=/Users/fuchunzhang/xxx/data/realtime-cluster/sharding-0/ \
-fs.disableMmap=false

2.2 count_data 统计数据文件的数据信息

vmfile \
-action=count_data \
-storageDataPath=/Users/fuchunzhang/xxx/data/realtime-cluster/sharding-0/ \
-fs.disableMmap=false

2.3 export_metrics 导出 metrics 数据到文本文件

  • 通过 output 来指定导出的位置
vmfile \
-action=export_metrics \
-storageDataPath=/Users/fuchunzhang/xxx/data/realtime-cluster/sharding-0/ \
-output=./metrics.txt \
-fs.disableMmap=false

(后续会优化这个功能,例如:可以把所有 metrics 数据的 name, value, timestamp 都导出,然后可以再导入到 clickhouse 做复杂分析)

2.4 simple_merge 简单合并多个 sharding 数据

把多个 sharding 文件夹的数据,把索引和数据两部分分别拷贝到目的文件夹,并最终成为一个可以正常启动 vm-storage 的数据文件夹。

  • simple_merge_from: 多个逗号分隔的路径
  • simple_merge_to: merge 后的目的文件夹
vmfile \
-action=simple_merge \
-simple_merge_from=/Users/fuchunzhang/xxx/data/2024-01-02/sharding-0/,/Users/fuchunzhang/xxx/data/2024-01-02/sharding-1/,/Users/fuchunzhang/xxx/data/2024-01-02/sharding-2/ \
-simple_merge_to=/Users/fuchunzhang/Documents/temp/2024/simple_merge

2.5 merge 重建索引和数据方式的merge

  • mergev2_from: 多个逗号分隔的路径
  • mergev2_to: merge 后的目的文件夹
vmfile \
-action=merge_v2 \
-mergev2_from=/Users/fuchunzhang/xxx/sharding-0/,/Users/fuchunzhang/xxx/sharding-1/,/Users/fuchunzhang/xxx/sharding-2/ \
-mergev2_to=/Users/fuchunzhang/Documents/temp/2024/2024-01-22/merge_v2/ \
-dedup.minScrapeInterval=0s \
-cpu=1

2.5.1 降采样(downsample)功能

-dedup.minScrapeInterval=0s 的时候,数据部分不会丢失任何数据。

可以使用这个参数指定一个时间窗口,在时间窗口内,同一个 metric 仅保留一个 data point。

下面的例子,每 5 分钟仅保留一个 data point,数据部分的体积会缩小很多:

vmfile \
-action=merge_v2 \
-mergev2_from=/Users/fuchunzhang/xxx/sharding-0/,/Users/fuchunzhang/xxx/sharding-1/,/Users/fuchunzhang/xxx/sharding-2/ \
-mergev2_to=/Users/fuchunzhang/Documents/temp/2024/2024-01-22/merge_v2/ \
-dedup.minScrapeInterval=5m \
-cpu=1

使用降采样方式的 merge,我的测试数据如下:

  • 降采样时间窗口 0s: 数据部分膨胀 1.1 倍,merge 后记录数不变
  • 降采样时间窗口 1m: 数据部分膨胀 1.005 倍, merge 后记录数减少 0.004%
  • 降采样时间窗口 5m: 数据部分减少 2.919 倍, merge 后记录数减少 79.97%

2.5.2 索引和数据并行merge

-cpu=参数大于 1 时,索引部分和数据部分会并行 merge。目前最多只支持两个核。

vmfile \
-action=merge_v2 \
-mergev2_from=/Users/fuchunzhang/xxx/sharding-0/,/Users/fuchunzhang/xxx/sharding-1/,/Users/fuchunzhang/xxx/sharding-2/ \
-mergev2_to=/Users/fuchunzhang/Documents/temp/2024/2024-01-22/merge_v2/ \
-dedup.minScrapeInterval=5m \
-cpu=2

3.历史群集部署

有了 vmfile 这个工具后,部署历史群集就简单很多了。

每天只需要把最新的备份数据不断 merge 到一个最终的数据文件就行了。(当然,这里仍然是离线操作的)

每天自动拉取最新的各个 sharding,并开始 merge,然后停掉旧的 vm-storage,启动新的 vm-storage……这一系列的动作我都通过一个 shell 脚本来实现了。

我通过 terraform 来实现了 k8s 上的部署代码,通过阅读源码,修改成别的部署方式也很容易。

历史群集的部署流程如下:

  1. 实时群集需要创建 crontab,每天半夜使用 vmbackup 把各个 sharding 部署到 s3 上;

  2. 构造一个新的 docker 镜像:

  3. 创建一个 k8s 上的 deployment,启动命令是上面提到的 shell

        container {
name = "${local.vm-storage-name-with-merge}-${count.index}"
image = "ahfuzhang/vm-historical:v1.95.1-vmfile" # 包含了多种工具和 shell 的镜像
image_pull_policy = "Always" #"IfNotPresent"
command = ["/bin/sh"]
args = [
"/daily_with_vmfile.sh", # 从镜像中的 shell 脚本启动
]
......

部署的代码请看:https://github.com/ahfuzhang/deploy_VictoriaMetrics_cluster/blob/main/terraform/historical_cluster/vm-storage-with-merge.tf

shell 的控制参数通过容器的环境变量来传入,重要的参数有这些:

  • storage_base_path: 本地的存储路径
  • s3_storage_base_path: s3 上的备份文件的路径
  • sharding_count: sharding 的个数
  • n_days_before : 历史群集从几天以前开始,填 1 就是昨天。历史群集会在第二天半夜拉取最新备份,始终维持在当前时间的 n 天以前。
  1. shell 的执行逻辑:

    • 检查是否已经存在 merge 后的文件夹,如果不存在,就使用 vmrestore 来下载多个 sharding
    • sharding 文件夹下载好后,使用 vmfile 的 merge 功能来重建索引和数据。
    • 在 merge 好后的文件夹上启动 vm-storage 来提供历史数据的查询服务;
    • 脚本进入循环睡眠,等到第二天半夜。
    • 根据当前日期,下载 n_days_before 指定的历史文件夹到本地
    • 使用 vmfile merge 数据
    • 启动新的 vm-storage
    • 停掉旧的 vm-storage

    具体代码请看:https://github.com/ahfuzhang/deploy_VictoriaMetrics_cluster/blob/main/terraform/historical_cluster/docker_image/daily_with_vmfile.sh

The End

  • vmfile 的功能还会继续优化,如果你们的团队也在使用 VictoriaMetrics ,欢迎关注我的后续进展;
  • vmfile 的实现代码很简单,但是原理却相对复杂,设计很多存储引擎的结构设计。如果对 vm-storage 的 tsdb 感兴趣,欢迎查看我分享的源码分析电子书:《VictoriaMetrics存储引擎分析.pdf》

Have fun. 希望对你有用。

【VictoriaMetrics的vmbackupmanager】这个一年卖 2 万美元的功能,我做出来了的更多相关文章

  1. 核心思想:早胜过一切,张小龙的Foxmail居然可以卖1200万

    现在谁都可以做一个类似的软件,但是市场已经成熟了,满大街都是,也就没有人会来收购你的软件了.

  2. 期权交易基本原理——买进看跌期权(Long Put),卖出看跌期权(Short Put)

    期权交易基本原理--买进看跌期权(Long Put),卖出看跌期权(Short Put) 来源:中电投先融期货-青岛 浏览:13508次2014-07-25 14:25:55 3 第三节 买进看跌期权 ...

  3. 想要风投被你的融资 PPT 打动吗?别忘了你其实就是在想方设法卖出自己公司的部分股权

      硅谷,一个常常见诸于报端,看着很熟悉,但是又不那么被人所了解的未及之地.它不是一个严格限定的地理位置,一般来说是指旧金山和湾区,其中湾区又分为东湾(East Bay)和南湾(South Bay), ...

  4. 程序员买房指南——LZ的三次买房和一次卖房经历

    引言 买房,一直是程序员群体绕不开的一个话题,尤其是到了一定年纪和人生阶段以后,买房这件事会变得越来越迫切. 为什么LZ一上来就说,买房是程序员绕不开的一个话题? 其实原因很简单,由于程序员这个职业的 ...

  5. 开源囧事4:你们这些卖代码的能不能留自己的QQ号?留我QQ号干嘛?

    缘起于开源项目 从 2017 年开始,陆陆续续写了一些开源项目放到开源网站里,都是一些实战项目,给大家练练手.有基础整合的demo,有 Spring Boot 博客项目,有 Spring Boot 商 ...

  6. Intel 推出 DPDK 开发包的意义是什么?

    Intel 推出 DPDK 开发包的意义是什么? http://www.zhihu.com/question/27413080?sort=created 基于intel dpdk的包处理器,相较于基于 ...

  7. 【转】JAVA自学之路

    JAVA自学之路 一: 学会选择 为了就业,不少同学参加各种各样的培训. 决心做软件的,大多数人选的是java,或是.net,也有一些选择了手机.嵌入式.游戏.3G.测试等. 那么究竟应该选择什么方向 ...

  8. 精通Web Analytics 2.0 (10) 第八章:竞争情报分析

    精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第八章:竞争情报分析 在现实世界中,收集竞争情报可能意味着雇人在竞争对手的垃圾桶(实际会发生!)翻找. 在虚拟世界中,堆如山的数 ...

  9. SQL Server 2016五大优势挖掘企业用户数据价值

    SQL Server 2016五大优势挖掘企业用户数据价值 转载自:http://soft.zdnet.com.cn/software_zone/2016/0318/3074442.shtml 3月1 ...

  10. 【商业源码】生日大放送-Newlife商业源码分享

    今天是农历六月二十三,是@大石头的生日,记得每年生日都会有很劲爆的重量级源码送出,今天Newlife群和论坛又一次疯狂了,吃水不忘挖井人,好的东西肯定要拿到博客园分享.Newlife组件信息: 论坛: ...

随机推荐

  1. 一文带你了解什么是GitOps

    摘要:说起GitOps,可能很多朋友马上会联想到DevOps,那么GitOps和DevOps之间有什么关系.又有什么区别呢? 本文分享自华为云社区<浅谈GitOps>,作者: 敏捷的小智. ...

  2. 火山引擎ByteHouse助力中国地震台网中心,快速构建一站式实时数仓

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,并进入官方交流群 近日,中国地震台网中心与火山引擎达成合作,双方将围绕 ByteHouse 实时数仓展开合作. 中国地震台网中心为中国地震局 ...

  3. 【eBPF-04】进阶:BCC 框架中 BPF 映射的应用 v2.0——尾调用

    这两天有空,继续更新一篇有关 eBPF BCC 框架尾调用的内容. eBPF 技术很新,能够参考的中文资料很少,而对于 BCC 框架而言,优秀的中文介绍和教程更是凤毛麟角.我尝试去网上检索有关尾调用的 ...

  4. 【主流技术】聊一聊 Redis 的基本结构和简单应用(一)

    目录 前言 一.String 类型 二.List 类型 三.Hash 类型 四.Set 结构 五.Sort Set (Zset)结构 六.文章小结 前言 Redis 是目前互联网后端的热门中间件之一, ...

  5. Java实现压缩文件浅谈

    背景: 在Java中,可以使用java.util.zip包提供的类来进行文件的压缩和解压缩操作.主要涉及的类有ZipOutputStream.ZipEntry.ZipInputStream和Infla ...

  6. AliPLC 智能丢包补偿算法,提升弱网环境的通话质量

    在线视频/语音通话逐渐成为人们日常生活的一部分,而复杂多变的网络环境会导致部分音频包无法传送到接收端,造成语音信号的短时中断或者卡顿,这会严重影响通话体验,为解决这类问题,阿里云视频云音频技术团队在综 ...

  7. 它来了!真正的 python 多线程

    哈喽大家好,我是咸鱼 几天前,IBM 工程师 Martin Heinz 发文表示 python 3.12 版本回引入"Per-Interpreter GIL",有了这个 Per-I ...

  8. #3038:How Many Answers Are Wrong (带权并查集)

    HDU 3038 第一次接触带权并查集 //带权并查集 更新父节点的同时更新权值 #include<bits/stdc++.h> using namespace std; const in ...

  9. POJ 1011 Sticks​ (DFS + 剪枝)

    题目地址:http://poj.org/problem?id=1011 题目大意 给出n个小木棒,组合成若干长度最短棍子 解题思路 首先将木棒从大到小排序 dfs(k, l), k是还剩多少木棒没用, ...

  10. 2012年第三届蓝桥杯【C++省赛B组】

    第一题:微生物增殖 假设有两种微生物 X 和 Y X出生后每隔3分钟分裂一次(数目加倍),Y出生后每隔2分钟分裂一次(数目加倍). 一个新出生的X,半分钟之后吃掉1个Y,并且,从此开始,每隔1分钟吃1 ...