首页/新闻资讯/正文详情

VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 架构演进:从 TSDB 到 MergeSet 的设计取舍

发布时间:2026/9/27 21:37:29 来源:云帆数科 栏目:资讯中心
VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 架构演进:从 TSDB 到 MergeSet 的设计取舍
一、TSDB 存储引擎演进史思考记忆提示— 理解 TSDB 存储引擎的演进才能理解 MergeSet 为什么会这样设计第一代 TSDB基于 B-Tree如 InfluxDB 1.x第二代 TSDB基于 LSM Tree如 Prometheus 2.x、Cassandra第三代 TSDBMergeSetVictoriaMetrics独创面试高频提问MergeSet 和 LSM Tree 的核心区别是什么1.1 传统 TSDB 的存储架构在讨论 MergeSet 之前我们需要了解传统 TSDB 的存储架构。主流的 TSDB如 Prometheus 2.x采用LSM TreeLog-Structured Merge Tree作为底层存储引擎。LSM Tree 的核心思想是写入时数据先写入内存中的 MemTable类似 WAL达到阈值后刷盘生成 SSTable合并时多个 SSTable 按层次合并小表合并成大表这就是分层的概念查询时需要读取多个层次的 SSTable可能影响查询性能LSM Tree 架构 ┌─────────────────────────────────────────────────────────────────────────────┐ │ │ │ Level 0 (L0) │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ SSTable │ │ SSTable │ │ SSTable │ ← 新刷出的文件小而多 │ │ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ │ │ │ │ └───────────┴───────────┘ │ │ │ │ │ ▼ │ │ Level 1 (L1) │ │ ┌───────────────────────────┐ │ │ │ SSTable │ ← 合并后的文件较大 │ │ └─────────────┬─────────────┘ │ │ │ │ │ ▼ │ │ Level 2 (L2) │ │ ┌───────────────────────────┐ │ │ │ SSTable │ ← 更大 │ │ └─────────────┬─────────────┘ │ │ │ │ │ ▼ │ │ ... │ │ │ │ 问题查询需要遍历所有层级Level 越多查询越慢 │ └─────────────────────────────────────────────────────────────────────────────┘1.2 Prometheus TSDB 的局限性Prometheus 2.x 的 TSDB 基于 LSM Tree 设计虽然相比 1.x 版本有了巨大提升但在超大规模场景下仍面临挑战问题描述影响分层合并开销LSM Tree 需要多层合并Level 越多 IO 越重写入放大、写放大问题严重查询延迟不稳定查询需要遍历多个 Level数据分散P99 延迟难以控制内存占用高多层索引、BloomFilter 需要维护RAM 消耗大注意Prometheus 的 LSM Tree 实现与 Cassandra/RocksDB 有一定区别但核心问题类似。对于超大规模场景如 100 万 seriesLSM Tree 的分层合并策略会成为性能瓶颈。二、MergeSet 核心设计只合并不分层思考记忆提示— MergeSet 的精髓在于只合并不分层——这是它与 LSM Tree 的本质区别MergeSet 不分层所有 Part 文件在同一层级合并策略小型 Part 合并成大型 Part永远变大的单向合并设计优势查询只需扫描少量大文件IO 更高效2.1 MergeSet 的核心概念MergeSet 是 VictoriaMetrics 独创的存储架构其核心设计哲学可以用一句话概括只合并不分层。这与 LSM Tree 的分层合并形成鲜明对比。在 lib/mergeset/table.go 中MergeSet 的设计理念被清晰定义// lib/mergeset/table.go // MergeSet 核心设计只合并不分层 // MergeSet 与 LSM Tree 的本质区别 // - LSM Tree: 分层合并Level N 合并到 Level N1 // - MergeSet: 不分层所有 Part 文件在同一目录按大小合并 // Part 文件的生命周期 // InMemoryPart (新建) // ↓ (1秒后刷盘) // Small Part (小文件KB级别) // ↓ (合并) // Big Part (大文件MB级别) // ↓ (合并) // 更大的 Part // ↓ // 最终的超大 Part // 关键设计点 // 1. Part 文件永不删除只合并成更大的文件 // 2. 查询时扫描所有 Part但利用 BloomFilter 快速跳过无关 Part // 3. 后台任务持续合并小 Part 成大 Part保持 Part 数量可控2.2 MergeSet vs LSM Tree 对比MergeSet 架构VictoriaMetrics ┌─────────────────────────────────────────────────────────────────────────────┐ │ │ │ /data/ │ │ ├── 2024_01/ │ │ │ ├── small_001.tar / small_002.tar / small_003.tar ← 小文件合并中 │ │ │ ├── big_001.tar ← 大文件已稳定 │ │ │ ├── big_002.tar │ │ │ └── super_001.tar / super_002.tar ← 更大文件 │ │ │ │ │ ├── 2024_02/ ... │ │ └── 2024_03/ ... │ │ │ │ 特点 │ │ - 所有 Part 文件在同一目录层级 │ │ - 小文件持续合并成大文件单向合并 │ │ - 查询扫描所有 Part但用 BloomFilter 过滤 │ │ - IO 模式顺序读大文件而非随机读多层小文件 │ │ │ └─────────────────────────────────────────────────────────────────────────────┘维度LSM Tree (Prometheus)MergeSet (VictoriaMetrics)文件层级多层L0, L1, L2...单层所有 Part 在同级目录合并方向逐层向上合并小 Part → 大 Part单向查询方式遍历所有层级扫描所有 Part BloomFilterIO 模式大量小文件随机读少量大文件顺序读写放大严重多层重复写轻量只写一次查询延迟不稳定P99 难控制稳定可预测源码视角MergeSet 合并调度MergeSet 的合并调度逻辑在 lib/mergeset/table.go 的 scheduleMerges() 函数中实现默认配置defaultPartsToMerge15每次合并最多 15 个小 Part合并策略优先合并最老的小 Part避免大量小文件堆积并行合并通过 rawItemsShards 实现 CPU 级别的并行合并ZSTD 压缩合并时自动选择压缩级别getCompressLevel() 根据数据量动态选择三、源码解析MergeSet vs LSM Tree思考记忆提示— 源码是理解 MergeSet 设计取舍的最佳途径lib/mergeset/ 是 MergeSet 的核心实现lib/storage/ 中的 Table/Partition 对接 MergeSet面试高频提问MergeSet 为什么不需要 WAL3.1 InmemoryPart1秒刷盘的原子性保证MergeSet 不使用 WALWrite-Ahead Log而是通过InmemoryPart的原子性刷盘实现数据可靠性。这在 lib/mergeset/inmemory_part.go 中实现// lib/mergeset/inmemory_part.go // InmemoryPart 核心设计原子性刷盘 // 刷盘流程 // 1. 内存中构建完整的 Part 数据4 个 buffer 并行写入 // 2. 调用 MustStoreToDisk() 原子性刷盘 // 3. 刷盘成功后才更新目录索引 // MustStoreToDisk 的关键点 // - 先写临时文件如 small_001.tar.tmp // - 刷盘成功后原子性 rename 到正式文件名 // - 如果进程崩溃临时文件会被忽略不会污染数据 // 这就是为什么 MergeSet 不需要 WAL // - InmemoryPart 每秒刷盘数据最多丢失 1 秒 // - 刷盘后的数据已经是完整可用的 Part 文件 // - 重启时扫描目录即可恢复所有 Part3.2 Part 文件结构四文件合一MergeSet 的 Part 文件采用独特的四文件结构这在 lib/mergeset/part.go 中定义MergeSet Part 文件结构 ┌─────────────────────────────────────────────────────────────────────────────┐ │ │ │ Part.tar 文件内部结构 │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ metaindex.bin │ │ │ │ ├── [MetaIndexRow 1] ← Block 1 的元信息offset, size, min/max │ │ │ │ ├── [MetaIndexRow 2] ← Block 2 的元信息 │ │ │ │ └── [MetaIndexRow N] ← Block N 的元信息 │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ index.bin │ │ │ │ ├── [IndexRow 1] ← MetricName → BlockID 映射 │ │ │ │ ├── [IndexRow 2] │ │ │ │ └── [IndexRow N] │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ items.bin │ │ │ │ ├── [Item 1] ← 时序数据点Timestamp Value │ │ │ │ ├── [Item 2] │ │ │ │ └── [Item N] │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ lens.bin │ │ │ │ └── 每行的长度信息用于快速随机访问 │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ │ │ 关键设计点 │ │ - metaindex.binBlock 的索引用于快速定位数据 │ │ - index.binMetricName 倒排索引用于标签查询 │ │ - items.bin实际数据commonPrefix 压缩 │ │ - lens.bin行长度用于随机访问 │ │ │ └─────────────────────────────────────────────────────────────────────────────┘小贴士— 为什么 Part 文件是 .tar 格式.tar 格式最初用于将多个文件打包成一个便于传输。在 MergeSet 中.tar 格式用于将 metaindex、index、items、lens 四个文件打包成一个 Part。.tar 本身不压缩压缩发生在 items.bin 内部的 ZSTD 压缩。3.3 commonPrefix 压缩存储空间减少 30-50%MergeSet 的另一大优化是commonPrefix 压缩在 lib/mergeset/block_header.go 中实现// lib/mergeset/block_header.go // commonPrefix 压缩原理 // BlockHeader 结构 type BlockHeader struct { // commonPrefix 长度当前 Block 与前一个 Block 的公共前缀长度 CommonPrefixLen uint64 // 第一个 Item 的元信息 FirstItemMeta uint64 // 最后一个 Item 的元信息 LastItemMeta uint64 // Items 数量 ItemsCount uint64 // 压缩类型NearestDelta / ZSTD / None CompressionType uint64 } // 压缩示例 // 未压缩[2024-01-01 10:00:00] cpu_usage{jobprometheus,instancelocalhost:9090} 95.5 // 压缩后[2024-01-01 10:00:00] cpu_usage{jobprometheus,instancelocalhost:9090} 95.5 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 全部存储 // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ // 只存一次后面的 Block 只存差异 // 实际效果 // - 时序数据通常有很长的共同前缀标签名标签值模式固定 // - commonPrefix 压缩可以将存储空间减少 30-50% // - 同时保持解码速度不需要解压只需提取差异部分四、设计取舍与适用场景设计精髓MergeSet 的设计哲学是用空间换时间用简单换性能。放弃 WAL 换来的是写入的极致简单只合并不分层换来的是查询的可预测性。4.1 MergeSet 的优势优势原因实际效果写入简单不需要 WAL不需要复杂的两阶段写入写入延迟极低查询稳定扫描大文件而非多层小文件P99 延迟可控资源高效commonPrefix ZSTD 双重压缩存储空间减少 50%运维简单无分层无复杂合并策略调参少易理解4.2 MergeSet 的取舍取舍描述影响无 WAL进程崩溃可能丢失最多 1 秒数据不适用于数据零丢失的金融场景Part 数量膨胀高写入场景下小 Part 产生速度快于合并需要足够的 CPU 进行后台合并查询全扫描查询需要遍历所有 Part虽然有 BloomFilter超多 Part 时查询变慢4.3 适用场景对比VictoriaMetrics MergeSet vs Prometheus LSM Tree vs InfluxDB TSM ┌─────────────────────────────────────────────────────────────────────────────┐ │ │ │ 场景 │ Prometheus │ InfluxDB │ VM │ │ ─────────────────────────────────┼─────────────┼────────────┼────────────│ │ 超大规模 series (1000万) │ ⚠️ │ ⚠️ │ ✅ │ │ 高写入吞吐 (100万 samples/s) │ ⚠️ │ ⚠️ │ ✅ │ │ 稳定 P99 查询延迟 │ ⚠️ │ ⚠️ │ ✅ │ │ 低内存占用 │ ⚠️ │ ⚠️ │ ✅ │ │ 数据零丢失要求 │ ✅ │ ✅ │ ⚠️ │ │ 运维简单优先 │ ⚠️ │ ⚠️ │ ✅ │ │ 开源生态成熟 │ ✅ │ ⚠️ │ ⚠️ │ │ │ │ ✅ 强烈推荐 ⚠️ 可用但非最优 ❌ 不推荐 │ │ │ └─────────────────────────────────────────────────────────────────────────────┘五、面试高频提问

