40. 存储系统与 RAID 原理

从存储层次与磁盘、SSD 的物理特性出发,讲清寻道与旋转延迟、FTL、写放大与磨损均衡,系统梳理 RAID 0/1/5/6/10 的数据布局与容错模型、奇偶校验与重建、写惩罚与写洞,并延伸到可靠性建模、4K 对齐、页缓存与块层存储栈,最后对比分布式存储的副本与纠删码并讨论 SSD 时代的 RAID 取舍。

1. 存储层次

1.1 金字塔结构

寄存器     <1ns      ~KB
L1/L2/L3  1~40ns    ~MB
DRAM      50~100ns  ~GB
SSD       10~100μs  ~TB
HDD       5~15ms    ~TB
磁带      秒级       ~PB

越往下容量越大、速度越慢、单位成本越低。存储系统的核心任务就是用层次结构把热数据放在上层。

1.2 局部性原理

  • 时间局部性:刚访问的数据很可能再次被访问 → 缓存。
  • 空间局部性:相邻数据很可能被一起访问 → 预读、块传输。

所有存储优化(缓存、预读、条带化)都建立在局部性之上。

1.3 关键指标

  • 吞吐量(bandwidth):每秒传多少 MB。
  • IOPS:每秒多少次 I/O 操作。
  • 延迟(latency):单次请求往返时间。

顺序 I/O 与随机 I/O 差距巨大:HDD 上随机比顺序慢百倍,SSD 上差距缩到 10 倍以内。

2. HDD 与 SSD 特性

2.1 机械硬盘的延迟构成

一次随机读的耗时:

总延迟 = 寻道时间 + 旋转延迟 + 传输时间
       ≈ 8ms     + 4ms(7200rpm 半圈) + 忽略
  • 寻道时间:磁头移动到目标磁道,是最大头。
  • 旋转延迟:等目标扇区转到磁头下,平均半圈。
  • 7200 RPM 转一圈 8.3ms,平均旋转延迟约 4.2ms。

结论:HDD 的瓶颈是机械动作,优化方向是减少寻道(顺序化、合并、预读)。

2.2 磁盘几何与寻址

  • 磁道(track)→ 柱面(cylinder)→ 扇区(sector)。
  • 传统扇区 512 字节,现代为 4KB(4Kn / 512e)。
  • 512e(512 模拟):物理 4K、逻辑报 512,写入未对齐会触发读改写(RMW)。

2.3 SSD 的内部结构

SSD 由**闪存颗粒 + 主控(controller)**组成:

  • 页(page):读写的最小单位,常见 4KB~16KB。
  • 块(block):擦除的最小单位,常见 256KB~几 MB。
  • FTL(Flash Translation Layer):把逻辑地址映射到物理页,是 SSD 的核心固件。

关键约束:闪存只能按页写、按块擦。改一个页要先擦整个块,于是产生写放大。

2.4 写放大与磨损均衡

写放大(WA) = 实际写入闪存的量 / 主机请求写入量。

  • 垃圾回收(GC):块内有效页搬走、整块擦除,搬迁过程产生额外写入。
  • TRIM:告诉 SSD 哪些块已删除,减少 GC 搬迁量。
  • 磨损均衡(wear leveling):动态与静态两种,把擦写均匀分散到所有块,避免个别块先坏。
fstrim -av                          # 手动 TRIM
cat /sys/block/nvme0n1/queue/discard_max_bytes
smartctl -a /dev/nvme0n1            # 查看磨损与健康

2.5 写放大与过度配置

企业级 SSD 通过 OP(over-provisioning,过度配置) 预留 7%~28% 空间给 GC,降低写放大、提升寿命与随机写性能。

3. RAID 基础概念

3.1 RAID 是什么

RAID(独立磁盘冗余阵列) 把多块磁盘组合成一块逻辑盘,目标是提升性能、容量或可靠性。注意它不是备份——它防的是磁盘故障,不防误删、勒索、机房事故。

3.2 三个基本技术

  • 条带化(striping):数据切块分散到多盘,提升吞吐。
  • 镜像(mirroring):数据写多份,提升可靠性。
  • 奇偶校验(parity):用 XOR 冗余,省空间地容错。

3.3 关键术语

