想象一座建在地下的环形图书馆:一层层盘片就是楼层,每层上下两面都摆满书架;从圆心向外一圈圈排开的书架叫“磁道”,书架上等分的格子叫“扇区”,不同楼层垂直对齐的那一圈格子合起来叫“柱面”。取书管理员(磁头)要先把小车移到对应半径(寻道),等环形书架转到面前(旋转),才能抽出书(传输)。单馆藏书再多也怕火灾,于是人们把多座图书馆组织起来协作:把书拆开分馆存(条带化)、两馆各存一本(镜像)、让某个馆记“总账本”(校验),这套多馆协作策略就是 RAID。本文从这座环形图书馆出发,讲清磁盘的物理结构、性能指标,以及 RAID 0 到 RAID 6 的数据分布与取舍逻辑。

岗位关联

理解磁盘结构与 RAID 级别,是存储选型、数据库性能调优和高可用架构设计的基本功,直接决定线上系统的数据安全与吞吐表现。

目录
  1. 可视化演示
  2. 磁盘物理构造:环形图书馆的楼层与书架
  3. 磁盘性能指标:取书的三大时间账单
  4. RAID 设计思想:多馆协作的三件法宝
  5. RAID 0 与 RAID 1:极致速度 vs 双保险
  6. RAID 5 与 RAID 6:记账员与双保险账本
  7. RAID 10:先镜像再条带的黄金组合
  8. 条带大小的权衡:拆书拆多碎最合适?
  9. 选型与工程实践:给每种业务挑合适的图书馆联盟
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。

本节配有交互动效(进入视口后自动加载,约 3KB)。

系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T

磁盘物理构造:环形图书馆的楼层与书架

想象你走进一座建在地下的环形图书馆:每一层楼都像一个巨大的光盘,上下两面都摆满了书架。从圆心向外,书架一圈一圈排开,这些同心圆书架叫“磁道”;每条磁道被隔成等大的格子,每格是一个“扇区”;而不同楼层圆心距相同的那一圈书架垂直叠起来,叫“柱面”。馆里的取书小车(磁头)悬在书架上方,负责把书(数据)拿起放下。

这座“图书馆”就是机械硬盘。盘片是铝合金或玻璃圆盘,正反两面都涂着磁性材料,所以一片盘片有两个记录面,每个记录面配一个磁头。数据不是连续铺满盘面的,而是按“磁道-扇区”寻址:控制器说“第 3 面、第 500 磁道、第 12 扇区”,磁头就知道该去哪一格取放。

磁道从外圈向内圈编号。传统磁盘每条磁道扇区数相同,导致内圈线密度过高;现代磁盘采用等位密度(ZBR 分区位记录)把外圈切成更多扇区,容量随之增大。扇区是读写的最小单元,传统为 512 字节,大容量盘升级为 4096 字节(高级格式化)。整盘容量就是把所有参数乘起来:

知道了图书馆有几层楼、每层几圈书架、每圈几格书,就能算出它总共能装多少本书。盘片数、磁道数、扇区数、扇区字节数四者相乘,就是磁盘容量的全部秘密,也是做存储容量规划时最先要算清的一笔账。

磁盘容量=盘片数×2×每面磁道数×每磁道扇区数×每扇区字节数\displaystyle \text{磁盘容量} = \text{盘片数} \times 2 \times \text{每面磁道数} \times \text{每磁道扇区数} \times \text{每扇区字节数}
公式说明:四个结构参数相乘即总容量——楼层数翻倍(双面)、每层书架圈数、每圈格子数、每格可装字节数,缺一不可。
  1. 盘片数与双面每片盘片的上下两个表面都能记录数据,总记录面数为盘片数的两倍。
    总记录面数=盘片数×2\text{总记录面数} = \text{盘片数} \times 2
  2. 每面磁道数每个记录面从外圈到内圈划分出若干圈同心圆磁道。
    每面磁道数\text{每面磁道数}
  3. 每磁道扇区数每条磁道等分为若干扇区,扇区是寻址与读写的最小单元。
    每磁道扇区数\text{每磁道扇区数}
  4. 每扇区字节数传统扇区为 512 B,大容量盘普遍采用 4 KB 高级格式化。
    每扇区字节数=512 B 或 4096 B\text{每扇区字节数} = 512\ \text{B 或 } 4096\ \text{B}

磁盘性能指标:取书的三大时间账单