相关推荐

纳米无人机自主导航:技术挑战与轻量化解决方案
纳米无人机自主导航:技术挑战与轻量化解决方案

1. 纳米无人机自主导航的技术挑战与机遇 在无人机技术快速发展的今天,纳米级无人机(Nano-UAVs)正成为研究热点。这类重量不足50克、计算功耗低于100毫瓦的微型飞行器,正在重新定义自主导航的极限。与传统无人机不同,纳… · 2026/9/20 6:32:29

AI智能体开发实战:从角色定义到技术栈选型
AI智能体开发实战:从角色定义到技术栈选型

1. AI智能体开发概述 AI智能体(AI Agent)与传统AI模型最大的区别在于其自主决策和执行能力。就像给一个聪明但缺乏实践经验的大学生配备了一整套专业工具和操作手册,让它不仅能思考问题,还能实际动手解决问题。我在过去两年参与了… · 2026/9/16 17:23:56

基于Si4732与MK60的高保真收音机系统设计
基于Si4732与MK60的高保真收音机系统设计

1. 项目背景与核心目标 在数字音频设备泛滥的今天,传统AM/FM收音机系统依然保持着独特的生命力。这个项目基于Si4732数字信号处理收音机芯片与MK60DN512VLQ10微控制器的组合,旨在打造一套超越普通消费级收音机性能的高保真接收系统。不同于市面上常见的&… · 2026/7/25 1:42:12

