尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

嵌入式存储网关的RAID5实践:从容量焦虑到掉电安全

嵌入式存储网关的RAID5实践:从容量焦虑到掉电安全 今年年初我们那款面向边缘视频监控的嵌入式存储网关碰到一个非常现实的难题4盘位设备两块一组做RAID1镜像可用容量直接打了五折。客户那边是48路高清码流要保留30天按单路4Mbps码率粗算需要约20TB可用空间RAID1配两块10TB盘刚好卡在临界点再多一路都危险。于是我们把目光转向了RAID5——同样的单盘冗余容量利用率从50%提到75%四盘位瞬间多出10TB空间。决定好做真正把RAID5支持做进嵌入式存储栈、和上层文件系统对齐、躲开掉电不一致的坑、扛住坏盘重建这一路踩的坑比预想多得多。这篇文章就从头拆一遍这段经历容量焦虑怎么来的、RAID5底层的数据组织和写惩罚、中间层架构怎么落位、写路径怎么保证掉电安全、坏盘重建怎么做增量优化最后聊聊RAID5和RAID10在嵌入式场景下的真实取舍。1. 嵌入式存储的容量焦虑为什么镜像不够用了1.1 先算一笔容量账先回到那个让人头疼的容量账。以一台4盘位设备、每块盘10TB为例传统方案是两块一组做RAID1镜像可用空间20TB冗余度100%——任何一块盘坏了镜像对还在数据一件不少。这套方案在很长一段时间里是嵌入式设备的默认答案原因很简单实现成熟、重建简单、没有任何校验计算开销。但代价同样明显50%的磁盘空间被锁死磁盘容量越做越大这种浪费就越让人肉疼。RAID5的诱惑在于同样是容忍一块盘损坏它把冗余成本从N块盘里砍一半变成N块盘里只扣掉一块。同样四盘位RAID5可用容量是30TB比RAID1整整多了50%。我把几个常见方案的容量账拉了个表方案4×10TB可用容量容量利用率最少盘数冗余能力RAID120TB50%2单盘RAID530TB75%3单盘RAID620TB50%4双盘RAID1020TB50%4每个镜像组单盘回到我们那个48路存储的案例16路4Mbps码流30天大约需要20.7TB20TB的RAID1连冗余余量都留不出来RAID5的30TB则能轻松覆盖还能再扩展几十路。这类容量敏感型负载正是RAID5最擅长的战场也是主流NVR和边缘存储网关这两年集体向RAID5迁移的根本原因。1.2 RAID5能扛什么不能扛什么不过得先把边界说清楚。RAID5解决的是磁盘单体故障下的数据可用性问题一块盘物理损坏、固件卡死、接口松脱阵列里其它盘依然能通过校验把这块盘上的数据算出来业务不中断。它不解决所有问题——文件被误删、系统被勒索、固件BUG把元数据写坏、同一批次磁盘在短时间内连续故障这些都不是RAID5的职责范围。把RAID5当备份用是嵌入式行业最常见的误解之一。还有一个容易被忽略的点RAID5的冗余是计算出来的不是复制出来的。读数据时一切正常一旦需要从校验重建某一块盘就意味着所有幸存盘都要参与XOR运算。这个运算本身不复杂但在嵌入式平台上CPU频率、内存带宽、I/O调度都会成为瓶颈。所以评估RAID5合不合适不能只看容量提升更要看主控芯片有没有富余的算力和内存通道。1.3 什么时候该认真考虑RAID5概括下来我判断一个嵌入式项目适不适合上RAID5就看三个信号第一盘位至少三块最好四块以上否则容量收益不显著第二业务负载以顺序写、大块写为主或者能够通过对齐设计把随机写转化为条带级的满写第三团队有能力处理掉电一致性、重建调度这些系统工程问题而不是只接一个内核模块就跑。三条全中RAID5就是好选择缺任何一条我建议你把后面RAID10那节看完再决定。2. 条带、校验与写惩罚RAID5的底层心法2.1 分布式校验的原理RAID5的数据组织方式可以用一句话概括把N块盘的空间切成一组组等长的条带每条带里专门留一块放校验校验块的位置在条带之间依次轮换所以叫分布式校验。具体到一条带里假设有4块数据盘和1块校验盘数据块D1、D2、D3、D4和校验块P同属一条带校验关系就是P D1 XOR D2 XOR D3 XOR D4。XOR的逆运算就是它自己这是RAID5最妙的地方想恢复D2时只要拿幸存块D1、D3、D4和P全部异或一遍就能算出来。整个恢复过程只需要一次按位异或硬件实现极简逻辑电路也好、NEON指令也好都能干得非常快。校验块在条带间轮换分布是为了避免所有写压力都集中在一块盘上。如果固定让0号盘当校验盘那任何数据块的任何一次更新都要触发对0号盘的写操作这块盘的寿命和吞吐会先于其它盘崩溃。轮换之后每块盘的写负载被摊平这也是RAID5区别于更早的RAID4最核心的一点。2.2 写惩罚RMW与RCW的取舍校验关系带来了一个绕不开的代价写惩罚。当你只更新一条带里的一个数据块时不能直接一写了之因为旧校验已经对不上新数据。这时有两条路。第一条是读改写Read-Modify-WriteRMW。先把旧数据D_old和旧校验P_old读出来计算新校验P_new D_old XOR D_new XOR P_old然后写D_new和P_new。一起两读两写四次I/O。第二条是重构写Reconstruct-WriteRCW。不读旧数据改读这条带里其余所有幸存数据块全部异或直接得到新校验再写数据块和校验块。在4块数据盘的配置下是三读两写五次I/O。这两种策略没有绝对优劣取决于一次更新涉及这条带里多少个块。经验阈值是当需要更新的数据块数量超过条带内数据块总数的一半时RCW更划算否则RMW更划算。成熟的RAID5实现会在两种策略间动态切换我们也保留了这套逻辑。这个写惩罚直接决定了一个结论RAID5对小块随机写极其不友好。每次4KB的元数据更新落到底层可能变成四次甚至五次I/O在机械盘上意味着多几倍寻道在SSD上意味着多几倍写放大。所以如果业务负载是大量随机小写RAID5不是好选择这一点在讲RAID10对比时还会展开。2.3 chunk size选型嵌入式的特殊考量条带内单个数据块的大小也就是chunk size是RAID5规划时必须先定死的参数。它决定了业务请求切分的粒度一个4KB的小请求可能只落在一个块上一个128KB的大请求会横跨多个块。我们的产品最终取64KB主要权衡了三点视频监控的码流在秒级粒度上本来就是连续大块64KB能让一个条带装下足够多的有效数据单条带缓存开销适中不至于挤压主控内存重建时以条带为单位推进恢复速度不会太碎。如果主控内存宽裕、业务又偏大块顺序写128KB甚至256KB也可以重建效率更高反之如果业务小块居多chunk调小一些能减少写惩罚的放大范围但会增多校验块的碎片。这个参数在建阵列之后很难再改千万别图省事用默认值一定按真实业务做一轮基准测试再定。3. 架构落位文件系统与物理盘之间的那条中间层3.1 三条路线内核MD、改造MD还是自研层在嵌入式Linux平台上最省事的路是直接用内核的MD模块md/raid5它成熟、稳定、久经考验。但能用和好用是两回事。MD模块的内存占用、线程调度、重建优先级都是面向通用服务器设计的直接搬进一个只有256MB内存的设备里会遇到两个典型问题条带缓存数量默认偏大导致内存吃紧后台重建线程与前台业务I/O的调度策略不可控业务高峰时可能被重建拖垮IOPS。我们最终没有直接跑纯原版MD而是对它做了三层改造。一是把条带缓存上限压到只保留少量活跃条带用可控并发深度换内存稳定二是把重建线程优先级调低并且每重建一段就检查前台I/O队列深度超过阈值就让路三是把写意图位图从MD默认的位图文件改成固定在系统分区里的裸区避免位图本身挂在文件系统上形成鸡生蛋的依赖。如果你们平台是用buildroot或Yocto裁剪的改动路径基本一致这三条是嵌入式部署MD的通用经验。如果是在RTOS或裸机环境里做那就得自己实现一个块设备抽象层了。思路也不复杂上层文件系统看到的是一个完整的逻辑块设备底层把这个逻辑块按chunk映射到多块物理盘上。映射表、条带调度、XOR校验、重建恢复本质上是把一套小型MD搬进你的存储栈。工作量大但自由度最高很多做SSD控制器的团队就是这么干的。3.2 中间层的模块划分与数据流不论走哪条路线RAID5层建议拆成五个职责清晰的模块设备映射表维护逻辑块地址到盘号、物理块地址的映射记录哪些块属于同一条带。条带管理器把上层逻辑I/O请求拆成针对单块盘的物理请求管理活跃条带生命周期。校验引擎封装XOR计算在Cortex-A系列上优先走NEON在低端内核上退化为逐字节XOR。写意图位图记录哪些条带正在被更新且校验尚未落盘是掉电恢复的关键。恢复代理负责降级读、坏盘后的重建调度以及重建期间的资源控制。数据流大致是这样文件系统下发一个写请求条带管理器先查映射表确定它落在哪条带根据请求大小和条带内已有脏块情况决定走RMW还是RCW更新写意图位图置位对应条带执行物理盘读写计算新校验写入数据块和校验块校验落盘确认后清除位图标记再向上层返回完成。这套流程里位图的更新时机和校验落盘的确认级别是后面要重点讲的两个细节。3.3 与上层文件系统的对齐RAID5层不是孤立存在的它上面还挂着一个文件系统我们这边用的是ext4。链路一旦拉长对齐问题就来了。第一是写对齐。文件系统的块大小、日志journal区域、数据段划分尽量设计成条带大小的整数倍。我们的做法是把文件系统的stripe_width参数设成64KB×5320KB让ext4在做块分配时就知道RAID5的条带边界把连续写尽量落到同一条带减少RMW触发。纯粹靠RAID5层在底下硬扛随机碎片收益远不如文件系统配合分配策略来得明显。第二是刷盘语义。文件系统下发的fsync和带FUA的写到RAID5层必须如实传递给物理盘不能因为中间层有缓存就把刷盘请求吞掉。我们曾为了性能让校验块走Write Back缓存结果把掉电安全的窗口拉大了后来老老实实给校验块和位图更新都加上FUA性能损失在可接受范围一致性却从碰运气变成了可证明。第三是TRIM/Discard透传。如果底下是SSD文件系统发来的discard请求要能正确映射到各物理盘否则SSD的垃圾回收会退化长期插着用性能就劣化了。这个点很多自研层会漏做测试的时候一定要覆盖。4. 写路径与掉电一致性没有BBU的嵌入式只能靠设计4.1 写洞问题RAID5的命中注定RAID5的写路径上藏着一个经典问题叫写洞write hole。一条带里既有数据块又有校验块更新这条带至少要写两个块。如果系统在一号数据块写完、校验块还没写的时候突然掉电重启后这条带的校验就和数据对不上了而你无法判断到底哪个块是新的——数据块是新的、校验是旧的结果就是静默数据损坏。服务器阵营对付写洞的办法是BBU或NVMe的掉电保护电容保证掉电瞬间缓存里的数据还能完整落盘。嵌入式设备可没这个条件要么没有BBU要么只有一小块只够保护文件系统元数据的专用电容根本覆盖不了整条带。所以嵌入式做RAID5必须从写路径的调度设计上把写洞风险压到最低。4.2 我们的方案顺序约束加写意图位图我们选的方案分两层顺序约束加写意图位图。先说顺序约束。更新一条带时永远保证先写数据块、后写校验块并且校验块落盘确认后才向上层返回写入成功。这一条强约束的好处是最坏情况就是掉电时这条带的数据已经更新而校验还是旧的系统启动时能通过位图发现不一致触发重算修复。如果反过来先写校验掉电后数据是旧的、校验是新的同样不一致但数据损坏方式更隐蔽有时连判断哪块盘需要重建都很困难。再说位图。我们划分了一个裸的位图区每一位对应一条带。写路径上在发起条带更新之前就置位校验落盘成功后再清除。启动时扫描位图凡是置位的条带全部进入重算流程读该带所有数据块重新计算校验写回清除标记。这里有个关键细节位图本身的更新也必须可靠不能出现实际已经开始写了、位图还没置位的窗口。所以位图更新走带FUA的写命令宁可多一次刷盘开销也决不压缩这个安全窗口。4.3 故障注入与断电测试一致性这东西嘴上说没用得上手段。我们做了三类测试。第一类是注入式故障测试在驱动层制造随机写中断模拟盘在条带更新的任意时刻掉线第二类是系统级断电测试用可控电源循环器对整机做随机掉电连续跑200轮每次重启后都挂载文件系统做全量校验第三类是长时间稳定运行测试把设备挂在持续写入的视频流下跑72小时同时跟踪位图脏带数量确认不同负载下都能收敛到接近零。三轮测试跑下来抓到过两个真问题。一个是位图清除时机偏早个别条带在校验未完全落盘时就被标记为干净重启后出现校验损坏。根因是盘厂商的Write Back缓存把写到盘接口当成了写到盘片于是给校验块下发加上了FUA标志。另一个是重建期间如果恰好再坏一块盘重建流程缺少锁保护两台后台任务会同时写重建目标块的竞态后来在恢复代理里加了按条带粒度的自旋锁才堵住。这些坑都是内核文档和芯片手册里不会写的。5. 坏盘重建从全量扫描到增量恢复5.1 降级模式坏一块盘之后怎么活着RAID5的容错是少一块盘还能完整服务。盘掉线后阵列进入降级模式读请求命中坏盘对应条带时把幸存盘的对应块全部读出来做XOR重建那个丢失的块写请求则直接把新数据和计算出的新校验写到幸存盘上同时把更新过的条带记录在重建日志或位图里等新盘替换后再补写。降级模式的性能会明显下降原因是每次读都变成多次物理读。以四盘阵列为例子坏了一块盘后一次逻辑读对应的物理读从1次涨到4次读放大明显。还有一个更隐蔽的问题如果掉线前有部分条带本来就处于校验不一致状态比如刚发生过掉电事故那这些条带在降级模式下是否还能正确重建需要提前用位图区分。我们的做法是降级开始时先扫一遍写意图位图把脏条带优先重算干净再开放对外业务。5.2 全量重建为什么慢等用户换上备用盘就要触发重建。最粗暴的方式是全量重建把幸存盘上所有条带逐条读出XOR算出坏盘数据写到新盘。这个流程逻辑最简单但对大容量盘来说慢得离谱。10TB机械盘按实际200MB/s的重建速度算要跑14小时以上如果期间还有前台业务在抢带宽这个时间轻松突破24小时。重建窗口越长第二块盘在压力下出事的概率就越高这也是RAID5在超大容量阵列里被诟病的核心原因。全量重建还有一个容易被忽视的问题它让新盘承受持续的大规模写入在SMR叠瓦盘上一旦写入缓存被冲垮重建速度会断崖式下跌。所以嵌入式选盘时如果要给RAID5用尽量避开SMR盘或者至少确认盘的写入策略能应对连续大块覆盖写。5.3 增量重建我们实际采用的工程优化最终我们在产品里用的是增量重建平时把降级期间被更新过的条带记录到一块专门的重建日志中换盘后先进行全盘扫描但只重建日志里标记的条带。实测下来日常掉线后马上换盘的场景绝大多数条带在降级期间根本没被写过增量重建通常能在1小时内跑完重建期间对前台视频写入的影响也小得多。增量重建逻辑不复杂但有一个坑掉线前就有写洞脏带的场景。如果掉线前位图里还有脏条带那么这些带的旧校验本来就不可信降级期间如果又恰好读过这些带读出来就可能是错误数据。我们的处理是降级模式启动时强制把所有脏条带先修复干净再做后续切换。宁可停机几秒钟也不带着不干净的校验进入降级模式这个原则到现在都没动摇过。6. RAID5还是RAID10别被参数表绑架要看业务长什么样6.1 核心差异对照最近RAID5和RAID10的讨论热度不低很多嵌入式工程师在这两个方案之间反复横跳。先给一张核心差异对照表再展开讲场景。对比项RAID5RAID10最少盘数342盘组阵列时等同镜像可用容量(N-1)/NN/2冗余原理XOR校验重建完全复制镜像随机写惩罚RMW/RCW带来2~4倍I/O放大约2倍I/O放大双写顺序大块写全条带写时几乎没有惩罚稳定坏盘重建速度全量或增量XOR重算直接复制镜像更快重建期间风险幸存盘全部参与计算只读源盘一份风险较低CPU开销需要XOR算力几乎为零适合负载顺序写、大文件、容量敏感随机小写、事务型、性能敏感从表里能看出RAID5是用计算换容量RAID10是用容量换简单和稳定。没有谁是绝对好的只有跟业务对不对得上。6.2 三类典型场景怎么选如果是安防视频监控、影像归档、日志采集这类设备负载以顺序大块写为主只要把写入记录段设计成和条带对齐RAID5的写惩罚几乎不会出现而容量收益立竿见影。我们的边缘存储网关最终就选了这条路64KB chunk让视频写入按条带对齐全条带写占比超过90%RAID5的劣势被业务特性天然规避了。如果是边缘AI推理服务器、数据库一体机或者任何存在大量随机小写和事务型更新的场景我建议老老实实上RAID10。虽然容量砍一半但每次写只是双写镜像没有读改写、重构写、位图这些复杂逻辑重建也快整个系统的心智负担低非常多。尤其嵌入式团队往往没有专职存储工程师一个维护成本极低却性能稳定的RAID10可能比微优化的RAID5方案更合适。再补一类容易被忽略的场景设备盘位不对称的。比如5盘位设备如果走RAID5可用容量是4/5如果走RAID10只能做两对镜像加一块空盘可用容量是2/5浪费严重。这种硬件形态天然就该选RAID5强行上RAID10是拿用户的预算填坑。6.3 一个折中的实战组合最后分享一个我们目前在方案层面比较推荐的折中思路RAID5加热备盘。比如五盘位设备做四盘RAID5加一块热备盘坏盘后系统自动把热备盘拉进阵列开始重建用户只需要在方便的时候更换坏盘即可。代价是可用容量从80%掉到60%换来的是重建不依赖人工介入、窗口期大幅缩短。这个组合在做产品时尤其合适嵌入式设备往往部署在无人值守的机房或路边站点指望现场有人第一时间换盘不现实。热备盘让系统在坏盘后立即自我修复等维护人员到场时重建通常已经完成了大半。如果产品形态支持插拔盘位这个RAID5加热备是目前我们最愿意推荐的生产组合。我在实际部署中还发现一个容易被忽略的细节无论选RAID5还是RAID10都一定在出厂前做好盘位标识和序列号记录。阵列恢复时插错盘位、插回旧盘导致的数据错乱我见过不止一次。把盘位信息固化到设备管理界面里比任何技术优化都更能保护用户数据。
返回列表