文件映射、磁盘冗余和历史恢复是三件事
一个文件能分布到很多数据块,也能被复制到多块磁盘。访问并行度、磁盘故障容忍和误删恢复,需要分别设计。
文件系统把文件偏移映射到存储块;RAID 把逻辑块映射到多块设备;分布式文件系统又增加节点定位、副本与网络路径。叠加这些层次可以扩大容量和可用性,但不能直接推出读取速度或历史恢复能力。
本文以 ext4 的 extent 映射为入口,比较 RAID 与 HDFS 的责任边界。普通镜像文件的元数据访问已用 e2fsprogs 1.47.2-3+b12 验证;RAID 阵列、物理坏盘、重建和 HDFS 集群均未运行,相关结构与容量分析是文档依据和示意。
一、从文件偏移找到实际数据
目录项把文件名关联到 inode。inode 描述文件类型、权限、大小等信息,也保存或指向数据映射。ext4 的 extent 用一段连续逻辑块对应一段物理块,避免把每个连续块都单独列出来;更大的映射可以组织成树。旧式间接块布局不能当成所有现代文件系统的统一模型。内核的 ext4 映射文档给出了两类结构。
图中每层的「块」具有自己的地址空间。inode 里的物理块号仍是文件系统看到的设备地址,设备下面还可能存在 RAID、逻辑卷或虚拟化。不能只看一条 extent 就判断数据最终落在哪块真实硬盘上。
配套实验在移除全部 capabilities、禁止网络的普通容器内,创建一个 64MiB 的文件作为 ext4 镜像,没有挂载、loop 设备或宿主机磁盘操作。写入 51,200 字节的演示文件后,debugfs stat 与 dumpe2fs -h 的输出摘录(Block size 来自后者):
Size: 51200
Flags: 0x80000
Blockcount: 104
EXTENTS:
(0-12):2097-2109
Block size: 4096这里 13 个数据块覆盖逻辑块 0—12,映射到镜像里的连续块 2097—2109。13 × 4096 = 53,248 字节,足够容纳该文件;最后一块没有被文件内容填满。Blockcount 在这个输出里按 512 字节单位计数,104 × 512 同样是 53,248,不能当成 104 个 4KiB 块。st_blocks 计量单位可核对 Linux stat 文档。该位置是本次镜像的实际分配结果,不是跨环境保证。
脚本再把文件导出并按字节比较,验证内容一致。镜像离线编辑没有验证内核挂载后的缓存、日志恢复、并发写入或真实磁盘 I/O。对正在使用的文件系统,不应照抄 debugfs -w 修改;完整实验只操作它刚创建的临时镜像。
二、RAID 用容量和写入工作交换故障容忍
以下按 N 块等容量磁盘、每块容量 S、没有热备和其他保留空间来估算逻辑容量。实际产品的布局、最小盘数和元数据开销应另查文档。
| 级别 | 简化容量 | 整盘故障容忍 | 写入与恢复时要考虑什么 |
|---|---|---|---|
| RAID 0 | N × S | 不容忍成员盘丢失 | 条带化增加并行机会,成员缺失破坏阵列 |
| RAID 1,两盘镜像 | S | 一块 | 写入需更新镜像;读调度与实现有关 |
| RAID 5 | (N−1) × S | 一块 | 小范围更新可能需要读旧值和更新校验;重建读取其他成员 |
| RAID 6 | (N−2) × S | 两块 | 双校验增加写入与编码工作;重建仍消耗资源 |
| RAID 10,两副本镜像再条带化 | N/2 × S,N 为偶数 | 取决于坏盘落在哪个镜像组 | 同一镜像组全部丢失即损坏,不能概括成任意一半磁盘可坏 |
这些是布局模型,不是性能测试。读带宽取决于请求能否并行、设备和队列、条带尺寸、缓存、降级状态以及上层访问模式;RAID 5 的「数据盘数量」不能直接用作所有读写吞吐的倍数。Linux MD 的 RAID 行为与管理接口见内核文档。
以四盘 RAID 10 为示意,镜像组为 A/B 和 C/D:A、C 同时坏仍各有一个副本;A、B 同时坏则丢失一组数据。计数相同,故障分布不同。电源、控制器、机架和错误操作还会产生共同故障,单纯增加盘数没有隔离这些风险。
三、当前副本与过去版本要分开保存
文件系统删除目录项时,正常工作的镜像会反映同一次逻辑修改。两侧都保存最新状态,无法仅凭「有两份」恢复已经删除的旧文件。误写、勒索加密和应用错误也会按正常写入传播。
实验没有模拟 RAID。它先复制一份尚未修改的镜像文件,再从活动镜像删除 /record:
活动镜像:/record: File not found by ext2_lookup
独立的早先镜像:导出成功,内容与原文件相同这个结果只演示两个时间点的数据差异;复制普通文件不是在线一致性快照方案,也不证明有独立的故障域。备份还要考虑应用一致性、独立凭据、异地或离线保存、保留期,以及定期恢复验证。快照与原卷共享设备时,设备损坏可能同时影响两者。
因此应分开验收:成员设备坏了能否继续服务,以及错误逻辑写入之后能否恢复到指定时间。恢复点目标和恢复时间目标需要实际恢复流程支撑。
四、HDFS 把定位和传输放到不同路径
按 Hadoop 3.5.0 的架构,NameNode 管理命名空间和块位置,DataNode 保存块并提供数据读写。客户端获取位置后直接与 DataNode 传输数据,读取内容通常不经 NameNode 转发。HDFS 架构文档说明了这条元数据路径与数据路径。
副本为读取提供多个候选位置,还可跨故障域放置;数据量、块数和小文件数量则影响元数据规模。增加 DataNode 不会自动让一个客户端的每次读都并行,也不保证上层计算能充分利用本地性。
纠删码(Erasure Coding)用数据单元和校验单元交换存储开销与恢复成本。例如 HDFS 默认的 RS-6-3-1024k 策略是 6 个数据单元加 3 个校验单元,名义空间系数为 9/6;三副本模型是 3 倍。前者还需要编码、重建和跨节点读取,不能只比较系数。条带、文件大小、放置策略、可用节点和故障分布都影响选择,具体限制见 HDFS 纠删码文档。这里没有运行 HDFS,不能据此声称某种方案在本机更快。
估算遍历一个大文件,至少分别计算数据总量除以可持续读取带宽、网络传输能力和处理能力,再检查串行依赖与元数据成本。吞吐的来源、能否并行和故障状态没有说明,就不应给出「固定时间遍历任意规模文件」的承诺。分区、数据移动与计算执行的联系可继续读执行计划中的 shuffle。
配套实验
- codesphere-labs/system-design/filesystem-raid-boundaries:e2fsprogs 1.47.2:无特权、未挂载的 ext4 镜像;extent、Blockcount 单位、导出校验、删除与独立早先副本;未运行 RAID 或 HDFS(验证记录)
参考资料