TypeScript 7 原生语言服务“转到实现”内存修复:从 O(K²) 爆炸到近似线性增长
TypeScript 7 原生语言服务“转到实现”内存修复:从 O(K²) 爆炸到近似线性增长

文档教程 【免费下载链接】typescript-book The Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source. 项目地址: https://gitcode.com/gh_mirrors/typ/typescript-book 点击查看 免费下载 2026 年 7 月 30 日… · 2026/9/27 21:37:28

isomorphic-git readNote 详解:在 Node 与浏览器中读取 Git Note 注释内容
isomorphic-git readNote 详解:在 Node 与浏览器中读取 Git Note 注释内容

开发工具 【免费下载链接】isomorphic-git A pure JavaScript implementation of git for node and browsers! 项目地址: https://gitcode.com/gh_mirrors/is/isomorphic-git 点击查看 免费下载 readNote 是 isomorphic-git 提供的用于读取 Git Note(对… · 2026/9/27 21:37:28

Claude Code源码学习之上下文压缩(Compact):从触发条件到配置骨架
Claude Code源码学习之上下文压缩(Compact):从触发条件到配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 21:37:28

安装wordpress注意什么意思最佳实践
安装wordpress注意什么意思最佳实践

新手装WordPress踩坑?3个配置细节对比评测帮你搞定服务器 域名服务器搞不懂?别慌,这确实是新手转行建站最头疼的坑。 很多人以为买个域名、租个服务器就能开工,结果一动手就卡壳。… · 2026/9/27 21:37:22

零后端硬改!LightRAG二次开发全局顶部导航,无缝对接自研第三方业务系统
零后端硬改!LightRAG二次开发全局顶部导航,无缝对接自研第三方业务系统

博主深耕AI本地部署、RAG工程化落地、开源框架二次开发运维实操,专注轻量化智能检索平台私有化适配改造,全程落地可复现,无冗余理论踩坑干货,适配政企内网自研业务全场景集成需求。 📌 写在前面:为什么一定要改 LightRAG 顶部 Header? 很多政企、园区、事业单位技术团… · 2026/9/27 21:37:22

树和二叉树的应用(哈喜老师)
树和二叉树的应用(哈喜老师)

1.哈夫曼树(也称为赫夫曼树)(重点) 1.1:一些与树相关的概念1.2:哈夫曼树的概念1.3:哈夫曼树的构造1.4:哈夫曼树的性质习题1(易)习题2(题目简单,但是问法很新颖)习题3(易错… · 2026/9/27 21:37:22

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码