RAID 10 工作原理:VPS 存储为何首选 RAID 10?
深入解析 RAID 1、5、6 与 10 的故障容忍度与写入成本。了解为什么 VPS 主机偏好 RAID 10,如何通过 /proc/mdstat 查看阵列状态,并明确 RAID 并非数据备份的真相。
RAID 10 的工作原理,以及 VPS 主机为何采用它
RAID 10 是大多数 VPS 主机在虚拟化 NVMe(非易失性内存 express)驱动器上采用的存储布局。在传统的双副本布局中,RAID 10 会将每个驱动器镜像到一个配对驱动器,然后将数据条带化写入这些镜像对。单个驱动器发生故障时,阵列仍可继续运行。修复时只需从正常的配对驱动器复制数据,无需重新计算,也无需读取阵列中的其他所有驱动器。
RAID 是独立磁盘冗余阵列的缩写。它只有一个作用:磁盘故障或更换期间,仍让机器继续提供服务。这个作用是可用性,而可用性不等于安全性。
RAID 会复制您的写入操作。rm -rf /srv 是一次写入。镜像的两部分会在同一毫秒内删除该目录,但阵列之后仍会报告自身状态正常。
记住这句话。本页其余部分将介绍每个级别可以承受哪些故障,以及每次写入会产生什么代价。最后几节介绍如何在您拥有的机器上使用命令查看阵列状态,以及 RAID 从未覆盖的那类故障。
托管服务用户实际会遇到的级别:1、5、6 和 10
方案页面通常只列出一个数字。这个数字回答两个问题:最多可以损坏多少块硬盘,以及每次写入需要付出什么代价。
RAID 1 是镜像。 两块硬盘保存完全相同的数据块。每次写入都会发送到两块硬盘。任一硬盘都可以处理读取请求。一块硬盘发生故障时不会丢失数据,但原始容量只有一半可用。由于不需要计算校验,因此写入路径较短。
RAID 5 是带有每条条带一个校验块的条带化。 使用 n 块硬盘时,可用容量相当于其中 n-1 块硬盘,并且阵列恰好可以承受一次故障。校验数据不会固定存放在某一块硬盘上,而是轮换分布在所有硬盘上。因此,每块硬盘都同时承载数据和校验数据。
RAID 6 为每条条带增加第二个独立的校验块,通常记为 P 和 Q。它可以承受任意两块硬盘同时发生故障。这一点比看起来更重要,因为第二次故障最常发生在第一次故障的修复期间。
RAID 10 是镜像组的条带化。 硬盘两两组成镜像,数据再分布到各个镜像组之间。可用容量是原始总容量的一半,与 RAID 1 相同,同时具备条带化带来的并行处理能力。
您还会看到 RAID 1+0 这种写法,这种描述更准确:先创建镜像,再跨镜像组进行条带化。RAID 0+1 的顺序相反,先进行条带化,再对两组条带做镜像。它更差,因为一块硬盘故障就会使整组条带停止提供服务,修复时还必须复制另一侧的全部数据。
Linux 有一个值得了解的特殊情况。内核的 raid10 是一个整体实现,而不是两个叠加的层,因此它可以运行在奇数块硬盘上,并且支持嵌套配置无法表达的布局(near、far、offset)。因此,Linux 主机的状态行会显示 2 near-copies,而不是列出两个阵列。
此图表背后的数据
[
{
"label": "RAID 1 (eight copies)",
"usable_tb": 1,
"worst_case_drives_lost": 7,
"best_case_drives_lost": 7
},
{
"label": "RAID 5",
"usable_tb": 7,
"worst_case_drives_lost": 1,
"best_case_drives_lost": 1
},
{
"label": "RAID 6",
"usable_tb": 6,
"worst_case_drives_lost": 2,
"best_case_drives_lost": 2
},
{
"label": "RAID 10",
"usable_tb": 4,
"worst_case_drives_lost": 1,
"best_case_drives_lost": 4
}
]8 块 1 TB 硬盘在 RAID 5 下提供 7 TB 可用空间,在 RAID 10 下提供 4 TB。这个差额确实会影响成本,这也是人们不断提出使用校验方案的原因。RAID 6 在任何故障组合下都可以承受 2 次故障。RAID 10 只能保证 1 次故障,因为最危险的第二次故障,是发生在已经故障硬盘的镜像伙伴上。若没有两次故障发生在同一对镜像硬盘上,它最多可以承受 4 次故障,但这取决于运气,并不是设计特性。
每次写入各级别的开销
向镜像写入会产生两次写入,同时发送到两个成员。向奇偶校验条带写入的处理量更大,因为该条带的奇偶校验块已失效,必须重新计算。
对于读-改-写,控制器会先读取旧数据和旧奇偶校验。在 RAID 5 上,未缓存的单块覆盖会变成读、读、写、写。RAID 6 维护两个奇偶校验块,因此读-改-写会变成读、读、读、写、写、写。Linux 还会使用重构-写入,读取未更改的数据来计算奇偶校验。在三盘 RAID 5 上,这种覆盖可能需要读取一个数据块并执行两次写入;在四盘 RAID 6 上,则需要读取一个数据块并执行三次写入。四次和六次是读-改-写的操作计数,不是每次小型随机写入的固定开销。
此图表背后的数据
[
{
"label": "RAID 1 (2 drives)",
"write_ops_per_host_write": 2,
"drives_read_to_rebuild": 1
},
{
"label": "RAID 5 (8 drives)",
"write_ops_per_host_write": 4,
"drives_read_to_rebuild": 7
},
{
"label": "RAID 6 (8 drives)",
"write_ops_per_host_write": 6,
"drives_read_to_rebuild": 7
},
{
"label": "RAID 10 (8 drives, fixed mirror pairs)",
"write_ops_per_host_write": 2,
"drives_read_to_rebuild": 1
}
]在 RAID 6 上,未缓存的单块读-改-写需要 6 次设备操作;在双副本 RAID 10 上,相同的覆盖只需要 2 次设备操作。这些计数低估了延迟差异。两次镜像写入会并行执行,因此客户机需要等待两次写入中较慢的一次。读-改-写路径包含一次读取,该读取必须完成后才能计算新的奇偶校验,因此客户机需要先等待读取,再等待写入,两个操作依次执行。在繁忙的主机上,这次读取还会排在其他人的 I/O 后面。
但有一个重要例外。足以填满整个条带的写入不需要读取旧数据,因为条带中的每个块都会被替换。奇偶校验直接根据内存中已有的数据计算。此时,RAID 5 每个条带只需写入一个奇偶校验块,RAID 6 只需写入两个奇偶校验块,且不需要预读。这就是 RAID 5 在顺序基准测试中表现良好,却在多个租户产生小型写入的混合负载下表现不佳的原因。请测试实际运行的负载模式:正确测试 VPS 磁盘性能意味着在合理的队列深度下执行随机 I/O,而不是执行一次大型 dd。
重建为何是危险环节
完整的 RAID 5 重建必须根据其他所有磁盘重构缺失磁盘中的数据。因此,在八盘示例中,它会从第一个块读取到最后一个块,共读取 7 个正常磁盘。对于固定的双副本镜像对,RAID 10 重建只读取 1:故障磁盘的镜像伙伴,不读取其他磁盘。其他 Linux RAID10 布局会以不同方式分布副本:重建三设备近布局中的一个成员时,会读取另外两个正常成员。
这会带来两项成本。第一项是时间,因为重建速度受正常磁盘、重构工作量和恢复速度目标限制。第二项是负载。校验重建会将 I/O 分散到正常磁盘上。对于固定的镜像对,RAID 10 重建会将 I/O 集中到其中一对磁盘;共享控制器和主机资源仍会影响其他镜像对。
同一时间窗口内还存在数据正确性风险。RAID 5 阵列在一块磁盘故障后不再具有冗余,因此正常磁盘上的任何不可读取扇区都无法恢复。重建是唯一会读取每个扇区的操作,包括过去一年中从未访问过的扇区。已发布的数据表指标显示,消费级硬盘每读取 10^14 bit 可能出现约 1 次不可恢复读取错误;企业级 NVMe 磁盘则为每读取 10^17 bit 约 1 次或更好。这些数据是厂商规格,而不是实测结果,但这个比例说明了为什么“RAID 5 重建会失败”这一旧警告针对的是大容量机械硬盘,以及为什么它在 NVMe 上的适用性弱得多。负载方面的结论适用于任何介质。
通过 scrub 在重建前发现潜在错误。Debian 和 Ubuntu 会为 md 阵列提供定期 scrub,但不同发行版的实现机制不同,因此请先确认当前使用的机制,然后手动触发一次检查。
systemctl list-timers --all | grep -i mdcheck
ls -l /etc/cron.d/mdadm
echo check | sudo tee /sys/block/md0/md/sync_action
cat /sys/block/md0/md/mismatch_cntsync_action会在检查完成后恢复为 idle,而 mismatch_cnt应显示为 0。镜像中的非零数字表示两半内容不一致。由于两个副本都不包含校验和,内核无法判断哪一份正确。有些不匹配无害,交换分区是常见来源:内核可能正在写入一个页面,而该页面的内容在此期间发生变化。数据阵列中的计数持续增加时,需要进一步调查;仅凭该计数无法确定应更换哪块磁盘。
为什么 VPS 提供商在 NVMe 上普遍采用 RAID 10
虚拟机管理程序节点不会只运行一种工作负载。它会运行数十个彼此无关的客户机,其 I/O 交错到达,表现为大量小写入,而且不同写入之间没有局部性。奇偶校验 RAID 的读-修改-写周期在这种模式下开销最高,而共享节点全天都处于这种模式。
再考虑重建行为,选择就很明确了。奇偶校验节点上的磁盘发生故障后,剩余磁盘都要参与重建。固定镜像对的 RAID 10 节点发生磁盘故障后,重建 I/O 只会增加到其中一个镜像对上;当系统存在其他活动时,Linux MD 还会降低恢复速度。提供商销售的是不会出现延迟尖峰的性能,因此会用容量换取这种性能:原始 NVMe 容量的一半用于镜像。
磁盘容量也会推动同样的选择。磁盘容量越大,重建窗口越长;而在 RAID 5 中,这段时间正是重建会增加负载且系统不再具备冗余保护的时期。RAID 6 还能承受另一个磁盘故障。ZFS 虚拟化部署使用由镜像 vdev 组成的池,而不是宽条带 raidz,原因相同:镜像 resilver 只复制实际使用的块,而且只发生在一个镜像对上。
这并不意味着 RAID 10 在所有场景下都正确。备份目标通常以长距离顺序写入,很少读取,因此 RAID 6 更适合。它可以承受两个磁盘故障,并保留大部分容量。应由工作负载决定,而不是由磁盘数量决定。对于今天选择的方案,介质通常比其上的布局更重要,而且 从 SATA SSD 迁移到 NVMe 的提升大于两者之间的任何 RAID 差异。
如何读取 /proc/mdstat
在您拥有该阵列的机器上运行这些命令:专用服务器、家用主机,或配有两个由您自行组装的附加卷的 VPS。读取您自己的输出。下面的代码块是示例,已完整列出,便于您对照实际输出的结构。
cat /proc/mdstat
sudo mdadm --detail /dev/md0
lsblk -o NAME,SIZE,TYPE,MOUNTPOINTS健康的四盘 RAID 10 通常会输出类似内容。
Personalities : [raid1] [raid10]
md0 : active raid10 nvme3n1p3[3] nvme2n1p3[2] nvme1n1p3[1] nvme0n1p3[0]
3906764800 blocks super 1.2 512K chunks 2 near-copies [4/4] [UUUU]
bitmap: 0/30 pages [0KB], 65536KB chunk
unused devices: <none>其中每一部分都包含信息。
Personalities列出正在运行的内核已加载的 md 模块。raid10出现在其中表示代码可用,仅此而已。md0 : active raid10是阵列设备、阵列状态和阵列级别。- 后面的名称是成员设备。方括号中的数字是设备在阵列元数据中的索引,不是它在线上的位置,也不一定是它所在的插槽。
- 更换驱动器后,新成员通常会保留一个高于其所填补插槽的索引,因此
nvme4n1p3[4]可能位于插槽 2。mdadm --detail会在其RaidDevice列中输出实际插槽,因此在两者不一致时应以该列为准。 - 成员后的
(F)表示故障。(S)表示备用设备:设备已存在但处于空闲状态,等待其他设备发生故障。 3906764800 blocks super 1.2是以 1 KiB 块为单位的可用大小,后面是元数据格式。512K chunks 2 near-copies是条带块大小和 RAID 10 布局。此处的布局会将每个块的两个副本放在相邻位置。[4/4]是阵列应包含的成员数,后面是当前已同步的成员数。[UUUU]按插槽顺序为每个插槽显示一个字符。U表示该插槽已启用且已同步。_表示该插槽中没有正常工作的设备。bitmap:是写意图位图。它记录正在写入的区域,因此成员设备掉线后重新加入时,只需重新同步这些区域,而不是整个驱动器。
出现故障时,[4/3] 和 [UU_U] 的含义
降级阵列如下所示。
md0 : active raid10 nvme3n1p3[3] nvme2n1p3[2](F) nvme1n1p3[1] nvme0n1p3[0]
3906764800 blocks super 1.2 512K chunks 2 near-copies [4/3] [UU_U]结合查看这两组方括号。[4/3]表示四个插槽中有一个未提供数据。[UU_U]指出具体是哪一个,因为下划线是第三个字符,而插槽编号从 0 开始,因此插槽 2 已停止工作。驱动器仍连接在机器上时,(F)标志会标识该设备。将其从机器中拔出后,该名称会从此行消失,但下划线仍会保留。
阵列在上述情况下仍会继续提供服务。RAID 10 通常还能接近满速提供服务,因此仅凭使用感受通常无法发现问题。必须通过监控发现它。
grep -i mailaddr /etc/mdadm/mdadm.conf
sudo mdadm --monitor --scan --oneshot --test
systemctl list-units --all | grep -i mdmdadm软件包会安装一个监控守护进程。该守护进程从 /etc/mdadm/mdadm.conf读取 MAILADDR。单元名称在不同版本之间可能发生变化,因此应使用最后一个命令查找它,不要猜测名称。--test运行后会立即为每个阵列发送一条消息。运行后收件箱为空,表示邮件路径已损坏;真正需要关注的消息也会以同样方式丢失。
替换驱动器正在重建时,阵列下方会出现进度行。
md0 : active raid10 nvme4n1p3[4] nvme3n1p3[3] nvme1n1p3[1] nvme0n1p3[0]
3906764800 blocks super 1.2 512K chunks 2 near-copies [4/3] [UU_U]
[==>..................] recovery = 12.4% (242012928/1953382400) finish=63.1min speed=452000K/secrecovery表示正在将数据重建到替换驱动器上。resync表示一致性检查,包括初始检查和从非正常关机中恢复时执行的检查。check表示您在上面触发的校验。圆括号中的数值表示进度,单位是 1 KiB 块;分母是每个设备的总块数。finish是内核根据当前速度给出的预计剩余时间。Linux MD 使用 /proc/sys/dev/raid/speed_limit_min和 speed_limit_max作为恢复速度目标;也可以在 sync_speed_min和 sync_speed_max中为各个阵列单独设置覆盖值。默认最大目标速度为每个设备 200,000 KiB/s。这些目标用于让恢复任务让出资源给生产 I/O,并不是严格的速度上限。
重建期间的完整 mdadm --detail
/dev/md0:
Version : 1.2
Creation Time : Tue Mar 10 09:14:22 2026
Raid Level : raid10
Array Size : 3906764800 (3.64 TiB 4.00 TB)
Used Dev Size : 1953382400 (1.82 TiB 2.00 TB)
Raid Devices : 4
Total Devices : 4
Persistence : Superblock is persistent
Update Time : Wed Aug 5 11:02:41 2026
State : clean, degraded, recovering
Active Devices : 3
Working Devices : 4
Failed Devices : 0
Spare Devices : 1
Layout : near=2
Chunk Size : 512K
Rebuild Status : 12% complete
Name : storage:0
Events : 4184
Number Major Minor RaidDevice State
0 259 3 0 active sync set-A /dev/nvme0n1p3
1 259 7 1 active sync set-B /dev/nvme1n1p3
4 259 11 2 spare rebuilding /dev/nvme4n1p3
3 259 15 3 active sync set-B /dev/nvme3n1p3Number列是元数据索引,对应 /proc/mdstat方括号中的索引。RaidDevice列是插槽,也就是 [UU_U]字符串中的位置。此处两者不同,因为设备 4 替换了原先占用插槽 2 的驱动器。set-A和 set-B标识每个镜像的两个部分,因此同一镜像对中分别属于 set-A 和 set-B、且保存相同数据的两个成员,不能同时丢失。
在您拥有的阵列上更换驱动器需要执行四条命令,最后一条命令用于检查。
sudo mdadm --manage /dev/md0 --fail /dev/nvme2n1p3
sudo mdadm --manage /dev/md0 --remove /dev/nvme2n1p3
sudo mdadm --manage /dev/md0 --add /dev/nvme4n1p3
cat /proc/mdstat恢复进度行应在 1 或 2 秒内出现。替换分区必须至少与 mdadm --detail中的 Used Dev Size一样大。如果分区小哪怕一点,也会被拒绝,并显示类似 not large enough to join array的消息。添加新驱动器前,应先将其分区设置为与旧驱动器匹配。
从 VPS 内部可以看到和不能看到的内容
大多数客户无法看到宿主机的 RAID,这是设计如此。虚拟化管理程序会向您提供一个虚拟磁盘。该磁盘是从 NVMe 驱动器组成的 RAID 10 池中划分出来的,还是位于单个驱动器上,属于宿主机属性,在客户机内部不会显示。
systemd-detect-virt
lsblk -d -o NAME,SIZE,ROTA,MODEL
cat /proc/mdstatsystemd-detect-virt 在 KVM 客户机上输出 kvm,在容器上输出诸如 lxc 的容器类型,在裸机上输出 none。在 KVM 客户机上,您通常只能在 lsblk 中看到一个 vda 或 sda,并且在 /proc/mdstat 中看不到任何阵列,因为客户机内部不存在阵列。
在基于容器的 VPS 上,这个结果不可靠。容器共享宿主机内核,而 /proc 的部分内容没有进行命名空间隔离,因此其中显示的信息可能描述的是宿主机,而不是分配给您的存储切片。不要将其中任何信息视为您自己的存储事实。请向服务提供商询问存储布局;如果这对您很重要,请要求对方提供书面答复。
您可以在 VPS 内部检查分配给您的磁盘的实际行为。检查 VPS 磁盘是否确实为 NVMe介绍了能够报告真实信息的命令,SSD VPS 实际包含哪些内容介绍了套餐页面上的标签所代表的内容。
应在 VPS 内运行 RAID 吗?
通常不应这样做,原因在于故障域。如果将两个卷附加到一个 VPS,并使用 mdadm 将它们配置为镜像,这两个卷可能位于同一个物理阵列、同一个节点,并共用同一个电源。这样,您会为已有的冗余将每次写入的成本增加一倍,但对于真正关键的那种故障,两个副本仍会同时丢失。
如果服务提供商明确说明这些卷位于不同的故障域,或者您使用的是可以自行选择磁盘的专用服务器,那么这样做才有意义。否则,应优先将精力用于创建存放在本机之外的副本。
RAID 无法防护的情况
RAID 只能应对一种事件:磁盘停止正常工作。下面的操作都是有效写入,因此阵列会将其应用到每个副本,并报告自身状态正常。
- 删除。 在错误目录中执行
rm -rf,或部署脚本在路径中使用未设置的变量。阵列会将其视为合法写入,并执行两次。 - 勒索软件。 加密本身就是写入操作。正常工作的阵列会将加密后的版本存储在镜像的两端。
- 应用损坏。 会向数据库写入垃圾数据的 bug,也会将相同的垃圾数据写入冗余磁盘。
- 整个节点。 主机发生故障,或某个帐户被误暂停。阵列可以完全正常,但同时无法访问。
- 一周后的您自己。 您在星期一删除的文件,会在星期一从每个磁盘上消失。只有此前创建的副本才能将其恢复。
存储在同一存储设备上的快照也不是解决方案。它们可以帮助应对删除,但会随所在阵列一起失效。备份之所以是备份,关键在于它位于其他位置。使用 restic 创建加密的服务器外备份 是本页的另一部分:阵列让您能够在磁盘故障时继续提供服务,而当损坏来自阵列认为合法的写入时,restic 可以恢复您的数据。
FAQ
RAID 10 是否意味着不需要备份?
不需要。RAID 10 可防止磁盘停止工作。它会将每次有效写入同时应用到镜像的两侧,因此删除操作或勒索软件运行会在同一时刻到达冗余磁盘。阵列随后会报告自身状态正常,因为从阵列的角度看,没有任何组件发生故障。您仍然需要将副本存储在本机之外,并且仍然需要定期恢复副本,以验证备份确实可用。
VPS 提供商为什么选择 RAID 10,而不是 RAID 5 或 RAID 6?
有两个原因,都与小规模随机写入有关。未缓存的单块读-修改-写操作需要先读取旧数据和校验数据,再计算新的校验数据。在 RAID 5 上需要 4 次操作,在 RAID 6 上需要 6 次,而双副本镜像只需要 2 次。重构写入使用未变化的数据,因此无需预读旧数据和旧校验数据;完整条带写入也无需预读旧数据或旧校验数据。完整 RAID 5 重建需要从头到尾读取每个仍存活的磁盘,而采用固定镜像对的传统 RAID 10 会从存活的镜像成员复制数据;其他 Linux RAID10 布局则会使用多个源成员。其他活动运行时,Linux MD 会限制恢复速度。提供商需要为此付出容量代价:原始 NVMe 容量的一半。
/proc/mdstat 中的 [U_] 或 [UU_U] 表示什么?
每个字符代表阵列中的一个槽位,按槽位顺序排列,每个槽位对应一个字符。U 表示该槽位包含一个已上线且已同步的成员。_ 表示该槽位中没有正常工作的成员。对于双盘镜像,[U_] 表示第二个槽位已停止工作,阵列已不再具备冗余。请结合它前面的成员数量一起读取,其中 [4/3] 表示阵列应有4个成员,当前有3个成员。槽位顺序对应 mdadm --detail 的 RaidDevice 列,而不是该行中设备名称出现的顺序。
RAID 10 阵列最多可以丢失多少块磁盘?
对于采用固定镜像对的传统双副本 RAID 10,任何情况下都能丢失1块。超过1块后,取决于故障落在哪些磁盘上。每个镜像对都可以丢失其中一个成员,因此8盘阵列在没有两个故障位于同一镜像对时,最多可承受4次故障;如果两个故障都位于同一镜像对,则发生第2次故障时阵列就会失效。请按保证数量进行规划,这个数量是1;超出该数量的部分只能视为运气,不能视为保护能力。
是否应该使用 mdadm 在 VPS 内部镜像两个卷?
通常不应该。连接到同一个 VPS 的两个卷通常位于同一主机上的同一个物理阵列中,因此镜像会使每次写入的成本翻倍,却无法防止主机自身 RAID 已经覆盖的任何故障。只有在提供商明确说明这两个卷位于独立故障域时,这样做才值得。否则,应将精力投入到存储在本机之外的备份上。