取书要三步:小车沿轨道横移到目标半径(寻道);等待环形书架转到小车正下方(旋转);把书抽出来送到出口(传输)。每一次取书的体验,是这三步时间之和,缺一不可。

对应到磁盘上就是寻道时间、旋转延迟、传输时间。寻道时间由磁头臂的机械移动决定,一般在 3~15 ms,是三笔账里的大头;旋转延迟取决于转速,7200 转/分的硬盘转一圈要 8.33 ms,平均等半圈约 4.2 ms;传输时间与读的数据量和盘面传输率有关,通常最短。三者相加就是一次随机 IO 的响应时间。

随机读场景下,每秒能完成的 IO 次数(IOPS)约等于 1/(寻道时间+旋转延迟)。顺序读时寻道和旋转只发生一次,之后就是连续数据流,吞吐(带宽)远高于随机读——这也是数据库把日志设计成顺序写的原因。

管理员最怕“满场乱跑”的取书请求;一次把一整排书搬走(顺序读)远比一次取一格(随机读)高效。磁盘性能优化的本质,就是尽量把随机访问转化为顺序访问——日志合并、预读、批量刷盘都是这个思路。

T存取=T寻道+T旋转+T传输\displaystyle T_{\text{存取}} = T_{\text{寻道}} + T_{\text{旋转}} + T_{\text{传输}}
T旋转=12×转速(转/秒)\displaystyle T_{\text{旋转}} = \frac{1}{2 \times \text{转速(转/秒)}}
公式说明:一次 IO 的响应时间等于“横移定位 + 等半圈 + 搬数据”三项之和;顺序读能摊薄前两项,所以快得多。
  1. 寻道时间磁头臂径向移动定位目标磁道,机械动作决定了它最耗时,典型 3~15 ms。
    T寻道T_{\text{寻道}}
  2. 旋转延迟盘片转到目标扇区所需时间,平均取转一圈时间的一半。
    T旋转=12×转速(转/秒)T_{\text{旋转}} = \frac{1}{2 \times \text{转速(转/秒)}}
  3. 传输时间数据从盘面读出并送到接口的时间,与块大小成正比、与传输率成反比。
    T传输=S数据v传输率T_{\text{传输}} = \frac{S_{\text{数据}}}{v_{\text{传输率}}}
  4. 三者求和一次随机 IO 的响应时间基本等于三者和,顺序读只需付一次寻道与旋转。
    T存取=T寻道+T旋转+T传输T_{\text{存取}} = T_{\text{寻道}} + T_{\text{旋转}} + T_{\text{传输}}

RAID 设计思想:多馆协作的三件法宝

单馆藏书再多也怕火灾。于是人们把几座图书馆联合起来,靠三件法宝应对灾难:把一本书拆成多份分馆存(条带化);两馆各存一本一模一样的(镜像);让某个馆额外记一本“总账”(校验),账本和书放在一起,任何一馆被烧,都能用剩下的书和账本反推出烧掉的内容。

这三件法宝就是 RAID 的核心机制。RAID(Redundant Array of Independent Disks,独立磁盘冗余阵列)由一个阵列控制器管理多块物理盘,对外表现为一块逻辑盘。它不改变单块盘的物理结构,而是靠“分布式存放 + 冗余信息”同时改善性能与可靠性。

条带化把连续数据切成小块轮流写到各盘,让多盘并行读写,吞吐几乎线性增长;镜像把同一份数据写两份,可靠性翻倍但容量减半;校验用异或(XOR)等算法生成冗余块,用少量额外容量换取可恢复性。三者可自由组合出不同级别,阵列还常配热备盘,故障后自动顶替并重建数据。所有级别都可以用下面这个式子统一描述可用容量:

三件法宝就像合作的三种契约:拆书提高效率但牺牲保险,抄书最保险但费书架,记账则用最小的书架成本换回大部分安全感。RAID 级别的差异,就是这三件法宝的不同组合方式。

