1. RAID到底是个什么东西
1.1 从一个真实工作场景说起
先讲一个我实际碰到的场景。某次给一台文件服务器做存储规划,机器里塞了四块4TB的SATA盘,需求是既要容量大,又不能让某一块盘挂了导致整个业务瘫掉。当时预算有限,采购独立RAID卡的成本比其中两块硬盘加起来还贵,所以我选择了Linux自带的软RAID方案,用mdadm把四块盘做成RAID5阵列。这套系统跑了两年多,中途坏过一块盘,在线换盘重建后数据完整,业务几乎没受影响。
你如果管理过几台Linux服务器,大概率遇到过类似的存储决策问题。这就是RAID概念的价值所在——它让你不用依赖昂贵的专用硬件,也能在普通服务器上实现磁盘冗余和性能提升。所谓RAID,全称是Redundant Array of Independent Disks,独立磁盘冗余阵列,核心思路很简单:把多块物理硬盘组合成一块逻辑硬盘,由阵列统一管理,数据按照不同策略分散存放,从而获得单块硬盘无法提供的容量聚合、性能叠加或故障容忍能力。
要注意一点,RAID不是备份。这是我在很多运维现场反复强调的一句话。RAID解决的是硬件层面的可用性问题,也就是某块盘坏了,系统还能继续跑;但如果你误删了文件、被勒索软件加密、或者整个阵列被格式化,RAID救不了你。真正保数据的方案是定期备份,RAID和备份是两条线,各管各的。
1.2 常见RAID层级速览
RAID有多个层级,实际工作中见到的就那么几种:RAID0、RAID1、RAID5、RAID6,还有混血的RAID10。每个层级的原理不同,适用的业务场景也完全不同。
RAID0,条带化存储。数据被切成等长的条带,轮流写入多块盘。比如两块盘做RAID0,一次写入的数据一半落到第一块盘,另一半落到第二块盘,读的时候两边同时取,性能接近翻倍。它的问题也直接——任何一块盘坏了,整个阵列数据全丢,可用性比单盘还差,因为又多了一个故障点。这个层级只适合存临时数据、缓存、或者可以从源头重建的内容,正经业务数据别这么玩。
RAID1,镜像。两块盘保存同一份数据,写入时同时写两份,读的时候可以两边同时读,性能不低于单盘,甚至某些场景更好。空间利用率只有50%,因为两块盘存的内容一模一样。它是最安全的入门方案,代价就是贵,想存2TB数据就得买4TB的盘。不过小规模应用中,两块盘做个RAID1作为系统盘或数据库盘,性价比其实不错,很多入门服务器就是这么干的。
RAID5,带分布式奇偶校验的条带化。至少需要三块盘,写入的数据按条带分散到各盘,同时有一份奇偶校验信息轮流存放在不同盘上。它的空间利用率是N-1块盘的容量,比如三块4TB盘实际可用8TB。当某一块盘故障时,利用其他盘上的数据和校验信息可以算出丢失的数据,系统照常运行。这是企业里最常用的层级,均衡了性能、容量和安全性。缺点是重建期间阵列处于降级模式,此时如果再坏一块盘,数据就彻底没了,所以RAID5只允许坏一块。
RAID6,双奇偶校验,至少需要四块盘,写入两份校验信息,允许同时坏两块盘。空间利用率N-2块盘的容量,安全性更高,适合数据量大、又无法接受重建期风险的场景。代价是写入性能比RAID5差一些,因为每写一次数据要计算两次校验,CPU开销翻倍。
RAID10,先镜像再条带。典型做法是四块盘,两两先做成镜像,再把两组镜像条带化。它兼顾了RAID0的性能和RAID1的冗余,最多允许每组镜像中各坏一块。空间利用率50%,成本高,但数据库、虚拟化这类对性能和数据安全同时要求高的场景,它是首选。
还有一个概念叫JBOD,简单把多块盘串成一个逻辑盘,没有冗余没有条带,现在基本被RAID0取代,只在特殊存储设备上还看得到,日常管理中用得很少。
1.3 不同层级怎么选
选哪个层级,本质是回答四个问题:你手里有几块盘、你能接受多少容量损失、性能瓶颈在哪、以及系统允许的最大停机时间是多少。
盘很少的情况下,两块盘没得选——要么RAID1要安全,要么RAID0要性能。三块盘起步,RAID5是比较均衡的选择;如果业务数据重要且盘够多,RAID6更稳妥。四块盘以上,性能敏感型业务选RAID10,容量敏感型选RAID5或RAID6。
这里有个容易被忽略的点:大容量硬盘的阵列重建时间越来越长。一块16TB的盘做RAID5重建,全速跑也可能要十几个小时,期间阵列性能大打折扣。所以现在新规划的阵列,如果单盘容量超过8TB,我倾向于建议RAID6,或者干脆把阵列拆小、用多组RAID1。磁盘容量越大,重建期二次故障的概率越高,这是概率论,不是玄学。
2. 软RAID和硬RAID怎么选
2.1 软RAID的本质
软RAID,就是通过操作系统自带的软件层实现RAID功能,不需要专门的RAID控制器芯片。Linux下的实现是内核的md模块,管理工具是mdadm。CPU参与所有条带计算和校验运算,数据走正常的存储栈写入各块磁盘。
很多人一听软RAID就觉得不靠谱,这是误解。现代CPU性能很强,md模块的实现也非常成熟,在纯软件层面做RAID5的异或运算,对系统整体性能影响并没有想象中大。我做过一个粗略对比:一台普通Xeon服务器上,软RAID5在持续大文件读写时,CPU占用大约多出5%到10%,对于文件服务器、备份服务器这类场景,完全可以接受。当然,如果是高并发的随机小IO数据库业务,软RAID的校验开销会被放大,这时候硬RAID或者RAID10会更好。
软RAID最大的优点是不用额外花钱买硬件,而且不受特定RAID卡型号限制。迁移到另一台Linux机器上时,只要盘没坏,mdadm能直接重新组装阵列,不依赖原卡片的私有元数据格式。这一点在实际运维中非常值钱——硬件RAID卡一旦损坏且买不到同型号卡,数据恢复会变得相当痛苦,软RAID就没有这个问题。
2.2 硬RAID卡的优势与局限
硬RAID依靠独立的RAID卡,卡上有专用处理器和缓存,操作系统看到的是一个逻辑磁盘,RAID运算全部由卡完成。性能上限高,尤其是带写缓存的卡,可以通过回写策略大幅提升随机写性能,这是软RAID比不了的。
但硬RAID卡有几个让人头疼的问题。第一是电池或电容问题:带缓存的卡在掉电时,如果缓存里的数据来不及写到磁盘,配合电池可以在恢复供电后进行回写,但电池老化后缓存策略会自动切到直写模式,性能骤降;一旦电池损坏没发现,掉电就可能丢数据。第二是卡坏了的可替换性问题:同一家厂商不同代际的卡,元数据格式可能不兼容,换卡有时候比修数据还麻烦。第三是便宜卡的性能反而不如软RAID,一百块钱的入门RAID卡,CPU弱、缓存小,跑起来还不如纯软的稳定。
所以不要无脑上硬RAID。小规模、低并发、成本敏感的项目,软RAID是性价比极高的选择;数据量巨大、并发高、要求极致性能的核心业务系统,再考虑高端硬RAID卡。
2.3 什么时候该用软RAID
我的建议很简单:如果你在管理的是十几台以内的小规模服务器,跑的是文件共享、备份、Web服务、容器存储这类业务,软RAID完全够用。Linux内核的md模块在稳定性方面经过了大量生产环境验证,不是玩具。
需要提醒的是,软RAID不要用在Windows服务器上。Windows的软RAID(动态磁盘)管理起来很别扭,而且系统崩溃后恢复阵列的流程相对复杂。Linux下用mdadm做软RAID是标准操作,资料多、踩坑经验也沉淀得很丰富,是行业里最常见的方式。另外,如果跑的是数据库、虚拟化这类随机读写密集型业务,建议优先考虑RAID10配合高性能盘,或者直接上硬RAID卡,软RAID在这类场景下确实有性能瓶颈。
3. 软RAID命令实操:mdadm从入门到熟练
3.1 环境准备与磁盘检查
实际操作前先做两件事:确认系统里有mdadm工具,确认参与阵列的磁盘盘符和容量。Debian系执行apt install mdadm,RedHat系执行yum install mdadm,装完用mdadm --version验证一下。
磁盘检查用lsblk和fdisk -l。这一步多花两分钟,后面少走很多弯路。特别要看清每个磁盘的设备名、容量、是否已经挂载、是否包含分区表或文件系统。用一块有数据的盘做RAID,创建成功后那盘上的所有数据都会被清零,没有后悔药。
注意:创建软RAID前,务必确认目标磁盘上没有需要保留的数据。mdadm --create操作会在初始化时覆盖磁盘数据,这个过程不可逆。检查磁盘是否挂载用mount | grep sdX,检查是否存在文件系统用blkid。
3.2 创建RAID阵列
创建阵列的核心命令是mdadm --create。我以三块4TB盘做RAID5为例,完整命令如下:
mdadm --create /dev/md0 --level=raid5 --raid-devices=3 /dev/sdb /dev/sdc /dev/sdd --chunk=256 --metadata=1.2逐个参数拆解。--create指定创建的阵列设备名,Linux命名规则是/dev/md0、/dev/md1以此类推。--level=raid5指定RAID级别,写raid5和5效果一样。--raid-devices=3声明参与阵列的物理磁盘数量,后面紧跟的盘符必须与这个数字一一对应。--chunk是条带大小,单位KB,这个参数直接影响读写性能。--metadata=1.2选择元数据版本,1.2是默认值,元数据存储在磁盘起始位置,1.0在磁盘结尾,0.9在老内核里用得多。我建议保持1.2,它能支持更多高级功能,而且1.2元数据所在的2.0测试中提到,不同版本差距不明显,也不必过度纠结。
执行完创建命令后,系统会显示一个初始化进度,可以通过cat /proc/mdstat查看。RAID5的初始同步需要较长时间,4TB级别的阵列可能要几个小时甚至十几个小时,期间阵列可以挂载使用,只是性能没有达到最佳。这个同步过程就是把奇偶校验信息完整建立起来,不急,让它慢慢跑。
初始化完成之前重启系统有个风险:阵列可能无法自动识别。所以创建完阵列后,第一件事是把配置写到mdadm的配置文件里:
mdadm --detail --scan >> /etc/mdadm/mdadm.conf这条命令会把当前所有已创建的阵列信息以扫描结果的形式追加到配置文件中,系统启动时,mdadm服务会根据这个文件自动组装阵列。如果不写配置文件,每次重启后都需要手动mdadm --assemble /dev/md0 /dev/sdb /dev/sdc /dev/sdd,麻烦不说,还有可能因为设备名变化导致组装失败。
创建完阵列不是终点,还得在阵列上创建文件系统才能存数据。用ext4或xfs都行,各有取舍,日常文件共享我一般用xfs,因为xfs对大文件和大容量支持更稳,而且在阵列降级时的恢复表现也更好。格式化命令mkfs.xfs /dev/md0,然后mkdir挂载点,mount /dev/md0 /data,最后写进/etc/fstab实现开机自动挂载。
3.3 查看与管理阵列状态
管理软RAID的日常操作主要围绕三个命令:mdadm --detail、cat /proc/mdstat、mdadm --manage。
cat /proc/mdstat是快速查看所有阵列状态的最好方式:
cat /proc/mdstat输出会列出每个md设备的组成盘、当前状态、同步进度。比如出现[UUU]表示三块盘全部在线正常,[U_]表示其中一块盘故障或离线。这是最直接的判断方式。
mdadm --detail /dev/md0是详细版信息,会列出阵列的UUID、RAID级别、设备数量、每个盘的编号和状态、坏道日志等。排查问题的时候先跑这条,信息最全。
关于设备状态,mdadm用不同字母表示:U代表在线正常,代表设备缺失,S代表备用盘。如果看到某个设备变成[],就要准备处理故障盘了。
3.4 扩容与故障处理
阵列建成后不可能一劳永逸,最常见的两类操作是扩容和换盘。
扩容的常规思路是:把新盘加入作为备用盘,然后执行数组增强操作。比如三块盘的RAID5,想扩成四块盘,先添加新盘:
mdadm --add /dev/md0 /dev/sde然后执行:
mdadm --grow /dev/md0 --raid-devices=4这个grow操作会重新计算条带分布和奇偶校验,把数据重新铺到四块盘上,需要较长时间,而且扩容期间性能明显下降。如果你不是特别追求在线扩容,更稳妥的做法是先把数据备份出来,重建一个四盘阵列,再把数据拷回去。操作更简单,出问题的概率也小得多。
故障处理流程反而是软RAID最体现优势的地方。假设/dev/sdc物理损坏,系统日志或mdadm状态会提示设备掉线。处理步骤如下:
# 1. 把故障设备标记为故障 mdadm --manage /dev/md0 --fail /dev/sdc # 2. 移除故障设备 mdadm --manage /dev/md0 --remove /dev/sdc # 3. 插入备用或新盘,自动开始重建 mdadm --manage /dev/md0 --add /dev/sdc执行完add操作后,阵列自动进入重建状态,cat /proc/mdstat可以看到重建进度百分比。在重建完成前,不要对这个阵列做其他重大操作,不要重启,尽量减少IO压力。整个重建过程中系统不会停机,业务可以继续跑,只是性能有所下降,这就是RAID的核心价值。把这个流程练熟,遇到磁盘故障你就不会慌了。
4. 常见问题与排查技巧实录
4.1 磁盘故障恢复的典型场景
我曾经在一台文件服务器上遇到过一块盘smart信息报警,但阵列还没自动把它踢掉。如果磁盘性能已经变得极差,留存阵列出问题的风险更大,更优选择是主动fail掉它,而不是等它彻底坏了才处理。
使用习惯:磁盘在阵列中的盘符偶尔会变化,比如sdb变成sdc。需要格外小心,不要根据盘符想当然操作。正确做法是通过专利的序列号或ID确认物理盘身份。可以使用smartctl --all /dev/sdX查看Serial Number,或者直接通过mdadm --detail命令查看每块盘的设备路径。
RAID5坏了一块盘后进入降级模式,能正常读写,但性能和安全性都下降了。有些时候运维人员看着阵列还能用,就不着急换盘,拖几个月。这个习惯很危险。RAID5降级模式下运行,每次读写都要经过异或校验计算恢复缺失数据,性能打折,而且此时再有一个扇区级的错误,整个阵列就崩了。发现故障盘,第一时间换上。
4.2 重启后阵列丢失怎么处理
重启后遇到md0找不到、系统只能看到物理盘的情况,心先别慌,数据大概率还在。排查看顺序。
第一是检查mdadm.conf里的配置是否正确。可能有人改过盘符,或者scan信息没有更新。重新扫描:
mdadm --assemble --scan第二是确认每块盘上是否还有阵列的元数据。用mdadm --examine /dev/sdb查看,可以识别出该盘属于哪个阵列。如果看到No array detected,说明这块盘的元数据被破坏了,情况更复杂一些。
第三是手动组装,指定盘符:
mdadm --assemble /dev/md0 /dev/sdb /dev/sdc /dev/sdd这条命令如果提示无法识别所有设备,可以加--run参数强制启动:
mdadm --assemble --run /dev/md0 /dev/sdb /dev/sdc /dev/sdd强制启动的前提是你确认参与阵列的盘没有遗漏,而且没有一块盘是曾经故障但没被正确移除的。强制组装成功后,第一件事检查文件系统完整性,然后立即备份数据。
我见过一次因为系统重装导致阵列丢失的情况。新系统里没有配mdadm.conf,但盘本身没动过。在安装mdadm后执行mdadm --assemble --scan,系统自动识别出原阵列并组装成功,数据完好。这也是软RAID相比硬RAID的一个优势——阵列信息在磁盘上,不依赖硬件和特定系统状态。
4.3 性能问题排查思路
阵列性能上不去,先分清是网络瓶颈、文件系统瓶颈还是RAID层瓶颈。我习惯的顺序是:先看磁盘吞吐,再看阵列状态,最后排查文件系统挂载参数有没有拖后腿。
RAID层排查重点看chunk大小。chunk是条带的单位,太小会让大文件写入时产生大量碎块,太大则会让随机IO性能变差。通用经验:
- RAID5的chunk一般取256KB或512KB,适合大文件连续读写
- RAID10的chunk可以小一些,64KB或128KB更均衡
- 块大小(block size)最好与chunk大小对齐,否则一个IO请求可能要跨越多个chunk,产生额外开销
关于性能测试命令,我常用hdparm -t /dev/md0先看缓存命中的读速度,再用dd以oflag=direct方式直接测裸设备IO,避开文件系统缓存。注意dd的bs参数要大于等于chunk大小,否则测的是小块读写性能而不是阵列的真实能力。
如果创建阵列时没指定chunk,mdadm默认值是512KB,在大多数场景下够用。但你要是用默认值建了一个用于数据库的RAID10,随机写性能大概率会让你失望。规划阵列前,想清楚业务IO模型再定参数,比建完后再调整简单得多。
4.4 其他低概率但致命的问题
元数据版本不统一的问题容易被忽视。比如原来阵列是用1.0版本的元数据创建的,后来服务器从老内核迁移到新内核,某些脚本对它不兼容,重启后可能无法自动组装。遇到这种情况,mdadm --examine可以帮你看到每个盘的元数据版本。想升级元数据版本也不是不行,只是操作复杂,需要整个阵列离线重建,性价比不高,一般建议保持创建时的版本不动。
还有磁盘顺序变化导致的“盘符漂移”。服务器重启时,系统以扫描顺序分配盘符,今天sdb明天sdd是常事。mdadm依赖的是磁盘内部的UUID和元数据,不依赖盘符,所以合理配置下盘符漂移不会影响阵列识别。千万不要把盘符写死在脚本里,要用设备UUID或阵列设备名(比如/dev/md0)来引用。查看盘符对应的UUID使用blkid /dev/sdb。
5. 最后分享几个珍藏的实战技巧和踩过的坑
用几年mdadm之后,有些经验是文档里写不清、实战才明白的。其中一个很重要的习惯:每次创建阵列后都把它记录在一个小本本上。阵列创建时间、每块盘的序列号和盘符、chunk大小、文件系统类型、当时怎么配置的mdadm.conf,全部写下来。这东西平时用不上,但一旦阵列出问题,它就是拯救数据的第一个工具。
第二个经验是新盘加入旧阵列时,不要急着执行grow操作。我有一次扩容,盘是新盘,但型号批次不同,性能差距明显,扩容后整个阵列整体性能被拉到了最低的那块盘的水平。如今大容量的SATA盘,不同批次性能差异真的存在。让新盘先在备用位置跑几天,看看smart信息和实际IO吞吐正常,再执行grow不迟。
第三是系统盘不要做软RAID。虽然技术上可行,但系统盘承载的是启动引导逻辑,软RAID的组装依赖initramfs配置,一旦initramfs重建出了问题,系统直接起不来。系统盘单独用一块固态盘,数据盘单独做阵列,这是更省心的方案。
第四是给阵列做定期巡检,不要等到报警了才看。写个简单的shell脚本,每天定时检查/proc/mdstat里的状态,发现[U_]级别的状态就发告警。软RAID的很多故障其实都有预兆,smart信息、系统日志、盘体声音,都是信号。能不能提前发现,就看你是不是定期在检查。
说到底,软RAID是个非常成熟的存储方案。它不花哨,不依赖神秘硬件,几乎在所有Linux发行版上开箱即用,性能和安全在大多数业务场景里都够用。真正决定存储系统可靠性的,从来不是选用了什么方案,而是你这个管理员有没有理解清楚RAID的边界和风险,有没有把日常巡检和应急预案做到位。把概念吃透,把命令练熟,关键时刻它就不会坑你。