C++ / a working model

142 / 163   ·   C11   ·   约 8 分钟

廉价磁盘冗余阵列(RAID)

先记住这句话

RAID通过将多块廉价磁盘组织成阵列,在保持对主机系统完全透明的前提下同时提升容量、吞吐和容错能力。本章介绍其对外接口、故障假设、三维评估方法以及最基础的条带化组织。

本篇内容
  1. 动机与透明部署
  2. 对外接口与控制器内部
  3. 故障假设与三维评估
  4. RAID-0 条带化组织
  5. 运行示例
  6. 动手练习

官方章节 PDF

动机与透明部署

单盘在速度、空间和寿命上都容易成为瓶颈。把多块磁盘当作一个整体来用,既能并行服务请求,又能提供更大的连续地址空间,还能靠冗余挡住个别磁盘损坏。最关键的一点是这种整体对外看起来仍然只是一块普通磁盘,因此操作系统和应用程序一行代码都不用改就能立刻受益。

对外接口与控制器内部

上层文件系统只看见一个线性块数组,发出逻辑读写即可。控制器负责把每个逻辑请求翻译成一次或多次物理磁盘操作,并维护必要的缓冲与校验计算。硬件实现通常自带微处理器、易失与非易失内存以及专用校验引擎,本质上就是一台专门跑存储固件的计算机。

故障假设与三维评估

当前采用最简单的故障-停止模型:磁盘要么完全正常,要么彻底丢失,并且丢失立刻可被控制器察觉。任何具体方案都从三个互相制约的维度衡量:客户端真正可用的容量、能够同时承受的磁盘失效个数、以及在顺序与随机两类负载下的实际带宽与延迟。

RAID-0 条带化组织

最朴素的做法是把连续逻辑块轮流放到各块磁盘上,既不浪费空间也不引入冗余。同一“行”上的块构成一条带,一次大顺序读可以同时启动所有磁盘。块组大小(chunk)决定了切换磁盘前在同一盘上连续放置多少块,从而在小随机请求与大顺序请求之间取得折中。

常见误区

  • 只计算总容量而忽略具体负载下的并行度差异
  • 把故障模型简化成“整盘立刻可检测”,从而忽视静默损坏

运行一个例子

最低标准 C11 · 完整程序 · 下载 .c

#include <stdio.h>

int main(void) {
    const int N = 4;
    const int C = 1;
    printf("RAID Level 0 mapping for first 16 logical blocks\n");
    for (int lb = 0; lb < 16; lb++) {
        int d = (lb / C) % N;
        int off = (lb / (N * C)) * C + (lb % C);
        printf("LB %2d maps to disk %d offset %d\n", lb, d, off);
    }
    return 0;
}

在本地编译

gcc -std=c11 -Wall -Wextra -Wpedantic -Werror ostep-38-raid.c -o example && ./example

预期结果

RAID Level 0 mapping for first 16 logical blocks
LB  0 maps to disk 0 offset 0
LB  1 maps to disk 1 offset 0
LB  2 maps to disk 2 offset 0
LB  3 maps to disk 3 offset 0
LB  4 maps to disk 0 offset 1
LB  5 maps to disk 1 offset 1
LB  6 maps to disk 2 offset 1
LB  7 maps to disk 3 offset 1
LB  8 maps to disk 0 offset 2
LB  9 maps to disk 1 offset 2
LB 10 maps to disk 2 offset 2
LB 11 maps to disk 3 offset 2
LB 12 maps to disk 0 offset 3
LB 13 maps to disk 1 offset 3
LB 14 maps to disk 2 offset 3
LB 15 maps to disk 3 offset 3

CHECK YOUR UNDERSTANDING

合上答案,试着解释。

4盘 RAID-0、chunk=1 时,逻辑块 11 落在哪一块磁盘的哪个偏移上?

查看参考答案

磁盘 3、偏移 2。因为 11÷1 后对 4 取模得 3,整除 4 后得偏移 2。

继续查证

标准草案与官方章节会更新;版本标记只说明示例最低要求。

回到目录