说起软RAID,我在不同场合都跟人聊过。有人觉得它是“穷人的备份方案”,有人觉得软RAID不靠谱、不如直接买阵列卡,也有人明明配好了阵列却从没关注过它的健康状态。我的看法不太一样:软RAID是在成本、灵活性和可靠性之间取得平衡的好东西,尤其适合家用NAS、小型文件服务器、测试环境和一些不太核心的生产存储。只要你知道自己在干什么,软RAID完全值得依赖。
这篇文章主要写给三类人:正在折腾NAS、打算把手头几块闲置硬盘利用起来的朋友;给公司或工作室搭文件共享存储的运维新手;以及已经搭好阵列但没搞懂“后续怎么维护、坏了怎么换盘”的人。核心内容围绕怎么选RAID级别、怎么规划磁盘、怎么用mdadm从零创建一个可用的软RAID阵列,以及阵列日常维护和故障恢复的完整思路。我会把参数怎么定、命令为什么这么写、踩过的坑在哪里,都尽量讲透。
1. 为什么选软RAID:方案选型的底层逻辑
1.1 软RAID和硬RAID到底差在哪
软RAID,指的是由操作系统自身实现的磁盘阵列功能。在Linux世界,最常见的实现就是内核的md模块,配合mdadm这个用户态管理工具来创建、组装、监控和管理阵列。硬RAID则是指独立于系统的阵列卡,它有自己的处理器、缓存、电池保护,在操作系统看来,所能看到的就只是一个“正常的硬盘控制器”。
两者的差别不只是名字。最核心的区别在于“谁来承担冗余和校验计算”。软RAID让CPU来算,硬RAID交给卡上的芯片算。看起来似乎是硬RAID更高效,但实际使用体验并不完全是这样。现代多核CPU处理软RAID的校验计算非常轻松,尤其在千兆网络环境下,多数文件读写场景的瓶颈根本不在CPU。我见过不少用入门级硬RAID卡跑出来的阵列,性能反而不如同一批盘做软RAID,原因很简单:低端硬卡本身的处理能力有限,缓存小得可怜,碰到随机写一样拉胯。
另外还有个反直觉的问题——硬RAID卡坏了怎么办。阵列是绑在卡上的,卡坏了,如果找不到同型号甚至同固件版本的卡,阵列数据就等于被“锁”住了。而软RAID的元数据就在磁盘上标准的位置里,只要系统能识别到硬盘,换一台Linux机器就能把阵列重新组装回来,这是软RAID非常大的灵活性优势。
1.2 什么场景适合用软RAID
我的判断一直很明确:如果需求是“几块盘做存储,数据重要但不是银行交易系统那种级别,预算有限且不想被硬件绑定”,软RAID是完全可以上的方案。
典型场景包括:
- 家庭或小型工作室的NAS,平时存文档、照片、项目备份、镜像和中小型虚拟机。
- 公司内部的共享文件服务器,几十个人同时访问文件目录。
- 开发测试环境,需要模拟不同RAID级别的性能特性,或者需要随时拆装阵列做实验。
- 备份服务器的存储池,比如接收定时备份任务,对写入吞吐有一定要求,但不追求极端性能。
反过来,我也要说清楚哪些情况不建议用软RAID。如果你要支撑高并发、高IOPS的数据库业务,对单阵列性能有严格SLA要求,或者阵列规模大到几十块盘、需要专业监控,那确实应该认真考虑硬RAID卡或者分布式存储方案。软RAID不是万能药,知道它的边界,才能更好地用它。
1.3 方案选型的三个判断维度
我通常建议从三个维度做评估:成本、性能、可靠性。
成本方面,软RAID几乎是零额外投入。几块盘加一台普通主机就够。硬RAID卡好一点的动辄几千块,低端卡几百块但性能和可靠性都打折扣。如果算上电池保护模块、万兆网卡这些配套,硬卡方案的成本可能翻好几倍。
性能方面,正如前面所说,软RAID顺序读写性能并不吃亏,尤其是RAID 0和RAID 1这种没有校验计算的级别。RAID 5和RAID 6的写入因为要计算校验值,消耗CPU资源,但当CPU核心数充足时,性能仍然在可接受范围。我在一台老旧的四核机器上跑过4盘RAID 5,千兆网络下持续写入能轻松跑满110MB/s左右,瓶颈在网络上而不是阵列本身。
可靠性方面,软RAID需要操作系统的正确维护。系统崩溃、内核模块加载失败、配置丢失都可能导致阵列无法自动挂载。但只要你把配置做好了,这种情况极少发生。更重要的是,软RAID的故障恢复路径比硬RAID更透明——你能看到阵列重建的进度、每块盘的状态、元数据的完整信息。这种“看得见”本身就是一种可靠性保障。
2. 动手前的功课:RAID级别与磁盘准备
2.1 各RAID级别怎么选
RAID级别的选择,是整个搭建过程中最影响后续体验的决策。我不打算泛泛而谈,直接给一套可落地的理解方式。
先看每个级别到底是干什么的:
- RAID 0:条带化,数据分散写在所有盘上,没有冗余。性能最好,容量是全部盘的总和。任何一块盘坏了,数据就全部丢失。
- RAID 1:镜像,数据同时写入两块盘,任何一块盘坏掉,数据仍然完整。容量只有一半,适合系统盘或容量不大但非常重要的数据。
- RAID 5:条带化加分布式奇偶校验,至少三块盘,允许坏一块盘,容量是N减一块盘的容量总和。
- RAID 6:在RAID 5的基础上把校验数据也分开存,至少四块盘,允许坏两块盘,容量是N减两块盘的容量总和。
- RAID 10:先镜像再条带,至少四块盘,容量是总容量的一半,但既能抗坏盘,又有不错的读写性能。
我习惯用一张表来对比,这样最直观:
| RAID级别 | 最少盘数 | 最大容错 | 可用容量 | 读取性能 | 写入性能 | 重建耗时 | 适用场景 |
|---|---|---|---|---|---|---|---|
| RAID 0 | 2 | 0 | 100% | 高 | 高 | 无需重建 | 缓存、临时数据 |
| RAID 1 | 2 | 1 | 50% | 较高 | 一般 | 快 | 系统盘、重要小数据 |
| RAID 5 | 3 | 1 | (N-1)/N | 较高 | 一般 | 较慢 | 文件存储、备份 |
| RAID 6 | 4 | 2 | (N-2)/N | 较高 | 较低 | 慢 | 大容量高可靠场景 |
| RAID 10 | 4 | 每组1 | 50% | 高 | 较优 | 快 | 数据库、虚拟机 |
很多新手一上来就问“RAID 5是不是最好的呀”,其实没有最好,只有最合适。我的建议是:
- 普通文件存储、照片库、归档数据,选RAID 5就够了,容量利用率高,容忍一块盘故障。
- 如果存储的数据非常重要,或者单盘容量已经很大(超过8TB),建议考虑RAID 6。因为大容量盘重建时间很长,重建期间如果另一块盘也出问题,RAID 5就全完了。
- 如果跑虚拟机或数据库,想都不用想,直接上RAID 10。RAID 10的随机写性能远好于RAID 5,重建速度也快得多。
- 如果只是放无关紧要的下载文件,追求最大容量和速度,RAID 0也不是不行,但一定要有“随时可以全部推倒重来”的心理准备。
2.2 磁盘选择的几个关键点
磁盘选择直接决定了阵列的寿命和体验,这块我的经验比较深刻。
第一,尽量保持磁盘容量一致。如果混用不同容量的盘,RAID会以最小容量盘为基准。比如三块盘分别是4TB、2TB、2TB,做RAID 5,其余两块盘各2TB会被基准确认到,你实际能用的容量只有4TB。多出来的那部分空间无法参与阵列,等于白白浪费。解决方案是让阵列规模统一,或者干脆只拿相同容量的盘来做。
第二,尽量避开SMR盘。SMR全称是叠瓦式磁记录,这种盘在连续写入后会触发内部重写机制,随机小写入性能很差。更要命的是,RAID重建需要持续的长时间写入,SMR盘在重建过程中很容易因为写入速度骤降甚至超时掉盘,这种“重建期间二度故障”在现实中一点都不罕见。有条件的话优先选择CMR盘或企业级盘。
第三,SSD做RAID也常见,但要注意不同牌子的SSDTRIM策略差异很大,部分消费级SSD做RAID1后写放大明显,掉电后数据一致性也不如企业级SSD。如果你打算全闪阵列,建议选择带断电保护的企业级SSD。
第四,关于盘位数。我在实际操作中发现,一个阵列的盘数越多,重建时间越长,风险越高。4到8块盘是比较舒服的区间。超过8块后,我会倾向于拆分成两组阵列,而不是把所有盘都塞进一个大阵列。
2.3 动手前的备份与空间规划
这是最容易被忽略但最重要的一步。很多人以为“RAID 1/5/6等于数据不会丢”,这是错的。RAID解决的是硬件故障冗余,但解决不了误删除、勒索病毒、火灾水灾、电源损坏、控制器bug。我见过最惨的一次,是有人把4块2TB盘做了RAID 5,结果某天误操作把整个阵列格式化了,数据全部无法恢复。所以但凡数据有一点价值,在开始搭建之前就要想清楚备份方案。
空间规划方面,建议先做一张简单清单:需要存储多少数据,预计未来一年增长多少,打算留多少空余给临时空间。我一般留10%到20%的空余容量,不至于让阵列跑到80%以上。RAID阵列一旦使用率超过85%,写性能会显著下降,碎片化也会更明显。这个“预留”不是矫情,是给运维留的喘息空间。
3. 核心实操:用mdadm构建软RAID全过程
3.1 环境识别与工具安装
正式开始之前,先把磁盘环境摸清楚。我用这些命令确认当前机器的存储布局:
lsblk这个命令会列出所有块设备,以及挂载点信息。你会清晰看到系统盘是哪一块,剩余的裸盘是哪些。接下来再用:
fdisk -l或者:
lsblk -o NAME,SIZE,MODEL,SERIAL来确认每块盘的容量和型号。这一步千万别偷懒,我要特别强调:在创建阵列前必须搞清楚哪一块盘是系统盘。曾经有人在SSD系统盘和几块机械盘之间做阵列,命令写错了设备名,直接把系统盘清掉,场面非常难看。所以我的习惯是,在创建之前,把每一块盘都标好序列号,甚至拿标签纸写在盘身上。
接着安装mdadm。不同发行版包管理器略有差异,比如在基于APT的系统上:
apt install mdadm在基于RPM的系统上:
dnf install mdadm装好之后,先确认内核是否已经加载了md模块。最直接的方式是看系统里有没有mdstat这个虚拟文件:
cat /proc/mdstat如果出现了一段以“Personalities”开头的文字,说明内核的RAID支持已经就绪。如果提示文件不存在,说明模块没有加载或内核没有编译支持,需要先处理这个问题再往下走。
3.2 磁盘分区与准备
接下来一个选择题:整盘直接加入阵列,还是先分区再加入阵列。
整盘加入块设备是最简单、最不容易出错的做法,直接指向一整块物理盘如/dev/sdb当作阵列成员设备。这也是绝大多数情况下推荐的做法,因为软RAID完全可以直接使用整块磁盘。只有当你想在磁盘上前留出空间,比如预留一部分作为系统备份或固件升级区域时,才需要先分区。
如果确实需要分区,我建议使用parted或gdisk。一个典型的分区做法是:
parted /dev/sdb mklabel gpt parted /dev/sdb mkpart primary 1MiB 100% parted /dev/sdb set 1 raid on要注意的是分区起点对齐到1MiB或4MiB这类现代算法对应的扇区,而不是从默认的0扇区或63扇区开始。对齐对阵列的持续性能影响不小,尤其在底层硬盘顺序写入时。分完区后用lsblk再确认每个分区的大小一致性。如果四块盘的容量完全一样,那分区后也应该保持完全一样,这样阵列条带在每个盘上跨度的分配才是均匀的。
我个人的偏好是直接用整块盘。分区带来的额外复杂度在实际场景中并不划算。在介绍命令时我以整盘加入为例,这也是社区里最常见、最稳定的做法。
3.3 创建阵列:mdadm --create 参数详解
假设我有四块盘要做RAID 5:/dev/sdb、/dev/sdc、/dev/sdd、/dev/sde。命令如下:
mdadm --create /dev/md0 --level=5 --raid-devices=4 --chunk=64 --metadata=1.2 --name=datastore /dev/sdb /dev/sdc /dev/sdd /dev/sde这里面的每个参数背后都有原因。
--level=5指定RAID级别。--raid-devices=4表示阵列里数据盘的数量,这个值必须与实际设备数匹配。--chunk=64是条带块大小,单位是KB。--metadata=1.2指定元数据版本。--name=datastore是给阵列起个名字,方便在机器上识别。
我逐个说清楚。
在RAID 5中,chunk决定了条带数据块的粒度。如果chunk太小,比如4KB或8KB,那么一次较大的连续读会被拆分到很多盘上,增加了并行度,但也会增加小文件的寻道开销。如果chunk太大,比如1MB,像数据库这种随机小块访问就吃亏了。我在实际中常用64KB或128KB作为通用文件服务的起始点,比较均衡。
metadata版本是很多教程不怎么展开但实际很影响排障的选项。RAID 1.0的超级块放在每个成员盘的最末尾,老系统兼容性最好,但缺点是盘尾有问题时元数据可能受影响。RAID 1.1放在盘的最开头,对引导型阵列更友好。RAID 1.2是mdadm自己最推荐的版本,超级块放在距离盘起始位置固定的位置,同时兼顾了识别与兼容。新分配的阵列,我没有遇到过必须用1.0或1.1的理由,默认1.2即可。
在创建命令执行后,系统会开始后台同步。这时可以查看:
cat /proc/mdstat输出中你会看到类似这样的内容:
Personalities : [raid6] [raid5] [raid4] md0 : active raid5 sde[3] sdd[2] sdc[1] sdb[0] 5860269056 blocks super 1.2 level 5, 64k chunk, algorithm 2 [4/4] [UUUU] [>....................] resync = 2.5% (195112/5860269056) finish=126.4min speed=...这表示阵列已经创建并处于active状态,4块盘都是UNKNOWN状态,正在后台重算校验数据。这部分初始同步过程是必须的,因为RAID 5的校验数据需要基于整块盘的数据计算出来。重建未完成之前,阵列已经可以格式化挂载,但性能会偏低。我的建议是等初始同步完成后再切换到正式业务使用,至少不要在同步期间承载较重的写入负载。
3.4 格式化、挂载与持久化配置
阵列创建完,格式化这一步很直观:
mkfs.ext4 /dev/md0文件系统选哪个,取决于用途。通用文件存储,ext4成熟稳定,够用。如果对元数据检索、快照有更强需求,可以考虑xfs。我见过的多数NAS方案,ext4是不出错的稳妥选择。格式化时可以顺手加一个卷标,比如“datastore”,以后挂载时也可以直接用LABEL引用:
mkfs.ext4 -L datastore /dev/md0接下来创建挂载点并挂载:
mkdir /data mount -o noatime /dev/md0 /datanoatime选项的意思是访问文件时不更新访问时间戳,对文件服务器来说能减少不必要的元数据写入。对阵列寿命和性能都有好处。
关键的一步来了:如果不做持久化配置,系统重启后mdadm可能不会自动重新组装阵列。很多人栽在这一步,后面我看到。生成配置文件的命令如下:
mdadm --detail --scan >> /etc/mdadm/mdadm.conf需要确认一下,不同发行版下配置文件路径不完全一样,有的在/etc/mdadm.conf,有的在/etc/mdadm/mdadm.conf。自行根据环境创建目录并写入即可。之后再更新一下initramfs,确保开机阶段就能识别阵列:
update-initramfs -u在基于RPM的发行版上,对应的命令可能是dracut --force。这一步做完后,最后一次检查就是把/etc/fstab里加上阵列挂载项。我的建议是以UUID方式写挂载项,避免盘符漂移导致挂载失败。先拿到UUID:
blkid /dev/md0然后在/etc/fstab中追加形如下面的行:
UUID=xxxxxx /data ext4 defaults,noatime 0 2写完fstab后,务必执行一次mount -a验证所有挂载项是否正确,防止错误的fstab导致开机卡在恢复模式。这一步极容易被忽略,出问题后启动时整个系统都会进入紧急模式,非常烦躁。
3.5 阵列优化与性能验证
阵列创建完成后,我一般会做几处优化。
首先是调整md0的同步速度参数。系统默认会在后台同步时占用较高的IO资源,导致业务读写变得很慢。如果你的机器承载着其它在线业务,可以通过下面两个文件把同步速度限制得更低:
echo 50000 > /sys/block/md0/md/sync_speed_max echo 1000 > /sys/block/md0/md/sync_speed_min这里的单位是KB/s。限制之后,初始同步会拖得久一点,但至少不影响日常操作。如果你完全不限制,同步会尽力而为,导致系统卡顿,这也是某些人觉得“软RAID很卡”的原因之一,其实是没控制好同步速率,不是软RAID本身慢。
其次,可以调整顺序读的预读缓存。Linux的md设备默认可能只有256KB左右的read-ahead,对大文件连续读取不太友好。我习惯加大一些:
blockdev --setra /dev/md0 65536参数单位不是字节而是512字节扇区,65536意味着预读32MB。对于NAS类存储场景,这个值能让大文件顺序读性能提升明显。如果你想在开机时也保持这个设置,可以把命令放到rc.local或systemd service里。
最后是性能测试。很多人建完阵列后直接用dd跑一次,看到数字高兴一下就算完了。我建议至少测两种模式:大文件顺序读写和小文件随机读写。使用dd可以简单地测顺序读写:
dd if=/dev/zero of=/data/testfile bs=1M count=2048 conv=fdatasync dd if=/data/testfile of=/dev/null bs=1M count=2048测完删除测试文件。如果要更严谨地模拟真实业务,可以用fio之类工具跑一小段随机读写测试。不过别忘了,测试结果受文件系统缓存、网络传输速度、CPU负载多种因素影响,同一个阵列不同时间段测出来的数字有起伏是正常的。统一测试条件,持续多次取平均值才有参考意义。
在我实际经验中,一个由4块普通机械盘组成的RAID 5,用小文件连续写入测速大约能跑到200MB/s以上,而千兆网卡的上限只有大约110MB/s,所以在绝大多数应用场景里,网络的带宽早就成了瓶颈。这也是为什么软RAID性能在家庭和小型办公场景中完全够用的原因。
4. 日常维护与监控:让阵列活得久一点
4.1 状态检查三板斧
阵列装好之后,最忌讳的就是“装完再也不看”。磁盘毕竟是机械结构,坏盘是必然事件,只是时间早晚问题。定期检查阵列状态,是运维里最简单也最有效的防护措施。
最常用的三组命令是:
cat /proc/mdstat这个命令告诉你阵列当前处于什么状态。如果看到[UUUU]表示所有盘在线正常。如果看到[UU_U]表示有一块盘处于失效状态。或者看到“degraded”字样,说明阵列已经掉了一块盘,进入降级模式。出现这种情况要立刻行动。
第二组:
mdadm --detail /dev/md0这个命令输出完整的阵列信息,包括每块盘的角色、状态、故障计数、同步进度。我最关注的是State字段,正常显示“clean”,降级模式会显示“degraded”,正在同步则显示“resyncing”或“checking”。另外还会列出每块盘的类型为“active”还是“spare”。
第三组是自己写的简单监控脚本,定期检测:
mdadm --monitor --scan --test --oneshot也可以结合crond定期把mdstat的状态发到系统日志。再配合smartctl查看每块盘的SMART健康信息:
smartctl -a /dev/sdb关注Reallocated_Sector_Ct、Current_Pending_Sector、Offline_Uncorrectable这几个属性。一旦有大量重映射扇区出现,这块盘就该进观察名单了。SMART健康状态在盘真正彻底坏掉之前就会给出征兆,学会了看它,基本上能避免绝大多数突然死亡情况。
4.2 热备盘与故障模拟演练
热备盘是个很容易被忽略的好设计。简单说,你在阵列里预留一块空闲盘,平时它不参与读写,一旦检测到某块盘失效,阵列会自动把这块热备盘加入,并自动开始重建数据。
添加热备盘的命令:
mdadm --add /dev/md0 /dev/sdf添加后,用mdadm --detail查询,你会看到这块盘的状态显示为“spare”。之后任何一块工作盘出问题,它就会被自动提升为active盘并开始重建,整个过程不需要人工介入。
如果连通了通知机制,你甚至可以在盘坏的瞬间收到邮件或系统日志告警。mdadm的monitor模式可以监控到状态变化:
mdadm --monitor --program=/path/to/alert-script --mail=you@example.com --delay=60 /dev/md0我强烈建议在正式开工前做一次故障模拟演练,不要等真的坏盘了再去学习。模拟故障的命令是:
mdadm --fail /dev/md0 /dev/sdc执行后阵列会立刻标记这块盘为error,热备盘随即顶上,开始重建。这时候再手动执行:
mdadm --remove /dev/md0 /dev/sdc把已经失效的盘从阵列中移除,之后关机,换成新的物理盘,再重新加入:
mdadm --add /dev/md0 /dev/sdc整套流程走一遍,你心里才有底。很多新手第一次遇到坏盘时手忙脚乱,就是因为没有提前演练过。另外要记住:不要热插拔不支持热插拔的普通SATA盘,先关机再操作,否则可能连主板带盘一起带走。
4.3 阵列扩容与迁移
随着数据增长,阵列容量不够用是迟早的事。软RAID的扩容思路是在线扩容,但代价是耗时很长,尤其是在机械盘阵列上。
以RAID 5为例子,扩容有两种方式。
一种是增加新盘。先加入新盘作为spare,然后执行:
mdadm --grow /dev/md0 --raid-devices=5系统会把新盘加入阵列,然后重新调整条带布局。这个过程会遍历全盘数据重新整理校验信息,速度取决于磁盘本身的读写速度。4块盘扩容到5块盘,以单盘150MB/s的写入速度计算,整个reshape过程可能是小时级甚至更久。
另一种方式是换更大容量的盘。你可以做滚动替换:把一块盘标记为failed并移除,换成4TB的新盘,等系统开始重建后再替换下一块,直到所有盘都替换完成。最后执行:
mdadm --grow /dev/md0 --size=max来扩展文件系统。这种方式的风险在于,在替换过程中阵列是处于“已经有一块失效盘”的状态,如果再有盘故障,数据会彻底丢失。所以我一般只在有完整备份的情况下才敢做这种操作。
扩容并不是不能做,但需要了解其风险。如果在生产环境中觉得空间吃紧,更稳妥的方案是先备份、停机、离线重建一个大容量的新阵列,再把数据拷过去。很多人的操作习惯是总希望在线扩容省事,结果却在reshape过程中暴露了磁盘隐患,最后得不偿失。
5. 常见问题与排查技巧实录
5.1 开机后阵列消失
“我明明建好了阵列,为什么重启后/dev/md0不见了?”这是问得最多的一个问题。
绝大多数原因是mdadm.conf配置文件缺失或损坏。在创建完阵列后,如果忘了执行mdadm --detail --scan把配置写入文件,或者写入的路径不对,开机后系统根本不知道有一个阵列需要组装。
排查方式先看当前状态:
cat /proc/mdstat如果只有“Personalities”一行,下面没有任何md设备,说明阵列没有被自动装配。可以用手动组装的方式先恢复:
mdadm --assemble /dev/md0 /dev/sdb /dev/sdc /dev/sdd /dev/sde如果设备名漂移了,比如原先是sdb、sdc,现在变成了sdd、sde,用盘符组装可能失败。这时可以改用磁盘的uuid或by-id路径来确定成员盘。先查看每个盘的元数据:
mdadm --examine /dev/sdb /dev/sdc /dev/sdd /dev/sde输出里会有该磁盘参与的阵列UUID。确认这几个盘的UUID一致之后,再用--assemble --scan命令尝试自动搜索并组装。手动组装成功之后,再把扫描结果重新写入配置文件。切记,要让系统重启后稳定识别,最好使用设备的UUID引用方式,而不要依赖盘符。
5.2 阵列降级或挂掉
阵列降级指的就是阵列中一块盘失效,但阵列本身还能读写的过程。此时执行cat /proc/mdstat看到的状态组合里有个__标记,或者在mdadm --detail的输出里看到“degraded”字样。
降级之后的首要任务不是立刻找盘替换,而是先在另一套媒介上做一次紧急备份。RAID 5降级后,数据仍在,但已经失去冗余。如果第二块盘也坏了,整个阵列就会直接变成inactive,数据基本只能靠专业数据恢复手段抢救。备份做完后,再去找合适的替换盘,执行替换重建。
有时候遇到阵列直接无法挂载的情况,可能是多块盘同时故障,或者文件系统层面出现了严重错误。这时候不要慌,更不要反复尝试自动修复操作。第一步是保持阵列设备原样,用mdadm --detail查看哪些盘还在线,哪些盘被标记fail。如果只是元数据错乱导致阵列被标记为inactive,通常可以通过强制组装恢复:
mdadm --assemble --force /dev/md0 /dev/sdb /dev/sdc /dev/sdd但“force”是把双刃剑,它可能掩盖真正的数据一致性问题。我给自己定的规矩是:只有当所有成员盘都能通过SMART健康检查、排除物理坏盘后,才允许使用force参数。如果怀疑有盘物理损坏,优先做磁盘级别的映像备份,再做任何修复,不要拿原始盘去赌。
5.3 重建卡住或中断
盘坏之后换上热备盘开始重建,这是最令人揪心的过程。重建数据时,系统要读取所有健康盘上的数据,计算出丢失的部分写入新盘。一旦原本就有隐患的盘在连续高负载读写下扛不住,可能又出现新的失效盘,那就是灾难。
重建过程卡住,最常见的原因有两个:一是磁盘本身存在大量坏道,SMART状态已经亮红灯,但你以为“还能用”;二是你在重建期间还在正常进行高强度的业务读写,阵列本来已经任务很重,重建速度被拖到极慢。
让重建更稳的办法就两条:控制同步速度,给阵列减负。前面提到的sync_speed_max参数在这里再次派上用场。比如设置最高20000KB/s一旦磁盘重试过多就触发超时掉盘,那才是真正的灾难。不要迷信磁盘的自动纠错能力,给点温和的节奏。
如果重建确实中断了,先看dmesg输出有没有明显的IO错误。如果报错指向某块盘读取失败,很可能是该盘彻底不行了。这时候第一选择是找另一块盘替换它,而不是强行继续。我见过有人硬凑着同盘继续,结果数据越读越残。在重建过程中,一旦有一个新盘退出,我都会先停下来冷静评估,而不是立刻重启重建任务。
5.4 性能不符合预期
阵列建好了,性能却差强人意。这类问题通常有三种来源。
第一种是阵列本身还在同步中。初始同步或重建期间,阵列负载很高,这时的测试数据几乎没有参考价值。请等状态完全clean后再进行性能测试。
第二种是条带块大小和文件系统参数不匹配。如果你用默认工具格式化ext4时指定了较大的chunk,或者反过来文件系统块大小与条带块大小差距悬殊,都会导致读写效率打折。创建ext4时可以用参数指定条带大小:
mkfs.ext4 -E stride=16,stripe_width=48 /dev/md0这里的stride=16表示逻辑块数为16个4KB块,即64KB条带;stripe_width是数据盘数量乘以stride。但普通用户不一定需要手动设置,很多场景下默认参数也能用。只有当性能测试表现明显差时,我会建议重新格式化并用这些参数重试。
第三种是被网络瓶颈卡住。如果你通过SMB/NFS访问阵列,测出来速度就只有网卡的上限,那是链路的问题,不是阵列的。想排查时,最好先在服务器本地上用dd或fio测试,再对比网络挂载下的速度。分开能不能测出差别,多跑几次就知道了。
还有一点我多说一句:不要用IOPS这类指标去要求机械盘RAID 5。机械盘阵列的强项是大吞吐量的顺序读写,随机小IOPS就是弱项。如果业务偏重随机小文件,要么上固态加速,要么用RAID 10。选择一个合适方案与你的负载模型匹配,比事后调优有效得多。
5.5 误操作恢复
最后说一类不太敢讲但经常遇到的问题:误操作。
比如不小心执行了mdadm --stop /dev/md0,然后系统也在运行,阵列看起来像消失了。此时不要慌,不要执行任何重建或重新创建操作。先检查磁盘上的元数据是否还在:
mdadm --examine /dev/sdb如果元数据还在,直接手动组装:
mdadm --assemble /dev/md0 /dev/sdb /dev/sdc /dev/sdd /dev/sde通常可以恢复正常。如果误格式化了文件系统,情况就麻烦多了,需要立即停止对阵列的一切写入,关闭自动挂载,交给专业的数据恢复工具处理。这类情况下,越早停止操作,恢复概率越高。
我在实际中见过不少本可以避免的灾难:有的只是在维护时敲错了设备名,有的搞混了盘符,把原本规划的热备盘当成裸盘重建了。所以我的习惯是:凡是会改变设备内容的命令,执行前都一再确认设备路径,fdisk和mkfs这类高危命令必须反复看两遍再执行。给自己写一张“设备对照表”贴在屏幕旁边,比什么都要管用。
最后再分享一个我的真实体会。每次给存储服务器做完软RAID,我都会花时间完整地做一次“销毁式演练”——故意模拟盘故障,故意重启机器,故意在混乱中尝试恢复。很多人觉得这是在浪费时间,但正因为做过这些演练,真出事的时候我才能不慌不忙地把阵列救回来。软RAID是一个可靠的工具,但它值得你用心对待它。把热备盘配上,把监控脚本跑起来,把配置备份下来,然后放心让它为你工作。数据安全这件事,从来不是单靠某一个环节能解决的,而是一整套习惯的结果。