C可用=(N−k校验)×C单盘\displaystyle C_{\text{可用}} = (N - k_{\text{校验}}) \times C_{\text{单盘}}
公式说明:N 块盘中,被镜像或校验“占掉”的等效盘数为 k,剩下的盘才真正用来存用户数据。
  1. 物理盘总数 N阵列由 N 块同规格磁盘组成,N 越大并行能力越强,但故障面也越大。
    NN
  2. 校验等效盘数 k被镜像或校验占用的盘数:RAID 0 为 0,RAID 5 为 1,RAID 6 为 2,RAID 1/10 为 N/2。
    k=0(RAID 0),k=1(RAID 5),k=2(RAID 6)k = 0 \text{(RAID 0)}, \quad k = 1 \text{(RAID 5)}, \quad k = 2 \text{(RAID 6)}
  3. 可用盘数用总盘数减去冗余开销,得到真正存放用户数据的盘数。
    N−kN - k
  4. 乘以单盘容量用可用盘数乘单盘容量,即得阵列的可用容量。
    C可用=(N−k)×C单盘C_{\text{可用}} = (N - k) \times C_{\text{单盘}}

RAID 0 与 RAID 1:极致速度 vs 双保险

RAID 0 像“拆书分馆”:一本书拆成 N 份分给 N 馆,取书时 N 馆同时开工,快,但任何一馆失火整本书就没了。RAID 1 像“各备一本”:两馆各存全书,一馆烧了另一馆照常出借,但书架利用率只有一半。

RAID 0 是最纯粹的条带化。它把数据切成固定大小的块(chunk),交替写到所有磁盘上。N 块盘的理论读写带宽接近单盘的 N 倍,空间利用率 100%。但它没有任何冗余,任何一块盘损坏,整个阵列数据全部丢失,可靠性还随盘数增加而下降。

RAID 1 是最纯粹的镜像。盘必须成对出现,每对盘写相同内容。写入要写两份,写性能不升反有额外开销;读取则可从两块盘并行分流,读性能提升。空间利用率恒为 50%,允许任意一块盘损坏,常用来放系统盘、日志盘等小容量高可靠数据。

一个是“快但脆弱”的团队,一个是“稳但浪费”的搭档。选 RAID 0 还是 RAID 1,本质是在问:这份数据丢了,重新生成它要多久?答案越昂贵,越该选镜像。

CRAID0=N×C单盘,CRAID1=N2×C单盘\displaystyle C_{\text{RAID0}} = N \times C_{\text{单盘}}, \qquad C_{\text{RAID1}} = \frac{N}{2} \times C_{\text{单盘}}
公式说明:RAID 0 每块盘都存数据,容量全用;RAID 1 盘必须成对,每对只贡献一块盘的容量。
  1. RAID 0 容量N 块盘全部存放用户数据,毫无冗余,可用容量等于全部盘容量之和。
    CRAID0=N×C单盘C_{\text{RAID0}} = N \times C_{\text{单盘}}
  2. RAID 1 容量盘必须成对,每对只贡献一块盘的容量,故除以 2。
    CRAID1=N2×C单盘C_{\text{RAID1}} = \frac{N}{2} \times C_{\text{单盘}}
  3. 可靠性格局RAID 0 任坏一盘即全损;RAID 1 每对可坏一块。
    RAID 0: 0 次容错,RAID 1: 每对 1 次容错\text{RAID 0: 0 次容错}, \qquad \text{RAID 1: 每对 1 次容错}
  4. 读写差异RAID 0 读写均并行加速;RAID 1 写要写两份、读可从双盘分流。
    RAID 0: 读↑ 写↑,RAID 1: 读↑ 写翻倍\text{RAID 0: } 读\uparrow\ 写\uparrow, \qquad \text{RAID 1: } 读\uparrow\ 写\text{翻倍}

RAID 5 与 RAID 6:记账员与双保险账本

RAID 5 的馆联盟请了一位“记账员”:每批书里有一本不是原文,而是用所有书按位异或算出的“总账本”,账本轮流由不同馆保管,谁也别想垄断。任何一馆失火,其余馆把书和账本异或一遍,被烧的书就能还原。RAID 6 则是请了两位记账员,各用一套算法记账,允许同时烧两馆。

RAID 5 把校验块分散到所有磁盘,每一条带(stripe)由 N-1 个数据块和 1 个校验块组成,校验盘位置逐条带轮转,避免专用校验盘成为瓶颈。它至少需要 3 块盘,允许任意 1 块盘损坏,空间利用率为 (N-1)/N,盘越多容量损失占比越小。

RAID 6 每条带有 2 个校验块:P 用异或生成,Q 用里德-所罗门(Reed-Solomon)编码在伽罗华域上构造,相当于解两个未知数,因此允许任意 2 块盘同时损坏,空间利用率为 (N-2)/N。代价是写开销更大:RAID 5 改写一个小块需要“读旧数据、读旧校验、写新数据、写新校验”共 4 次 I/O,RAID 6 则要 6 次,随机小写吞吐明显下降。

