本文整理单机文件系统的底层实现(FAT、inode、日志文件系统),并以 MySQL 索引说明 B 树/B+ 树的设计权衡,最后介绍分布式文件系统(HDFS/GFS)的抽象与读写模型。
硬盘读写不支持字节级随机存取,且速度远慢于内存(机械盘慢百万倍,SSD 慢数十到数百倍,NVMe 仍有差距)。为提升性能,物理存储被切分为等大的块(如 4KB),通过块序号即可计算物理位置,便于分配、回收与 DMA 批量传输。

文件分配表(File Allocation Table,FAT)用一个类似链表的结构描述文件对应的块。文件从某块开始,块中存放下一块的序号,序列以 -1 结束。

例:文件 1 的链为 5 → 2 → 9 → 14 → 15 → -1,对应块 {5,2,9,14,15}。FAT 算法简单,至今 Windows/Linux/macOS 仍支持。缺陷是 FAT 需整体驻留内存:1T 硬盘、1K 块需 1G 条目,叠加元数据需 2~3G 内存,容量扩展性差。
为每个文件增设 inode,仅在使用时随虚拟内存载入,包含文件属性与物理块位置;大文件通过指针块链式扩展。

相比 FAT,inode 只需为在用文件建立结构,随页表置换,解决了容量限制,沿用至今。
目录是特殊文件,每个目录有自己的 inode,目录内容存放其下文件的 inode 指针;文件名放在目录而非 inode 中,以支持别名与多目录共享(硬链接)。

ln a b)。ln -s a b);删除目标后链接失效但自身仍在。写入第 N 字节的典型步骤:修改内存数据 → 计算目标块 → 查 inode 定位真实块序号 → 整块写回磁盘。
传统实现每次写入都持久化,磁盘(尤其写)成为瓶颈,并易因写中断导致数据损坏或不一致。日志文件系统引入缓冲区 + 日志:
A=1 / A=2 / A=3),读时内存还原;为容灾,引入还原点(Checkpoint):每段时间日志写入一段连续块,写入中涂红、完成涂绿;读入时绿色应用、红色丢弃。区间越小风险粒度越细。

NTFS、Ext3/4 均为日志文件系统(Ext2 无日志)。该思想广泛用于分布式系统(MySQL binlog、Redis AOF、ZooKeeper 等)。
两者最终都落盘到块。
索引是"为加速查询而冗余维护的排序数据"。在数据量大到无法整树载入内存时,二叉搜索树每次下探都要读不同磁盘块,I/O 成本高。
B 树(B-Tree)让每个节点携带多个索引、子节点更多,树更矮,减少磁盘访问次数。节点内用分隔值对子树区间分段。

B+ 树继承自 B 树,仅叶子节点映射数据,非叶子节点为冗余索引(仅划定子树范围):

B+ 树优势:
B 树无冗余、删除根节点可能触发复杂变形,故实战多用 B+ 树。
Google File System(GFS)是分布式文件系统原型,HDFS 是其重要实现;BigTable 是构建于 GFS 之上的分布式数据库。搜索网页存储场景:行数固定但列不固定(外链数量不定、带版本),故采用 Key-Value(Map)模型,Key 为 <URL, 列族:列标识, 时间戳> 三元组。


读取某文件某 Chunk 某区间需两次往返:客户端 → Master(取 Chunk 地址与句柄)→ ChunkServer(取数据)。

先集中推送再统一更新,缩短不一致窗口。GFS/HDFS 牺牲强一致性(允许短时不一致)以换吞吐量。
HDFS 中 Secondary Node 类似客户端,定期将 NameNode 的变更日志与镜像合并,形成还原点(checkpoint);NameNode 故障时可据此恢复。