术语含义
条带(stripe)跨盘的一组数据块
条带单元(chunk)单盘上的一块
条带宽度参与条带的盘数
条带大小单个 chunk 的大小,常见 64K~1M

4. RAID 0 与 RAID 1

4.1 RAID 0 条带化

数据交替写入各盘,无冗余。

Disk0: A1 A3 A5 ...
Disk1: A2 A4 A6 ...
  • 容量:100% 可用(N 盘即 N 倍)。
  • 性能:读写吞吐近似 N 倍,IOPS 也近 N 倍。
  • 可靠性:任意一盘的故障即全盘数据丢失,MTTF 反而降到单盘的 1/N。

RAID 0 只适合可重建的临时数据(缓存、渲染中间结果)。

4.2 RAID 1 镜像

数据完整写两份:

Disk0: A1 A2 A3 ...
Disk1: A1 A2 A3 ...(完全副本)
  • 容量:50%(N 盘可用 N/2)。
  • 读性能:可并行读多份,读吞吐近 N 倍。
  • 写性能:受最慢盘限制,约等于单盘。
  • 可靠性:可容忍 N/2 盘故障(且需故障分散在不同镜像对)。

RAID 1 适合系统盘、数据库日志盘等写少读多且要求低延迟的场景。

4.3 RAID 1 的读策略

读时可从任一副本读,控制器做负载均衡;若某盘寻道繁忙,可从另一盘读,提升随机读 IOPS。

5. RAID 5 与 RAID 6

5.1 RAID 5 单校验

数据与校验交替分布在所有盘上,校验块轮转:

Disk0: A1 A2 A3 P4
Disk1: A2 A3 P4 A1
Disk2: A3 P4 A1 A2
Disk3: P4 A1 A2 A3

校验用 XOR:P = A1 ⊕ A2 ⊕ A3。任一块可由其余块 XOR 还原。

  • 容量:(N-1)/N,N=4 时 75%。
  • 容错:仅容 1 盘故障。
  • 写性能:每次写要更新校验,产生读改写(见写惩罚)。

5.2 RAID 6 双校验

用两种独立校验(P 用 XOR,Q 用伽罗华域乘法),可容 2 盘同时故障:

P = A1 ⊕ A2 ⊕ A3
Q = g1·A1 ⊕ g2·A2 ⊕ g3·A3      (GF(2^8) 上的乘加)
  • 容量:(N-2)/N。
  • 容错:2 盘。大容量阵列(>8 盘)的必备,因为重建期间第二盘故障概率不低。

5.3 校验重建

替换故障盘后,控制器读其余盘对应块 XOR 出丢失数据。重建期间阵列降级运行,性能下降且再坏一盘即全毁——这就是重建窗口风险。

6. RAID 10 与组合级别

6.1 RAID 10

先镜像再条带(RAID 1+0):

Mirror Pair 0: Disk0 = Disk1
Mirror Pair 1: Disk2 = Disk3
  ↑ 两组之间做条带
  • 容量:50%。
  • 性能:读写均好,随机 IOPS 高。
  • 容错:每组镜像可坏一盘,容错能力取决于坏盘分布。
  • 重建快:只从镜像副本拷贝,无需读全阵列算校验,重建窗口远短于 RAID 5。

RAID 10 是数据库与高 IOPS 场景的首选,代价是 50% 容量。

6.2 RAID 01 与 RAID 10 的差别

RAID 01 是先条带再镜像。RAID 01 在特定坏盘组合下会整组失效(如两条带各坏一盘且落在同一镜像对),容错能力不如 RAID 10,因此生产环境一律用 RAID 10。

6.3 其他组合

  • RAID 50:条带 + RAID 5,兼顾容量与性能。
  • RAID 60:条带 + RAID 6,大容量高可靠。
  • JBOD:只是把盘串成一个大盘,无冗余无条带。

7. 写惩罚与写洞

7.1 RAID 5 写惩罚

修改一个小块需要:

① 读旧数据 D_old
② 读旧校验 P_old
③ 算新校验 P_new = P_old ⊕ D_old ⊕ D_new
④ 写新数据
⑤ 写新校验

一次逻辑写变成 2 读 2 写,即 写惩罚 = 4(RAID 6 为 6)。所以 RAID 5 的随机写 IOPS 约等于单盘 IOPS / 4。