记账员越多账房越安全,但每次存取书的流程也越长。RAID 5/6 适合“大块数据往里搬、偶尔取整批”的容量型业务,比如文件存储和备份。

P=D1⊕D2⊕⋯⊕Dm\displaystyle P = D_1 \oplus D_2 \oplus \cdots \oplus D_m
小写 I/O 代价:RAID 5=4,RAID 6=6\displaystyle \text{小写 I/O 代价}: \text{RAID 5} = 4, \quad \text{RAID 6} = 6
公式说明:异或校验块等于所有数据块逐位异或;丢失任意一块时,把剩余块再异或一遍即可还原。改写一个小块要付出 4 或 6 次底层 I/O 的“记账手续费”。
  1. 异或校验同一条带中所有数据块逐位异或,得到校验块 P。
    P=D1⊕D2⊕⋯⊕DmP = D_1 \oplus D_2 \oplus \cdots \oplus D_m
  2. 恢复丢失块任一块盘损坏时,把其余数据块与校验块再异或一次,即还原丢失数据。
    D丢失=P⊕D1⊕⋯⊕Dm−1D_{\text{丢失}} = P \oplus D_1 \oplus \cdots \oplus D_{m-1}
  3. 校验盘轮转各条带校验盘位置循环移动,避免单个校验盘成为写入瓶颈。
    P 所在盘=条带号 mod NP\text{ 所在盘} = \text{条带号} \bmod N
  4. 小写惩罚改写一个小块需读旧数据、读旧校验、写新数据、写新校验;RAID 6 多一组校验,翻到 6 次。
    小写 I/O 代价:RAID 5=4,RAID 6=6\text{小写 I/O 代价}: \text{RAID 5} = 4, \quad \text{RAID 6} = 6

RAID 10:先镜像再条带的黄金组合

RAID 10 像这样组织四座图书馆:先两两配对,每对互为备份(镜像),再把两对之间拆书分馆(条带化)。借书时两对同时开工,比单镜像快;任何一馆被烧,它的同伴立刻顶上;就算两馆同时被烧,只要不是同一对里烧两个,书依然完整。

RAID 10(RAID 1+0)先做镜像、后做条带。以 4 块盘为例:盘 0/盘 1 一组镜像,盘 2/盘 3 一组镜像,数据在两组之间条带化。它兼具镜像的可靠性与条带的并行度,成为数据库等随机小写密集场景的默认选择。

容错上限是每组镜像恰好坏一块——N 块盘最多可坏 N/2 块,但同一镜像组内不能坏两块。重建时只需从组内幸存盘整块拷贝,无需读全条带算异或,重建速度快、对性能冲击小。缺点是空间利用率恒为 50%,成本较高。与之相对的 RAID 01(先条带后镜像)容错差,已基本被淘汰。

RAID 10 是“又稳又快但不便宜”的豪华方案。只要预算允许、数据金贵,它几乎总是比 RAID 5/6 更让人安心的选择。

CRAID10=N2×C单盘,可坏盘数=N2 (每组至多 1 块)\displaystyle C_{\text{RAID10}} = \frac{N}{2} \times C_{\text{单盘}}, \qquad \text{可坏盘数} = \frac{N}{2}\ (\text{每组至多 1 块})
公式说明:每对镜像只贡献一块盘容量;容错上限为 N/2 块,但有“每组至多一块”的约束。
  1. 先镜像后条带盘先两两成组镜像,组间再条带化,顺序不可颠倒。
    RAID 10=镜像(RAID 1)+条带(RAID 0)\text{RAID 10} = \text{镜像(RAID 1)} + \text{条带(RAID 0)}
  2. 可用容量每组镜像只提供一块盘的容量,故总容量为 N/2。
    CRAID10=N2×C单盘C_{\text{RAID10}} = \frac{N}{2} \times C_{\text{单盘}}
  3. 容错上限最多可坏 N/2 块,但同一镜像组内不能坏两块。
    可坏盘数=N2 (每组至多 1 块)\text{可坏盘数} = \frac{N}{2}\ (\text{每组至多 1 块})
  4. 重建方式直接从组内幸存盘整块复制,无需读全条带算校验,速度快冲击小。
    重建=纯拷贝,无校验计算\text{重建} = \text{纯拷贝,无校验计算}

