1. 服务器磁盘的“拼车”逻辑:为什么单块硬盘顶不住生产环境
我之前在运维一线待了不少年,遇到过最让人头疼的场景之一就是:半夜两点,监控告警响起来,某台数据库服务器的数据盘掉了。如果是单块盘直通,那基本就是听天由命,要么从备份恢复,要么花大价钱找数据恢复公司。但如果当初老老实实做了RAID,这时候只需要顶着降级状态继续跑,等白天上班再拿一块新盘替换上去,数据自动重建,有惊无险。
这就是RAID要解决的核心问题:把多块物理硬盘组合成一个逻辑卷,通过冗余或条带化换取性能或安全性。在Linux的磁盘管理体系中,RAID是一个绕不开的环节,特别是当你在管理物理机、自建存储、或者搭一套需要高可用的服务时,磁盘阵列几乎是标配。
很多刚接触Linux的人会有一个误区:觉得RAID是服务器硬件厂商的“黑科技”,要在BIOS里设置,要买专门的阵列卡,好像离软件层面很远。但实际上,Linux内核原生支持一套非常成熟的软RAID方案——md(Multiple Device),配合mdadm管理工具,可以在完全没有硬件阵列卡的情况下,用几块普通SATA盘或SSD搭出一套稳定的阵列。这也是生产环境中很常见的降本方案,尤其是对预算有限的团队而言,一台旧服务器加上几块二手盘,就能模拟出硬RAID的大部分效果。
这篇文章围绕Linux磁盘管理中的RAID展开,会从底层原理、级别选型、软硬RAID差异、mdadm实操、故障替换、监控优化六个维度拆解。不管你是刚接触Linux的小白,还是已经能熟练操作fdisk但没真正碰过阵列的运维,这篇文章都能给你一套能直接拿去用的方案。
动手之前,先给这篇文章定个调:RAID不是用来替代备份的,它解决的是硬件故障下的可用性问题,而不是误删、勒索病毒、逻辑损坏这类“人祸”。明白了这条底线,后面很多设计决策就顺理成章了。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. RAID级别选型:0/1/5/6/10到底怎么选
RAID的全称是Redundant Array of Independent Disks,独立磁盘冗余阵列。从名字就能看出,它的核心思路是让多块硬盘协同工作,形成一个逻辑设备。但不同级别的协同方式差别巨大,选错级别,要么性能浪费,要么冗余不足,要么重建时间长得让人绝望。
2.1 从条带化到镜像:RAID 0和RAID 1的底层逻辑
RAID 0说白了就是条带化(Striping)。数据按块大小(chunk size)切分,轮流写到每块盘上。比如你有一个100MB的文件,chunk设为256KB,那数据就会被切成很多256KB的小块,依次落在disk0、disk1、disk2上。这样做的最大好处是读写并行,多块盘同时工作,吞吐量随盘数线性增长。代价也很直观——任何一块盘损坏,整个阵列上所有数据全部丢失,因为文件被切碎了分散在各块盘上,缺一块就拼不回来。
RAID 1就不太一样,它是镜像(Mirroring),每个数据块会同时写入两块盘,两块盘上的内容完全一样。读取的时候可以从任意一块盘读,所以读性能理论上接近翻倍,写入性能则和单盘差不多(因为两块盘要写同样的数据)。冗余度最高,两块盘坏一块,阵列照常工作。但空间利用率固定为50%,两块2TB的盘做RAID 1,可用空间只有2TB。
我见过不少刚起步的小公司,为了追求容量和性能,直接用两块盘做RAID 0当系统盘,结果盘一坏,整个服务器的操作系统、配置、业务代码全都没了。后来花大价钱恢复数据也未必成功。当时我就跟他们说:RAID 0不是不能用,但用的场景非常狭窄,基本上只适合那些即使数据全部丢失也无所谓、但追求极致吞吐的场景,比如缓存服务器、临时计算节点,而且必须配合上游的分布式系统保证数据副本。
2.2 性价比之王的代价:RAID 5和RAID 6的容错与重建窗口
RAID 5在业界使用率最高,它采用条带化加分布式奇偶校验(Distributed Parity)的方式。每次写入数据的同时,会计算一份校验信息,均匀分布在所有磁盘上。如果一块盘坏了,系统可以靠其他盘上的数据和校验信息反推出那块丢失盘上的内容。空间利用率是N-1块盘,比如4块2TB的盘,可用6TB,比RAID 1高得多。
但RAID 5有一个经常被忽视的软肋:重建窗口期的二次故障风险。当一块盘损坏后,阵列进入降级模式,此时其余所有盘上的数据要持续读取、计算校验并重建到新盘上。这个过程中,如果任何一块盘再出问题(高位负载下老盘很容易撑不住),整个阵列立即崩溃,数据会彻底丢失。对现代大容量硬盘而言,RAID 5的重建可能要跑十几个甚至几十个小时,这么长的高强度读写窗口,对老盘来说无异于酷刑。所以现在的共识是:超过4块盘的阵列,或者单盘容量超过4TB,强烈建议用RAID 6。
RAID 6比RAID 5多一份独立校验,允许同时坏两块盘。代价是写入性能比RAID 5差一些(每次写数据要更新两份校验信息),空间利用率是N-2块盘。
2.3 兼顾性能与冗余的“万金油”:RAID 10
RAID 10(也叫RAID 1+0)是先做镜像,再做条带化。比如4块盘,先两两配对组成两个RAID 1,再把这个两个RAID 1组成RAID 0。它的优点是读写性能都很优秀(读可以从多个镜像对并行读,写也因为是纯条带化+镜像、无需计算校验而性能出色),冗余度也高,且重建速度快(只需要重建镜像对中的那块盘)。
空间利用率和RAID 1一样,只有50%,是所有冗余方案中成本最高的。但数据库场景、虚拟化平台、核心业务服务器,我基本都是无脑推荐RAID 10。原因很简单:数据库的写操作非常密集,RAID 5的写惩罚机制(写一个数据块要读旧数据、读旧校验、写新数据、写新校验四个IO)在写多读少的场景下是性能灾难,而RAID 10没有校验计算,内部可以更高效地处理随机写。
| 级别 | 最低盘数 | 容错能力 | 空间利用率 | 写入性能 | 读出性能 | 适用场景 |
|---|---|---|---|---|---|---|
| RAID 0 | 2 | 无 | 100% | 高 | 高 | 缓存、临时数据、可丢弃场景 |
| RAID 1 | 2 | 1块 | 50% | 等于单盘 | 接近2倍 | 系统盘、日志盘 |
| RAID 5 | 3 | 1块 | (N-1)/N | 中(写惩罚) | 高 | 文件存储、备份存储、读多写少 |
| RAID 6 | 4 | 2块 | (N-2)/N | 低 | 高 | 大容量存储、归档 |
| RAID 10 | 4 | 每组1块 | 50% | 高 | 高 | 数据库、虚拟机、生产核心业务 |
2.4 硬件RAID与软RAID的本质差异
搞清楚了级别,接下来要面对一个更实际的问题:这套阵列由谁来控制?这里面存在两条完全不同的技术路线。
硬件RAID靠的是专用的RAID卡,卡上有独立的CPU和缓存,所有的条带化计算、校验计算、数据缓存都在卡上完成,操作系统看到的只是一个单一的虚拟磁盘。优点是不占用宿主机CPU资源,性能稳定,掉电时卡上缓存带电池保护可以保证数据不丢失。缺点是贵,一块带电池和缓存的中端阵列卡就要几千块,而且一旦RAID卡坏了,如果换的不是同型号同固件版本的卡,很可能认不出阵列配置,数据照样玩完。需要注意的是,硬件阵列卡的配置界面通常是在服务器POST阶段按Ctrl+C或Ctrl+R进入的,不同厂商的卡操作按键不一样,有时候在装机现场会因为找不到配置界面而卡壳。
软件RAID是靠操作系统内核实现的,Linux下就是md模块。数据条带化、校验计算全部由CPU完成,不需要额外硬件。配置非常灵活,可以用mdadm命令随时创建、扩展、删除阵列,而且没有硬件绑定的问题——把一组软RAID盘拆下来插到另一台Linux机器上,只要mdadm conf配置正确就能识别。缺点是校验计算会占用一部分CPU,但现在的服务器CPU性能都不差,RAID 5的校验计算对CPU的压力其实微乎其微,实际测下来,在普通Xeon或Core系列处理器上,软件RAID 5/6的性能已经能满足大量中小业务的存储需求。
我在多个项目里的经验是:如果服务器没有配硬件阵列卡,或者你希望不受硬件绑定的限制,直接用Linux软RAID就好,它能覆盖大多数非极致性能场景。真正需要硬件RAID的,是那种对吞吐和时延要求极其苛刻的数据库、生产虚拟化集群,且必须配备掉电保护缓存模块。
3. 软件RAID实操:用mdadm从零搭一组阵列
理论说透了,下面直接进入能落地的部分。我用三块全新的20GB虚拟磁盘做演示,实际环境里可以是任意容量的物理盘或云盘。整个操作分为创建、格式化、挂载、持久化四个阶段。
3.1 环境准备与确认磁盘设备
先确认磁盘设备名。在Linux中,可以通过lsblk或fdisk -l查看所有块设备信息。这里要特别提醒:生产环境操作前必须反复确认盘符,因为SATA盘在系统里的设备名(如sda、sdb)可能会因为接入顺序、驱动加载顺序不同而变化,很多灾难事故都是因为搞错了盘符,把有数据的盘给格式化掉了。
bash复制lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 20G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 19G 0 part
├─centos-root 253:0 0 17G 0 lvm /
└─centos-swap 253:1 0 2G 0 lvm [SWAP]
sdb 8:16 0 20G 0 disk
sdc 8:32 0 20G 0 disk
sdd 8:48 0 20G 0 disk
sdb、sdc、sdd这三块盘是新加的,没有分区,也没挂载,非常适合拿来做实验。如果这几块盘曾经被使用过,里面残留分区表或文件系统信息,创建RAID前最好用wipefs清一下,否则mdadm可能会识别出旧信息导致麻烦。
bash复制wipefs -a /dev/sdb /dev/sdc /dev/sdd
这里简单解释一下为什么建议不用分区而直接用整块盘做软RAID:mdadm支持直接用整块盘创建,也支持在盘上先建分区再拿分区来创建。直接使用整块盘在替换坏盘时很方便(新盘插上就能用),缺点是盘上没有任何分区表,有些管理工具查不到这块盘的用途,需要靠mdadm --detail去看。用分区(比如把一块2TB盘分成一个2TB主分区)更符合传统习惯,但替换坏盘后需要先执行partition和mdadm --add两步操作,稍微繁琐一点。两种方式我都试过,如果盘是阵列专用,我倾向直接用整块盘,省事且不容易在替换时因分区表不一致出问题。
3.2 创建RAID 10阵列的完整命令
以RAID 10为例(四块盘最佳,但我这里实验环境有三块盘,三块盘做RAID 10其实并不标准,所以我们改用三块盘做RAID 5演示经典方案,同时补充RAID 10的命令供参考)。
创建RAID 5(三块20GB盘,可用空间40GB):
bash复制mdadm --create /dev/md0 --level=5 --raid-devices=3 /dev/sdb /dev/sdc /dev/sdd
创建RAID 10(四块盘,命令供参考):
bash复制mdadm --create /dev/md0 --level=10 --raid-devices=4 /dev/sdb /dev/sdc /dev/sdd /dev/sde
执行后系统会提示Continue creating array?,输入y。之后可以通过cat /proc/mdstat实时查看构建进度。
需要说明一下--create的参数含义:
/dev/md0:阵列的设备名。系统会按md0、md1、md2这样自动编号,你也可以用--name=raid5_data给阵列取一个有意义的名字,方便识别。--level=5:RAID级别,可以是0、1、5、6、10。--raid-devices=3:组成阵列的物理盘数量。- 后面的三个设备路径:指定哪些盘参与阵列。
创建命令执行后,可以加一个--chunk参数指定条带大小。RAID 5的chunk默认是512KB,这个值对性能影响非常大。数据库随机读写场景用64KB左右效果更好,视频大文件持续读写场景用256KB甚至1MB更合适。chunk大小是创建时定死的,之后无法动态修改,只能重建阵列,所以务必想清楚再动手。
3.3 查看构建进度与阵列状态
创建完成后,用cat /proc/mdstat查看状态:
bash复制cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4]
md0 : active raid5 sdd[2] sdc[1] sdb[0]
41906176 blocks super 1.2 level 5, 512k chunk, algorithm 2 [3/3] [UUU]
[>....................] resync = 2.5% (1054720/41906176) finish=1.2min speed=563200K/sec
字段解读:
active raid5:阵列处于活动状态,级别是RAID 5。sdd[2] sdc[1] sdb[0]:组成阵列的盘及其在阵列中的序号。41906176 blocks:总容量约40GB,对应三块20GB盘在RAID 5下的可用空间。[3/3] [UUU]:阵列有3块盘,当前3块都在线。U表示Up正常,_表示盘缺失或故障。resync:表示正在进行一致性同步,也就是后台在计算和写入校验信息,这个过程完成后阵列才达到全性能状态。
mdadm --detail /dev/md0可以查看更详细的阵列信息,包括每块盘的角色、状态、故障记录等。这是一条我在排查阵列问题时会第一时间敲的命令,后面的故障排查也全靠它。
3.4 格式化和挂载到目录
阵列创建完成后,还不是一个可直接使用的文件系统。需要先在/dev/md0上创建文件系统,然后挂载到某个目录。
格式化为ext4:
bash复制mkfs.ext4 /dev/md0
如果希望用XFS(CentOS/RHEL 7+默认文件系统,对超大容量支持更好,在线扩容更方便):
bash复制mkfs.xfs /dev/md0
挂载到/data目录:
bash复制mkdir -p /data
mount /dev/md0 /data
3.5 持久化配置:让阵列重启后自动生效
到了这一步,阵列能正常用,但重启系统后/dev/md0不会自动挂载,mdadm也不会自动重新组装阵列。Linux启动时默认不会去识别软RAID,需要把配置写入配置文件,否则下次开机进去发现/data目录是空的,业务就全崩了。
手动生成配置文件:
bash复制mdadm --detail --scan >> /etc/mdadm.conf
然后在/etc/fstab中添加一行,让系统启动时自动挂载:
bash复制echo '/dev/md0 /data ext4 defaults 0 0' >> /etc/fstab
这里有一个非常关键的坑,我踩过不止一次:如果阵列里的盘是整块盘(无分区),设备名如/dev/sdb在系统重启后可能变成/dev/sdc。因为Linux在启动时发现新硬件时,设备名的分配顺序不保证和之前一致。如果fstab写的是/dev/md0,那没问题,因为mdadm配置的是内部的UUID;但如果哪天你重建了系统,盘序变了,md0里的盘成员识别是靠UUID而不是盘符的,这正好是软RAID的优势。不过要提醒,在部分发行版下,/etc/fstab里使用/dev/md0是安全的,因为内核在识别到软RAID设备后会分配固定的设备号;但如果系统上同时存在多个RAID设备,编号可能会变化。更稳妥的做法是在/etc/fstab里用UUID替换设备名:
bash复制blkid /dev/md0
# 输出类似:/dev/md0: UUID="4f1e9f78-9c02-45a4-8f66-59f15cb0f955" TYPE="ext4"
然后把fstab那一行改成:
bash复制UUID=4f1e9f78-9c02-45a4-8f66-59f15cb0f955 /data ext4 defaults 0 0
另外,/etc/mdadm.conf里保存的是ARRAY /dev/md0 metadata=1.2 name=xxx UUID=xxxx这样的内容。mdadm在启动时会根据这个文件去扫描所有磁盘,找到对应的UUID并组装。有个细节:执行mdadm --detail --scan前需要保证md0处于活动状态;如果系统启动时阵列没有自动组装成功,需要手动执行mdadm --assemble --scan来尝试从MD超级块中自动发现并组装所有软RAID设备。
4. 故障模拟与恢复:硬盘掉了怎么办
搭建只是一个开始,日常运维中最常见的操作其实是故障替换。下面模拟一块盘坏掉的完整过程,并给出每一步的排查和修复命令。
4.1 模拟一块盘损坏后的阵列状态
生产环境中盘故障的表现各式各样:有的直接IO报错、盘符从系统中消失;有的虽然还在线但SMART指标狂跳、读写超时;有的干脆是缓慢变慢,性能明显劣化。我这里的操作是把一块盘从阵列中直接标记为故障,模拟最直接的坏盘场景。
bash复制mdadm --manage /dev/md0 --fail /dev/sdc
执行后立即看状态:
bash复制cat /proc/mdstat
md0 : active raid5 sdd[2] sdc[1](F) sdb[0]
41906176 blocks super 1.2 level 5, 512k chunk, algorithm 2 [3/2] [_UU]
(F)表示这块盘已标记为fault,[3/2]表示阵列共3块盘但当前只有2块正常工作,_UU说明第一个槽位的盘不可用,第二、第三个是正常的。此时整个RAID 5阵列处于降级模式,数据仍然可读写,但已经失去了容错能力,再坏一块就是全军覆没。
用mdadm --detail /dev/md0查看详细信息时,会看到State : clean, degraded字样,并且/dev/sdc那一行有Faulty标记。
4.2 从阵列中移除故障盘并替换新盘
确认盘确实坏了之后(最好先在系统层面用dmesg确认是不是线缆问题或盘符漂移),将其从阵列中移除:
bash复制mdadm --manage /dev/md0 --remove /dev/sdc
如果是整块盘直接做的阵列,拔掉旧盘后把一块新盘插到同一个槽位,新盘会被系统识别为一个设备(比如sdc),然后执行:
bash复制mdadm --manage /dev/md0 --add /dev/sdc
注意,新盘会被当作热备盘(spare)加入,随后mdadm会自动开始数据重建(rebuild),不需要手动触发。
如果是未分配的盘插入后系统没有自动识别,可能需要先执行echo '- - -' > /sys/class/scsi_host/host0/scan之类的命令触发SCSI扫描,新盘才会出现在系统里。热插拔故障盘时这一步很常见,具体host编号要根据lsscsi或/sys/class/scsi_host/下的目录来确认。
4.3 重建期间最需要注意的事
重建启动后,/proc/mdstat会显示类似这样的进度:
bash复制md0 : active raid5 sdc[3] sdd[2] sdb[0]
41906176 blocks super 1.2 level 5, 512k chunk, algorithm 2 [3/2] [UUU]
[>....................] recovery = 3.5% (1474560/41906176) finish=8.3min speed=83211K/sec
注意此时的状态是recovery,和初始构建时的resync略有区别。recovery表示有一块盘在重建,从其他盘读取数据重新计算并写入新盘。重建速度取决于盘的性能和新盘的写入速度,机械盘通常在50到150MB/s之间,所以一块4TB的盘全量重建可能需要12到20小时。
重建期间有几点需要特别上心:
- 千万不要拔错盘。在槽位不明确或盘序没确认清楚的情况下强制操作,很容易把好盘摘下来。我曾经遇到一次现场操作,现场工程师把两块盘插反了,又把组阵列的顺序搞混,好在最后靠mdadm的UUID识别把阵列恢复回来。最稳妥的先确认每块盘的设备名与物理槽位的对应关系。
- 减小对阵列的压力。重建期间阵列的读写能力会明显下降,尤其RAID 5要同时应对业务IO和重建IO。对生产环境而言,如果业务允许,最好是低峰期做替换;如果必须即时替换,要考虑容量规划和业务限流。
- 观察SMART信息。重建完成后一定要用smartctl检测新盘的SMART值,确认这块盘不是“准坏盘”。
4.4 验证重建结果
重建完成后,用以下命令确认阵列状态完全恢复:
bash复制mdadm --detail /dev/md0
/dev/md0:
Version : 1.2
Creation Time : ...
Raid Level : raid5
Array Size : 41906176 (39.97 GiB 42.91 GB)
Used Dev Size : 20953088 (19.98 GiB 21.46 GB)
Raid Devices : 3
Total Devices : 3
State : clean
Working Devices : 3
Failed Devices : 0
Spare Devices : 0
State : clean且三块盘都在线(Working Devices: 3),说明阵列已经恢复健康。此时可以实际写文件测试数据完整性:
bash复制cd /data && dd if=/dev/urandom of=testfile bs=1M count=1024 && md5sum testfile
操作过程中你可能会发现,重建后原来的数据完全没丢,文件内容正常读写,这就是RAID 5的价值所在。但这里必须强调:降级模式下阵列能工作,但恢复数据的能力只有一份保障,所以在重建完成前,理论上任何一块盘的故障都会导致数据永久丢失,千万不要因为阵列还没挂就掉以轻心。
5. 生产环境里常见的RAID坑,以及我的应对习惯
理论和实操都过了一遍,下面分享一些我在实际运维中积攒下来的经验,这些都不是文档里能直接查到的,更多是换了环境、踩了坑以后才真正理解的东西。
5.1 关于缓存策略:write-back与write-through的选择
硬件RAID卡上有一个非常重要的缓存策略配置,常见的两种是write-through(直写)和write-back(回写)。write-through模式下,数据先写入磁盘再返回成功,安全性高但性能差;write-back模式下,数据先写入RAID卡上的缓存即返回成功,由缓存再异步刷入磁盘,性能大幅提升,但一旦掉电,缓存里尚未落盘的数据就会丢失,所以必须依赖RAID卡上的电池或闪存模块(BBU/电容)保护。
对软件RAID来说,Linux内核里也有类似的机制,默认情况下块设备层会有一定的写缓存。具体到软RAID,mdadm创建阵列时可以通过--write-behind等参数配置,但生产环境中使用软RAID时通常不需要刻意调整,因为文件系统层(如ext4的journal、XFS的日志)已经做了很多一致性保证。不过如果是跑数据库,建议把文件系统的barrier(内存屏障)功能打开,避免乱序写入导致的数据损坏。
我自己的习惯是:硬件RAID卡一定要确保缓存模块的电池健康,并定期检查。如果BBU老化失效,需要立即停用write-back模式,否则一次意外掉电可能造成整个文件系统损坏。软件RAID的话,我更倾向依赖XFS的日志机制,并且在业务低峰期进行定期一致性校验。
5.2 raid卡和软RAID的混用:别让两种情况互相干扰
有些服务器出厂自带了硬件RAID卡,但如果你直接插入裸盘,RAID卡默认可能会把它们配置成JBOD模式(Just a Bunch Of Disks)或者单盘RAID 0。这时候再在系统里创建软RAID,就会出现“硬件层RAID0 + 软件层RAID5”的嵌套。这种嵌套不是不能用,但会造成写惩罚叠加,性能极差,而且运维排查时非常容易搞混——到底是哪个层出了问题?
我处理过几次这种情况,最终的建议是:明确边界、二选一。要么硬件RAID卡接管所有磁盘做阵列,系统里只看到逻辑盘;要么把RAID卡切到JBOD或直通模式,让操作系统直接管理物理盘,所有冗余靠软件层做。两个方案都成立,但一定不要同时在两层做RAID。
具体到操作,戴尔、浪潮、惠普这些品牌的服务器,进RAID卡配置界面后把虚拟磁盘删除、把控制器模式切换为JBOD即可。在Linux下可以通过megacli或storcli(LSI芯片卡)查看和修改:
bash复制# 查看当前控制器模式(LSI卡)
storcli /c0 show
# 把全部物理盘设为JBOD模式
storcli /c0 set jbod=on
切换JBOD模式前务必备份好所有数据并确认无业务IO,因为操作可能会触发盘重建或丢失配置。
5.3 软RAID的监控脚本与邮件告警
RAID设备不像普通硬盘那样出现故障时屏幕上会弹大字告警。多数时候,阵列降级的信息只会静默地躺在/proc/mdstat里,如果不主动去看,可能业务已经跑在降级状态好几天了,而你又在这个时间窗口发生了第二块盘故障——那数据就真没了。所以,给软RAID配一个监控告警是必须做的第一件小事。
我写过一个非常简单的巡检脚本,配合cron每小时跑一次,一旦发现阵列出现降级或故障就发邮件:
bash复制#!/bin/bash
# check_raid.sh
MAIL_TO="ops@example.com"
CHECK=$(mdadm --detail /dev/md0 | grep "State :")
if echo "$CHECK" | grep -qE "degraded|resync"; then
echo "$CHECK" | mail -s "RAID Array Warning on $(hostname)" "$MAIL_TO"
fi
稍微复杂一点的做法是用mdadm --monitor守护进程,它能够监听事件(比如磁盘故障、重建完成)并触发警报或脚本。一般会和/etc/mdadm.conf里的MAILADDR配合使用。
bash复制mdadm --monitor --scan --daemon
但这里要说个常识:邮件告警的前提是服务器本来就能发外网邮件,很多内网机器并没有配置邮件通道。所以更通用的方案是接入企业的监控系统,比如Zabbix、Prometheus + Alertmanager,通过对/proc/mdstat或node_exporter暴露的mdadm指标做监控报警。总之,监控必须做,不管用什么方式,让告警能够触达值班人员是最低要求。
5.4 要不要预留热备盘
热备盘(hot spare)是阵列中一块闲置的物理盘,不参与数据读写,但当阵列里任意一块盘故障时,会自动顶替上去并开始数据重建,不需要人工干预。这看起来非常方便,能显著缩短系统处于“无冗余”状态的时间,对关键生产环境来说价值很大。
但热备盘的使用有几个前提条件:首先,阵列中要预留出物理槽位和SATA/SAS通道;其次,热备盘的容量必须大于等于阵列中现有盘(具体取决于RAID卡或mdadm的规则);第三,如果你用的是服务器厂商的硬件RAID卡,热备盘有全局热备和专用热备之分,配置时务必定好作用范围,专用热备只对指定阵列有效,全局热备对控制器管理的所有阵列有效。
在软RAID中添加热备盘的命令是:
bash复制mdadm --manage /dev/md0 --add --spare /dev/sde
添加后查看状态,会看到Spare Devices : 1。这样以后一旦某块盘故障,系统会自动开始重建,无需人工介入。
不过,基于我个人的使用体验:热备盘并不应该成为你不监控阵列的理由。即使有热备盘,重建期间阵列依然没有冗余能力,而且热备盘通常会长期处于通电待命状态,反而更容易积累通电时间去老化。热备盘是保障机制,真正的核心还是依靠人工巡检及时发现问题。
6. 我对soft RAID性能调优的几个实测建议
很多人在用软RAID时担心性能差。其实对于机械硬盘阵列,软RAID因为不用经过额外的硬件RAID卡处理,在纯吞吐场景有时候反而能跑出不输中低端硬卡的性能。问题通常出在参数没调对。
6.1 chunk大小:一个被严重低估的参数
前面提到过chunk大小,这次用实测数据来量化说明一下。我在一组6块2TB的7200转SATA盘上做过对比测试,RAID 5,分别创建了64KB、512KB(默认)和1MB的chunk,再用fio做了4K随机写和1MB顺序写的基准测试:
| chunk大小 | 4K随机写(TPS) | 1MB顺序写(MB/s) |
|---|---|---|
| 64KB | 约860 | 约780 |
| 512KB | 约720 | 约860 |
| 1MB | 约690 | 约900 |
结论很清楚:小chunk对随机IO更友好,大chunk对顺序IO吞吐有优势。原因在于:数据块越小,条带分布就越细,随机IO可以更均匀地分摊到多块盘上;但chunk太小会让校验计算的分块更频繁,对CPU用量稍有影响,同时对于大文件写入,如果chunk设置过小,单次IO需要访问的盘数变多,反而会增加延迟。
所以调优时不要直接跟风用默认值,而是要结合业务形态想清楚:数据库事务日志用64KB比较好;视频转码输出、大数据离线分析这种顺序读写的,256KB到1MB效果更明显。
6.2 mdadm的readahead和调度器设置
软RAID默认会设置一个readahead值,可以理解为“预读策略”——在读取文件时,内核会额外读取内容到内存缓存中,以提高顺序读取性能。可以通过blockdev --setra调整。对于机械盘阵列,readahead设置在4096到8192(单位是512字节扇区,即2MB到4MB)比较合适;SSD阵列可以不用太大,因为随机访问本身延时低,预读反而浪费IO。
块设备IO调度器也需要关注。现在主流内核默认用none或mq-deadline调度器,不再需要像当年那样手动设置为cfq或noop。在大多数CentOS 7/8及以后的系统上,deadline在机械盘RAID上表现良好;NVMe和SSD用none更合理。可以通过cat /sys/block/md0/queue/scheduler查看当前调度器,临时切换用:
bash复制echo deadlink > /sys/block/md0/queue/scheduler
注意是deadline,不要拼错。如果想永久生效,用udev规则或tuned服务配置。
6.3 SSD缓存:给软RAID加速的另一个思路
机械盘做RAID,容量和冗余都解决了,但随机性能始终是硬伤。如果你手里有几块闲置的SSD,可以考虑用bcache或lvmcache给软RAID加一层SSD缓存,把热数据落到SSD上,冷数据留在机械盘阵列里。这个操作对数据库类场景的提升非常明显,有时候能把IOPS从几百直接拉到几万。
但要注意,SSD缓存并不会解决机械盘阵列本身的故障风险,它只是一个缓存层,缓存中的数据仍然来源于底层阵列。对生产环境来说,SSD缓存应该被视为性能优化手段,而不是一致性的保证手段。如果在缓存层出现问题,极端情况可能影响数据完整性,所以实施前要做足备份和测试。
LVM cache的配置大致是:创建LVM卷组,然后用lvcreate --type cache把SSD设备和机械盘阵列组合成一个带缓存的逻辑卷。bcache的配置则更复杂,需要先make-bcache -B /dev/md0 -C /dev/sdx创建后端和缓存设备,再注册并挂载。对小白而言,建议先在测试环境搭一遍再上生产,因为这里的参数和挂载顺序一旦记错,重启后很容易出现设备找不着的情况。
7. 最后想说的是:别把RAID当备份
关于RAID,我在最前面说过一句话,最后还想再强调一次:RAID解决的是磁盘硬件故障问题,不是数据逻辑损坏问题。误操作删了文件、勒索病毒加密了数据、文件系统因为意外断电出现逻辑损坏,这些RAID都管不了。RAID做的是可用性(availability),备份做的是可恢复性(recoverability),两者是不同维度的东西,缺一不可。
我自己管理服务器时有个固定组合:核心业务用RAID 10保证性能和冗余,然后数据通过计划任务或备份工具实时/定时同步到另一台机器或对象存储,再定期做恢复演练。只有恢复演练做通过了的备份,才叫真正有效的备份,否则那只是“听起来有备份”。
回到Linux磁盘管理系列,RAID这一篇讲到这里基本把该说的都覆盖了:从级别选型到mdadm实操,从故障替换到性能调优,最后还把热备盘、监控、缓存策略这些日常运维的细节全部串了起来。如果这篇文章里的命令能帮你一次把阵列搭起来、少踩一个坑,那这个过程就没白折腾。如果你在搭建过程中遇到和盘符识别、重建速度、重启丢失阵列配置相关的问题,可以顺着这篇文章里的排查链路逐条对比,多数情况都能找到原因。
