“存储实现还要保证用于恢复的符号属于一致版本。RAID校验更新与写洞以更简单的单异或校验阵列展示:只更新一个数据块而校验未同步持久,随后重建竟会把未修改的A5算成96。这里并未推翻编码的擦除恢…”
条带与镜像理路磁盘条带与镜像的布局和故障集合RAID striping and mirroring · RAID 0 and RAID 10 · 条带与镜像从逻辑块号算出条带成员与盘内位置,比较四盘条带和成对镜像的容量,枚举哪些双盘故障可恢复,并单独说明部分持久写与重建读错。用完整副本恢复丢失成员。另一种办法是为一组数据加一条校验方程:少一块时用其余块算回来。困难在于,修改数据时也要修改方程;两块各自能原子写入,不代表跨盘的两次更新能一起持久。
形式陈述
三块数据加一块按位异或校验
四盘每一行放三个数据块
异或按块内同一位置的每一位执行。因为
这种按位关系可看成二元线性码理路线性码Linear code有限域向量空间中的线性子空间作为码字集合的信道码。的单校验约束。它可以恢复一处已知擦除;若两块数据都未知,通常只有它们异或值的一个方程,不能唯一确定二者。未知位置的静默错误和已知擦除不同,也不因多一块校验就自动可纠正。
本页采用自定、明确的轮转布局:每条带恰有3个逻辑数据块,成员盘内行号
更新必须维护同一行的方程
只将X改成
再写X′与P′。另一个办法是读未修改的Y、Z,与X′重新求校验。无论采用哪个算法,最终稳定条带都应满足新方程;算法算对P′只是其中一步,跨盘持久化次序仍需单独处理。
直觉
校验是约束,不是另一份完整数据
把数据项改动记成
轮转校验盘能避免每一行校验都压在同一个成员上。它没有增加每条带的独立方程数,也没有使跨成员写入变成一次原子操作。小写入成本与写洞是两个不同问题:前者数读写请求,后者检查掉电后哪些版本混在一起。
例子与边界
从布局到十六进制校验
逻辑块8满足
现在只看第0行:D0、D1、D2是数据,D3是校验。每个256字节块只有第一个字节使用下列值,其余255字节全为0,因而可以完整手算且不遗漏块内异或的含义。
把X改成 0F,则 C3 xor 3C xor 0F = F0。也可直接用 0F xor A5 xor 5A = F0 交叉核对。初始一致状态若丢失D1,C3 xor 3C xor 5A 恰好恢复 A5。
两读两写的计算口径
假设无缓存命中、条带健康且各请求不合并,单块读改写需要读旧X与P两次,再写X′与P′两次,共4次成员数据块I/O;flush命令和元数据未计入。若本次一次性提供整行3个新数据块,可以直接算新P,写4块,不需要读取旧内容。
一般一次修改
一次未完成写怎样伤到从未修改的Y
假设初始 3C,A5,5A,C3 已可靠持久,包含Y=A5的旧文件内容早已确认成功。此次只请求把D0改为 0F,并给D3写新校验 F0;不向D1或D2写任何数据。允许两次成员写独立持久,每块本身不撕裂。
掉电时,D0的新值 0F 已持久,D3仍保留旧校验 C3,D1、D2仍是原值 A5,5A。因此真实数据异或为 F0,盘上校验却是 C3。此时若未先修复条带一致性就丢失D1,例如掉电后阵列已降级启动,用幸存三块重建得到
本次对X的写可能尚未确认,允许它丢失并不能解释Y被改成 96:Y完全没被这次请求修改,且旧值已确认。写洞破坏的是更新中数据与校验的一致性,随后重建可把损害传播到未修改块。
| 掉电后D0 | 掉电后D3校验 | D1缺失时算得 | 与未改Y一致吗 |
|---|---|---|---|
旧 3C |
旧 C3 |
A5 |
是 |
新 0F |
旧 C3 |
96 |
否 |
旧 3C |
新 F0 |
96 |
否 |
新 0F |
新 F0 |
A5 |
是 |
只规定“先发数据写、再发校验写”还不够,设备可能重排持久顺序;即使中间做flush强制数据先持久,也仍保留新数据/旧校验的掉电窗口。需要能识别并修复跨代状态的协议,而不只是选一种下发顺序。
一次擦除保证不能覆盖额外读错
若D1已经丢失,重建又读不到D2,则这一行出现两个已知缺失,单校验不足。若D2静默返回错误值,重建公式会把这个错误混入Y,即便没有写洞也不能保证正确。静态单盘擦除、部分持久写、重建读取错误必须分别列出;不能用“RAID5能坏一盘”省略其余前提。
推论与应用
保护恢复信息,再动条带成员
一种教学修复可复用重做日志理路文件系统重做日志与提交边界Filesystem redo journal · Journaling filesystem commit把文件数据、位图、inode和目录组成有界块事务,证明payload、commit、home和清日志的稳定顺序及再次崩溃恢复。的after-image工具:先把新X和新P及目标成员地址记入可靠日志,持久提交日志后才修改成员;把两份成员更新都flush后,才清除日志。崩溃若留下已提交记录,幂等重做两份目标值,恢复一致的新行;未提交记录则不能伴随任何成员改写。
这个说明首先处理“掉电后日志仍可读、四个成员都可访问,并先完成恢复再接受后续失效”的模型。若掉电同时已有成员丢失,日志保存在哪里、能否随该盘一起丢失、如何在降级状态重做,都要另行证明。上层文件系统已经有日志,也不自动说明底层跨盘校验满足该协议;上层日志依赖的稳定逻辑块接口必须先由阵列兑现。
Linux MD的部分校验日志PPL针对另一种较窄目标:记录与未修改数据有关的恢复信息,避免不完整写入让未改块在降级恢复时损坏。它不把正在进行的用户数据写入变成完整事务,也不承诺保存所有未完成写。本例的未改部分异或为 A5 xor 5A = FF;额外保存这一约束与仅保留旧全行校验不是同一份信息,具体可恢复情形还取决于日志与失效盘位置。
复算终点应给出完整四格表、每次向哪些成员发了写、哪些值已经持久,以及恢复时哪些盘缺失。若只写一句“校验不一致”,读者还不能判断究竟损失了哪份此前正确的数据,也无法评价提出的恢复协议是否保护了它。
参考资料
- Arpaci-Dusseau与Arpaci-Dusseau,OSTEP, Ch.38,§38.6–38.7:按位校验、读改写、整条带写和轮转校验。本文十六进制数值、四格持久表与盘号函数为自定可复算实例。
- Patterson、Gibson与Katz,“A Case for Redundant Arrays of Inexpensive Disks (RAID)”,SIGMOD 1988, 109–116,Level 5与Figure 4:分布式校验和小写入背景。
- Linux内核文档,“Partial Parity Log”,查阅于2026-10-09:写洞对未修改数据的危害,以及PPL并非完整写日志的保护边界。