条带大小的权衡:拆书拆多碎最合适?

拆书也有学问。拆成 100 页一本的大册子,动辄搬重书、单馆出力;拆成 10 页一本的小册子,借阅时可让多馆各递几本,但管理员要频繁拼装、来回跑。

条带大小(chunk size,常见 16KB~1MB)决定了一次请求会跨越多少块盘。设请求大小为 \(S_{\text{请求}}\),条带为 \(S_{\text{条带}}\),则跨盘数 \(m = \lceil S_{\text{请求}} / S_{\text{条带}} \rceil\)。m 越大,参与并行传输的盘越多,顺序大块读的吞吐越高;但要是一次请求本身就很小,跨盘数等于 1,并行使不上力,还要付出跨盘拼接的控制器开销。

因此没有绝对最优的条带大小。时延敏感的小块随机请求(如数据库页 4KB、8KB),偏好较小条带,让每次请求落在更少的盘、减少等待;吞吐敏感的大块顺序请求(如日志、备份),偏好较大条带或让请求自然横跨多盘。还要注意条带与文件系统块、数据库页对齐,避免一个逻辑块被切碎到两盘造成额外读写。

拆书的粒度要匹配读者习惯:借多人传阅的畅销书拆薄点,整批搬运的档案册拆厚点。RAID 调优同理,先看清负载是大块顺序还是小块随机,再定条带大小。

m跨盘数=⌈S请求S条带⌉\displaystyle m_{\text{跨盘数}} = \left\lceil \frac{S_{\text{请求}}}{S_{\text{条带}}} \right\rceil
公式说明:一次请求被切成多少块落到不同盘上,向上取整。请求远小于条带时 m=1,等于让单块盘单打独斗。
  1. 请求大小应用单次读写的数据量,数据库页、文件系统块决定了它。
    S请求S_{\text{请求}}
  2. 条带大小RAID 控制器切分数据、轮流写入各盘的基本块大小。
    S条带S_{\text{条带}}
  3. 跨盘数一次请求被切成多少块落到不同盘上,向上取整。
    m=⌈S请求S条带⌉m = \left\lceil \frac{S_{\text{请求}}}{S_{\text{条带}}} \right\rceil
  4. 权衡m 越大并行越足但拼接开销越大;m=1 时请求仅由单盘服务,无并行收益。
    m=1⇒单盘承担,m>1⇒多盘并行m = 1 \Rightarrow \text{单盘承担}, \quad m > 1 \Rightarrow \text{多盘并行}

选型与工程实践:给每种业务挑合适的图书馆联盟

建图书馆联盟前,馆长会算三笔账:每块书架能装多少书、多少书架要被账本和副本占掉、灾后重建要多长时间。不同业务对这三者的优先级完全不同,选型就是在这三笔账之间权衡。

空间利用率 \(\eta\) = 可用容量 / 总容量:RAID 0 为 100%,RAID 1/10 恒为 50%,RAID 5 为 (N-1)/N,RAID 6 为 (N-2)/N。重建开销上,RAID 1/10 是纯拷贝最快,RAID 5/6 需要读全条带再异或/解算,重建慢,期间读性能下降、写惩罚加倍,坏第二块盘的风险显著上升。

大容量盘时代(单盘 16TB 以上),RAID 5 重建时间长达数十小时,期间遭遇不可恢复读错误(URE)导致重建失败的概率不容忽视,这也是主流存储逐渐转向 RAID 6/RAID 10 或分布式纠删码的原因。选型参考:数据库在线事务(随机小写)→ RAID 10;文件共享、视频监控、备份(顺序大块)→ RAID 5/6;缓存、临时计算(可重建、要速度)→ RAID 0。热备盘能缩短故障窗口,但不能替代备份。

没有最好的 RAID,只有最匹配业务的 RAID。把书架账、重建账、速度账三本账摆在一起,选型自然水落石出——这也是存储工程师最重要的日常判断。