对策:用全条带写(full-stripe write)——一次写满整个条带时,校验可由数据直接算出,无需读旧值,惩罚降为 1。

7.2 写洞(write hole)

断电时数据块与校验块可能不一致:数据已写、校验未写(或反之),此时若另一盘故障,重建出的数据是错的,且无法检测。这就是写洞。

对策:

  • UPS / 掉电保护:最简单有效。
  • 日志式 RAID(journaling):写数据前先把意图写日志,崩溃后重放。
  • 写意图位图(write-intent bitmap):只记录哪些区域待同步,重建时优先重算这些区域。

7.3 写惩罚与业务选型

级别随机写惩罚适用负载
RAID 01临时数据
RAID 1/101随机写密集(数据库)
RAID 54顺序读多、写少
RAID 66大容量归档

8. 可靠性建模

8.1 MTBF 与 AFR

  • MTBF(平均无故障时间):厂商标称值,消费盘约 50 万~100 万小时,企业盘 200 万小时。
  • AFR(年化故障率):AFR ≈ 8760 / MTBF。MTBF 100 万小时对应约 0.88%/年。

8.2 阵列故障率

N 盘 RAID 0 的 MTTF 降到单盘的 1/N。盘越多,阵列越脆弱——这是 RAID 5 在大容量阵列中失宠的根本原因。

8.3 重建窗口风险

重建一块 4TB 盘可能耗时 数小时到十几小时(受负载影响)。期间:

P(重建期间再坏一盘) ≈ AFR × 重建时长 / 年小时数

以 AFR 2%、重建 10 小时估算,单盘再坏概率约 0.023%;但若阵列有 12 盘,且重建要读所有盘(RAID 5),任一盘在窗口内故障即全毁,风险放大 11 倍。这就是 RAID 6 存在的理由。

8.4 为什么 RAID 不是备份

  • 不防误删、误格式化:删除会同步到所有盘。
  • 不防勒索软件:加密同样同步。
  • 不防控制器故障、机房灾难:需要异地副本。
  • 不防静默数据损坏:位翻转需校验和(如 ZFS 的 checksum)才能发现。

9. 条带化与对齐

9.1 4K 对齐

现代磁盘物理扇区 4KB。若分区起始未按 4KB 对齐,一个逻辑写会跨两个物理扇区,触发读改写,性能腰斩。

parted /dev/sda unit s print      # 检查起始扇区是否为 8 的倍数
parted -a optimal /dev/sda mkpart primary 0% 100%   # 自动对齐

9.2 条带大小选择

  • 小条带(16K~64K):适合大量小文件、随机读,负载分散到多盘。
  • 大条带(256K~1M):适合大文件顺序读写,减少跨盘次数。

条带大小应与文件系统块大小、业务 IO 大小匹配,错配会浪费带宽。

9.3 条带与文件系统的配合

文件系统块、RAID chunk、磁盘扇区三层若不对齐,每次 IO 都会跨边界。创建阵列时显式指定 chunk size,创建文件系统时指定 stride/stripe-width。

mdadm --create /dev/md0 --level=5 --raid-devices=4 \
      --chunk=64 /dev/sd[b-e]
mkfs.ext4 -E stride=16,stripe-width=48 /dev/md0

10. 存储栈与文件系统

10.1 Linux 存储栈

应用(read/write)
  → VFS(虚拟文件系统)
  → 具体文件系统(ext4/XFS/btrfs)
  → 页缓存(Page Cache)
  → 块层(Block Layer)+ IO 调度器
  → 设备驱动
  → 物理设备

10.2 页缓存

读:命中页缓存直接返回,未命中触发预读。
写:默认回写(write-back),先进页缓存标记脏页,由内核回刷线程异步落盘。

echo 3 > /proc/sys/vm/drop_caches   # 清页缓存(测试用)
vmstat 1                             # 观察 bi/bo 与缓存

风险:write-back 下断电会丢未回刷的脏页,数据库需 fsync 保证持久。

10.3 IO 调度器

调度器特点
none / noop不排序,适合 SSD、NVMe
mq-deadline多队列 + 截止时间,通用
BFQ按进程公平分配带宽,桌面友好

SSD 无需寻道优化,用 none 或 mq-deadline;HDD 用 mq-deadline 合并相邻请求。

10.4 写屏障与 FUA

