Skip to content

文件映射、磁盘冗余和历史恢复是三件事 ​

一个文件能分布到很多数据块,也能被复制到多块磁盘。访问并行度、磁盘故障容忍和误删恢复,需要分别设计。

文件系统把文件偏移映射到存储块;RAID 把逻辑块映射到多块设备;分布式文件系统又增加节点定位、副本与网络路径。叠加这些层次可以扩大容量和可用性,但不能直接推出读取速度或历史恢复能力。

本文以 ext4 的 extent 映射为入口,比较 RAID 与 HDFS 的责任边界。普通镜像文件的元数据访问已用 e2fsprogs 1.47.2-3+b12 验证;RAID 阵列、物理坏盘、重建和 HDFS 集群均未运行,相关结构与容量分析是文档依据和示意。

一、从文件偏移找到实际数据 ​

目录项把文件名关联到 inode。inode 描述文件类型、权限、大小等信息,也保存或指向数据映射。ext4 的 extent 用一段连续逻辑块对应一段物理块,避免把每个连续块都单独列出来;更大的映射可以组织成树。旧式间接块布局不能当成所有现代文件系统的统一模型。内核的 ext4 映射文档给出了两类结构。

文件名与偏移目录项 → inodeextent 映射逻辑块 → 设备块RAID 布局设备块 → 成员盘查询设备地址当前镜像 / 校验反映正常逻辑写入同一次修改早先的独立副本恢复历史内容,另验一致性与故障域更早时点保存冗余容忍成员故障;历史恢复还需要时间与保存策略
图 1 · 示意:inode 和 extent 定位文件系统块,下层 RAID 再映射成员设备;早先备份是另一条时间路径

图中每层的「块」具有自己的地址空间。inode 里的物理块号仍是文件系统看到的设备地址,设备下面还可能存在 RAID、逻辑卷或虚拟化。不能只看一条 extent 就判断数据最终落在哪块真实硬盘上。

配套实验在移除全部 capabilities、禁止网络的普通容器内,创建一个 64MiB 的文件作为 ext4 镜像,没有挂载、loop 设备或宿主机磁盘操作。写入 51,200 字节的演示文件后,debugfs stat 与 dumpe2fs -h 的输出摘录(Block size 来自后者):

text
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 0N × 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:

text
活动镜像:/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。


配套实验

参考资料

文章以 CC BY-NC-SA 4.0 授权 · 代码片段以 MIT 授权