η=C可用N×C单盘=N−k校验N\displaystyle \eta = \frac{C_{\text{可用}}}{N \times C_{\text{单盘}}} = \frac{N - k_{\text{校验}}}{N}
公式说明:空间利用率统一为“可用盘数 ÷ 总盘数”。代入不同 k,就得到各级别的容量账。
  1. 空间利用率可用容量除以物理总容量。
    η=C可用N×C单盘\eta = \frac{C_{\text{可用}}}{N \times C_{\text{单盘}}}
  2. 代入公式RAID 0 无冗余利用率 1;RAID 1/10 恒为 1/2;RAID 5 为 (N-1)/N;RAID 6 为 (N-2)/N。
    η=N−k校验N\eta = \frac{N - k_{\text{校验}}}{N}
  3. 重建开销对比RAID 1/10 整块拷贝最快;RAID 5/6 需读全条带并计算,重建慢。
    T重建:RAID 10<RAID 5≲RAID 6T_{\text{重建}}: \text{RAID 10} < \text{RAID 5} \lesssim \text{RAID 6}
  4. 选型映射随机小写选 RAID 10,顺序大块选 RAID 5/6,可丢失的临时数据选 RAID 0。
    OLTP→RAID 10,归档→RAID 5/6,缓存→RAID 0\text{OLTP} \to \text{RAID 10}, \quad \text{归档} \to \text{RAID 5/6}, \quad \text{缓存} \to \text{RAID 0}

AI 应用场景

云硬盘与对象存储的纠删码

阶段:存储架构设计

解决的问题:云厂商面对成千上万租户,既不能给每个人都上 RAID 10(太贵),又不能放任数据裸奔(不可靠)。传统方式是硬件 RAID 卡,但弹性、成本都不理想。

具体案例:对象存储(如 S3、OSS)内部把文件切成数据块,用类似 RAID 6 思想的纠删码(EC,如 6+3 或 4+2)分布式存放:N 块数据 + k 块校验分到不同机器,任意 k 台机器故障都能恢复。云盘产品则把 RAID 1/10 的镜像思想做成“多副本”,底层故障自动迁移。这正是 RAID“条带+校验”思想在分布式时代的延续。

数据库高可用存储选型

阶段:性能调优与高可用部署

解决的问题:MySQL 的 redo log、binlog 是典型的小块顺序写但要求极高可靠,数据文件则是 16KB 页的随机读写。若数据盘用 RAID 5,每次小写要付 4 次 I/O 的“记账手续费”,大促时延迟直接失控。

具体案例:某电商数据库主库采用“日志盘 RAID 1 + 数据盘 RAID 10”的经典组合:日志盘两块镜像保证不丢事务,数据盘 12 块做 RAID 10,随机写性能比 RAID 5 快一倍以上;备份集群则用 8 盘 RAID 6 兼顾容量与安全。架构师用一张选型表,就把性能、容量、成本对齐到业务目标。

AI 训练集群的存储设计

阶段:训练数据管线与 Checkpoint 管理

解决的问题:大模型训练每小时要写几 TB 的 checkpoint,属于大块顺序写;同时数据加载又有大量小文件随机读。单机 RAID 无法覆盖整个集群,但 RAID 的条带与校验思想被移植到分布式文件系统。

具体案例:训练集群常用 HDFS/对象存储的 EC 策略:把 checkpoint 切成 128MB 块,按“6 数据 + 3 校验”分布式存储,磁盘成本和 RAID 6 相当,却能容忍任意 3 台节点同时故障。预取阶段再借助条带化并行读,把训练数据加载时间压缩到 GPU 计算的几分之一。

Python 演示

