前沿 05-文件系统与存储 预计 25 分钟 kp-025

现代存储范式:COW 文件系统、LSM 树与对象存储

超越"原地更新 + 日志"的经典范式,现代存储走出三条路线:COW 文件系统(btrfs/ZFS)用永不原地写换取快照与校验和,LSM 树(LevelDB/RocksDB)用顺序写换取极致写吞吐,对象存储(S3/GFS/Dynamo)用扁平键空间与冗余副本服务海量数据。

学习状态:

一句话定义

超越"原地更新 + 日志"的经典范式,现代存储走出三条路线:COW 文件系统(btrfs/ZFS)用永不原地写换取快照与校验和,LSM 树(LevelDB/RocksDB)用顺序写换取极致写吞吐,对象存储(S3/GFS/Dynamo)用扁平键空间与冗余副本服务海量数据。

为什么重要

今天的数据库(RocksDB 引擎)、云存储(对象存储桶)、容器镜像(overlayfs 是 COW 思想)、甚至手机相册的"秒回退",全是这三条路线的工程化产物。它们共同的出发点是 kp-022 的介质事实(顺序远快于随机)与 kp-024 的可靠性纪律,是"文件系统设计"向"存储引擎设计"的演进。

前置知识

kp-023(日志与原地更新模型);kp-024(崩溃一致性)。

核心概念

  • COW(写时复制)文件系统:更新写新位置、改指针、旧版本保留——天然快照与校验和;代表 btrfs、ZFS、BtrFS 快照。
  • LSM 树:内存 memtable 排序累积 → 满了刷成不可变 SSTable → 后台分层/分层压缩合并,写全顺序。
  • Bloom filter:LSM 读路径的"可能存在"概率过滤器,避免逐层磁盘查找。
  • 写放大(write amplification):实际写入量/逻辑写入量,LSM 压缩的主要代价。
  • 对象存储:扁平命名空间(桶+键)、HTTP 语义、不可变对象、靠副本或纠删码保久度;GFS/Dynamo 是系统原型。
  • 纠删码(erasure coding):用 k+m 分片编码替代 3 副本,以计算换存储成本。

原理与机制

LSM 的读写路径:

写:  key -> WAL(保崩溃一致, kp-024) -> memtable(内存跳表) -> 满则冻结刷出 L0 SSTable
后台: L0 与 L1 合并去重 -> 下沉 L2/L3... (每层放大倍率固定, 顺序大块读写)
读:  memtable -> Bloom(L0..Ln) -> 逐层查找; 新版本覆盖旧版本
代价: 写放大典型 10~30x; 读放大靠 Bloom 压回 O(层级)
COW: 更新 -> 写新块+新元数据树 -> 原子切换根指针; 旧树即快照; 定期清理(碎片化来源)
对象: PUT/GET/DELETE 不可变对象 -> 网关机散布副本/分片 -> 一致性用仲裁或最终一致(Dynamo 风格)

三路线的取舍矩阵:

范式写读快照代表场景
原地更新+日志(ext4)中好贵通用
COW(ZFS/btrfs)中(易碎片)好廉价原生NAS/备份
LSM(RocksDB)极快中(Bloom 补偿)天然版本化写密集数据库
对象存储吞吐型低延迟差版本桶海量归档/云原生

图示

LSM: 写入 -> [WAL][memtable] --刷--> L0 ---合并---> L1 ---合并---> L2 ...
                                   (不可变SSTable, 越往下越老越大)

直观类比

LSM 像先往笔记本上乱序速记(memtable),页满就把这一页誊清归档(SSTable),定期把多页誊本合并成一本(compaction);查旧账先翻速记本,再从新到旧逐卷查,Bloom filter 像每卷书的目录提示"这卷肯定没有,跳过"。COW 像合同改版从不涂改原文,每次整份重印并在封面换新版号,旧版自动存档。

实例或案例

lsblk -f                            # 识别 btrfs/zfs 文件系统
btrfs subvolume snapshot / /snap0   # COW 秒级快照(实验环境)
btrfs filesystem df /               # 数据/元数据分配概况
sqlite3 test.db "PRAGMA journal_mode=WAL"   # 亲手把一个库切成 LSM 式日志思想
docker/podman inspect 镜像层数        # overlayfs 的 COW 层叠即镜像原理(连接 kp-029)

常见误区

  • 认为 LSM 读"慢到不可用":Bloom filter 与层级设计把典型读压到个位数次磁盘访问,读密集场景选 B+ 树、写密集选 LSM 是默认分野。
  • 认为 COW 没有碎片问题:反复小写会持续开辟新块,长期碎片化需要后台清理,ZFS 的写放大与 btrfs 的 balance 都源于此。
  • 把对象存储当低延迟块设备用:其延迟与计费模型都面向吞吐型访问,随机小 IO 场景是反模式。

与其他知识点的关系

COW 思想与 kp-007 的页级 COW 同源;LSM 的 WAL 严格执行 kp-024 的纪律;对象存储与容器镜像层叠连接 kp-029 的云原生世界。

延伸阅读

O'Neil 1996 LSM 原始论文;GFS(SOSP 2003)与 Dynamo(SOSP 2007)两篇开山之作;《数据密集型应用系统设计》第 3 章。

自测题

  1. LSM 树为什么写快?用什么弥补读?

答:写全部转化为顺序追加(日志+memtable 刷盘),避免随机原地更新;读靠 Bloom filter 快速排除不存在层、并用后台压缩降低层数。

  1. COW 文件系统的快照为什么几乎免费?

答:更新只写新块并生成新元数据树,旧树原封不动,快照只是"保留旧根指针",无数据复制。

  1. 对象存储与文件系统接口的本质差异?

答:扁平的桶+键命名空间与不可变对象、无目录层级与局部更新,只能整对象替换,换取近乎无限的横向扩展与高久度。

标签:#COW #LSM #对象存储 #ZFS #RocksDB #GFS