fsync 触发 FLUSH 缓存刷新,确保数据真正落盘。文件系统的 journal(日志)保证元数据一致性,但数据一致性仍需 fsync。

11. 分布式存储的副本与纠删码

11.1 三副本

把每个数据块存 3 份到不同节点/机架:

  • 优点:读可并行、重建快(拷一份即可)、实现简单。
  • 缺点:存储开销 200%(3 份存 1 份数据)。

11.2 纠删码 EC

把数据切成 k 块,算出 m 块校验,共 k+m 块分布到不同节点:

k=10, m=4  →  可容 4 块丢失,存储开销 40%
  • 优点:存储效率远高于三副本,适合冷数据、归档。
  • 缺点:重建需读 k 块并解码,CPU 与网络开销大、重建慢;小文件场景不划算(需补齐块)。

11.3 副本与纠删码的取舍

维度三副本纠删码
存储开销200%40%~100%
重建成本低高
读延迟低需解码
适用热数据、低延迟冷数据、大文件

主流做法是分层:热数据三副本,冷数据转 EC,兼顾性能与成本。

12. SSD 时代的 RAID 取舍

12.1 传统 RAID 卡的问题

硬件 RAID 卡为 HDD 设计,对 SSD 有三大问题:

  • 写放大叠加:RAID 5 的读改写 + SSD 内部 GC,放大成倍。
  • 重建慢:重建要读全阵列,SSD 虽快但卡本身成瓶颈。
  • TRIM 透传:部分卡不支持 TRIM 透传给 SSD,加速磨损。

12.2 软 RAID 与 ZFS

  • mdadm:Linux 软件 RAID,灵活、无硬件依赖,性能已接近硬卡。
  • ZFS:文件系统与卷管理合一,端到端校验和防静默损坏,RAID-Z 系列用变宽条带 + 校验,无写洞(写时复制)。
  • btrfs:类似 ZFS,支持校验和与 RAID 1/10/5/6(5/6 稳定性曾受质疑)。

12.3 NVMe 时代的现实选择

  • 性能优先:RAID 10,重建快、无写惩罚,NVMe 的高 IOPS 才发挥得出来。
  • 容量优先 + 大阵列:RAID 6 或 RAID-Z2,容忍双盘故障。
  • 纠删码:分布式场景(Ceph、MinIO)用 EC 池,替代传统 RAID。
  • 单盘可靠性已很高:企业 NVMe 的 AFR 低,很多场景直接用副本或 EC 而非 RAID。

13. 常见陷阱

  • 把 RAID 当备份:RAID 只防盘坏,误删、勒索、火灾照样全丢,必须有离线与异地备份。
  • RAID 5 用在数据库:写惩罚 4 倍,随机写性能崩塌,数据库应上 RAID 10。
  • 大阵列用 RAID 5:重建窗口内再坏一盘即全毁,超过 8 盘务必用 RAID 6。
  • 分区未 4K 对齐:每次写触发读改写,性能腰斩,建分区时用 -a optimal。
  • 条带大小与负载不匹配:小条带配大文件顺序读会频繁跨盘,大条带配随机写会热点集中。
  • 忽略写洞:无掉电保护的 RAID 5/6 在崩溃后可能校验不一致,应配 UPS 或日志式 RAID。
  • SSD 上开 RAID 5 且不传 TRIM:写放大叠加,寿命与性能双输。
  • 用 SMART 只看温度:应关注重分配扇区数、待定扇区、磨损指示等关键属性。
  • 以为重建是后台无感:重建期间阵列降级、性能下降,业务高峰重建风险高。
  • 三副本存所有数据:冷数据也用三副本会浪费数倍成本,应按冷热分层。

参考文章

  • 文件系统与 IO — 页缓存、块层与调度器的实现细节
  • 操作系统体系结构 — 存储栈在操作系统中的位置
  • 分布式系统基础 — 副本、一致性与故障模型
  • 数据库原理 — WAL 与 fsync 在持久化中的角色
  • 虚拟化与容器原理 — 虚拟磁盘与存储直通

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「计算机基础」更多文章

  1. 46. 排队论与容量估算:利特尔法则与尾延迟
  2. 45. 编译器优化与中间表示:SSA、内联与循环优化
  3. 44. 并发模型对比:Actor、CSP 与数据并行