python70 行
"""模拟 RAID 0 / RAID 1 / RAID 5 的数据分布与故障重建演示要点:条带化如何跨盘分布数据、异或校验如何重建丢失的块"""  def write_raid0(chunks, ndisk):    """RAID 0:数据块轮流写入各盘,无冗余"""    disks = [[] for _ in range(ndisk)]    for i, chunk in enumerate(chunks):        disks[i % ndisk].append(chunk)    return disks  def write_raid1(data):    """RAID 1:两块盘保存完全相同的副本(镜像)"""    return [data[:], data[:]]  def write_raid5(chunks, ndisk):    """RAID 5:每条带 ndisk-1 个数据块 + 1 个轮转奇偶校验块"""    disks = [[] for _ in range(ndisk)]    stripe_len = ndisk - 1    for start in range(0, len(chunks), stripe_len):        stripe = chunks[start:start + stripe_len]        parity = 0        for c in stripe:            parity ^= c        p_idx = (start // stripe_len) % ndisk        for d in range(ndisk):            if d == p_idx:                disks[d].append(parity)            else:                off = d if d < p_idx else d - 1                disks[d].append(stripe[off] if off < len(stripe) else 0)    return disks  def rebuild(disks, failed):    """坏盘后:用其余盘逐条带异或,恢复 failed 盘上的全部块"""    n = len(disks)    max_len = max(len(d) for d in disks)    recovered = []    for i in range(max_len):        val = 0        for d in range(n):            if d == failed:                continue            val ^= disks[d][i] if i < len(disks[d]) else 0        recovered.append(val)    return recovered  def show(name, disks):    print(name)    for i, d in enumerate(disks):        print('  盘%d: %s' % (i, d))  if __name__ == '__main__':    data = list(range(1, 9))    show('RAID 0(4 盘,无冗余)', write_raid0(data, 4))    print('RAID 1(两盘互为镜像)')    print('  盘0: %s' % write_raid1(data)[0])    print('  盘1: %s' % write_raid1(data)[1])     r5 = write_raid5([2, 7, 3, 9, 4, 6, 5, 8, 1, 0], 4)    show('RAID 5(4 盘,含轮转校验)', r5)    rebuilt = rebuild(r5, 2)    print('  坏盘2后重建结果: %s' % rebuilt)    print('  与原盘2内容一致: %s' % (rebuilt == r5[2]))
目的:把 RAID 0/1/5 的块分布和“坏盘重建”用纯 Python 演示一遍,直观看到条带轮转、异或校验和重建验证的全过程。
  1. disks[i % ndisk].append(chunk)数据块轮流写盘,这是条带化的核心
  2. parity ^= c逐块异或累加,生成该条带的校验块 P
  3. p_idx = (start // stripe_len) % ndisk校验盘随条带号轮转,避免热点盘
  4. val ^= disks[d][i] if i < len(disks[d]) else 0重建核心:把其余盘同位置块异或回放,还原坏盘内容
  5. rebuilt == r5[2]用重建结果对比原盘内容,验证恢复完全正确

常见误区

误区组了 RAID 1 或 RAID 5,数据就有“双保险”了,不再需要额外备份。毕竟书都抄了两份,还怕丢吗?

正解RAID 防的是“盘故障”这一类硬件灾难,相当于书在馆内有副本。但误删、勒索病毒、机房火灾、控制器故障都会让整个阵列同时失效。备份是把书抄一份放到另一座城市的图书馆,二者是两层不同的保险,缺一不可。RAID 保“可用”,备份保“可恢复到过去”。

为何常见:初学者容易把“冗余”和“备份”混为一谈,以为数据多存了一份就等于有了后悔药,忽略了误删和逻辑损坏才是数据丢失的最大来源。

误区RAID 5 号称“坏一块盘不影响使用”,所以重建期间业务照常跑、性能也不掉线。

正解重建要读全条带算校验,持续消耗带宽和 CPU;同时所有写请求都要额外处理,写惩罚翻倍。更危险的是,重建期间若再坏一块盘(尤其大容量盘),RAID 5 直接失效。所以坏盘后应尽快换盘重建,并评估降级运行的风险,必要时限流保护。

为何常见:产品宣传强调“容错”,容易让人忽略容错只解决“数据不丢”,并不等于“性能不降、风险为零”。

误区条带设得越大,每块盘处理的块越大,性能一定越高。毕竟并行嘛,越大越并行。

正解大条带只对大于条带的顺序大块请求友好;对 4KB/8KB 的小块随机请求,请求只落在单块盘上,其它盘闲着,条带再大也无济于事,反而增加拼接开销。条带大小应匹配负载的请求大小与对齐方式,不存在一劳永逸的“最优值”。

为何常见:只看到“条带化=并行=快”就以为越大越并行,忽略了请求粒度这个前提,把吞吐优化当成了全局优化。

误区RAID 6 能允许坏两块盘,RAID 10 只允许每镜像组坏一块,所以 RAID 6 更安全,选它准没错。

正解RAID 6 的“坏两块”是任意两块;RAID 10 的“坏 N/2 块”是有条件的(每组最多一块)。真正决定可靠性的还有重建时间:RAID 10 纯拷贝重建快,RAID 5/6 要异或/解算,大容量盘上重建窗口长、二次故障风险更高。可靠性不能只看“可坏盘数”这一个数字。

为何常见:用单一数字比较可靠性,忽略了重建时间与故障窗口这两个决定性因素,属于典型的“静态比较、动态误判”。

面试题

Q1. 机械硬盘上,读写的最小物理寻址单元是?

单选题 · easy

  • A.磁道
  • B.扇区← 正确答案
  • C.柱面
  • D.盘片

答案:B。扇区是盘面上划分出的最小格子,操作系统以扇区(512B 或 4KB)为单位寻址和读写;磁道是扇区的集合,柱面是跨盘片的磁道集合,盘片是物理载体本身。

Q2. 7200 转/分磁盘的平均旋转延迟约为?

单选题 · easy

  • A.2.1 ms
  • B.4.2 ms← 正确答案
  • C.8.3 ms
  • D.16.7 ms

答案:B。转一圈需要 60/7200 = 8.33 ms,平均等半圈即 4.17 ms。2.1 ms 是 15000 转的水平,8.3 ms 是转一整圈的时间,16.7 ms 是 3600 转的水平。

Q3. 组建 RAID 5 至少需要几块物理磁盘?

单选题 · easy

  • A.2 块
  • B.3 块← 正确答案
  • C.4 块
  • D.5 块

答案:B。RAID 5 每条带由 N-1 个数据块和 1 个校验块组成,校验块要独立占一块盘,至少需要 2 块数据盘加 1 块校验盘,共 3 块。2 块只能做 RAID 0 或 RAID 1。

Q4. 同一柱面上各磁道的共同点是?

单选题 · mid

  • A.磁头需移动才能访问
  • B.半径完全相同← 正确答案
  • C.同属外圈磁道
  • D.只能读不能写

答案:B。柱面是不同盘片上半径相同的磁道集合,磁头无需径向移动即可访问同一柱面,这就是“柱面”概念的由来。磁道既可读也可写,内圈外圈都各有柱面。

Q5. RAID 5 中改写一个数据块(小写)通常需要几次底层磁盘 I/O?

单选题 · mid

  • A.2 次
  • B.3 次
  • C.4 次← 正确答案
  • D.6 次

答案:C。小写要走“读改写”流程:先读旧数据、读旧校验,再写新数据、写新校验,共 4 次 I/O。2 次太少,6 次是 RAID 6 的代价,3 次没有对应机制。

Q6. 6 块盘组成 RAID 6,坏 1 块后重建过程中又坏 1 块,数据是?

单选题 · extreme

  • A.一定丢失
  • B.完整可用← 正确答案
  • C.仅校验丢失
  • D.仅镜像可读

答案:B。RAID 6 每条带有 P、Q 两份独立校验,允许任意两块盘同时损坏。重建中再坏一块仍处于容错范围内,数据完整可用;坏第三块才会丢失数据。

Q7. 4 块盘组成 RAID 10,最多能同时坏几块盘而不丢数据?

单选题 · hard

  • A.最多 1 块
  • B.最多 2 块← 正确答案
  • C.最多 3 块
  • D.最多 4 块

答案:B。RAID 10 由两个镜像组构成,每组至多允许坏 1 块。两组各坏 1 块共 2 块时数据仍完整;若同一组坏 2 块即丢失,因此 3 块、4 块必然包含同组双损。

Q8. 下列哪些 RAID 级别使用校验码实现容错?

多选题 · easy

  • A.RAID 0
  • B.RAID 1
  • C.RAID 5← 正确答案
  • D.RAID 6← 正确答案

答案:CD。RAID 5 用异或校验 P,RAID 6 用 P 和 Q 双校验;RAID 0 无任何冗余,RAID 1 靠镜像副本而非校验码,所以选 C、D。

Q9. 关于 RAID 0 的说法正确的是?

多选题 · mid

  • A.空间利用率 100%← 正确答案
  • B.提供数据冗余
  • C.读吞吐可提升← 正确答案
  • D.适合放系统盘

答案:AC。RAID 0 条带化后所有盘都存用户数据,利用率 100%,多盘并行读提升吞吐;它不提供任何冗余,坏一盘全损,因此不适合放不可再生的系统盘数据。

Q10. 关于 RAID 5 与 RAID 10 的说法正确的有?

多选题 · hard

  • A.RAID10 重建速度更快← 正确答案
  • B.RAID5 空间利用率更高← 正确答案
  • C.RAID5 更适合小写密集
  • D.RAID10 有校验计算开销

答案:AB。RAID 10 重建是纯拷贝,RAID 5 要读全条带算异或,故 A 对;RAID 5 利用率 (N-1)/N 高于 RAID 10 的 50%,故 B 对;RAID 5 小写有 4 次 I/O 惩罚,不适合小写密集,C 错;RAID 10 无校验计算,D 错。