5. Fail-Slow at Scale
Introduction
这篇论文 Fail-Slow at Scale: Evidence of Hardware Performance Faults in Large Production Systems 由Haryadi S. Gunawi等人发表在第16届USENIX文件与存储技术会议(FAST 2018)上
系统性地揭示了在大规模生产系统中"fail-slow"(故障-缓慢)硬件现象的存在与影响;这类故障指的是硬件仍在运行, 但其性能严重退化, 未达到应有的标准;
硬件类型包括:
- disk, SSD
- CPU
- memory
- network components
几十年来, 系统领域已经形成了如下成熟的硬件故障模型 (fault model)
• Fail-stop(故障停止): 设备完全停止工作并发送明确的错误信号;
• Fail-partial(部分失效): 设备部分失效, 部分功能仍然正常;
• Fail-transient(瞬时性失效): 偶尔出现错误但会自行恢复;
• Corruption fault(数据损坏) 和 Byzantine fault(拜占庭错误) 等;
但是, fail-slow (故障变慢) 这种模式却被长期忽视: 即设备仍在运行, 但性能大幅下降, 不再达到预期速率
什么是 fail-slow?
硬件仍然在运行且功能有效, 但是已经处于一个 degraded 模式, 相比于其理想性能已经大幅度下降
过去 fail-slow 较少出现可能是因为系统规模小, 硬件结构简单;但如今:
• 数据中心规模庞大;
• 硬件越来越小型化, 复杂化;
• 故障概率随之上升;
• 系统边界模糊, 硬件/软件/运维交互复杂;
因此, fail-slow 故障不仅比以前更常见, 而且破坏性更强
在前人的作品中可以看到 fail-slow 问题的端倪, 但是没有系统性地研究它的影响和解决方案, 这篇文章是集合了多个相关数据中心开发者经验的共同作品;
Observations
Varying Root Causes
fail-slow 故障可能由多种根本原因引发, 且这些原因来自设备内部 (internal) 或外部
(external)
Internal 内部原因
硬件自身的问题, 主要包括:
- Firmware bugs (固件 Bug, FW:=Firware Issues), 例如: SSD 固件卡住 I/O, 网卡固件中的错误路由算法等;
- Device errors or wear-outs (设备错误或磨损, ERR), 如 NAND 闪存老化导致重读, 内存 ECC 频繁修正, 磁头损坏等
External 外部原因
• TEMP: 温度问题(如冷环境影响磁盘性能, 热环境加速 SSD 老化)
• PWR: 电力问题(如电压不足, 主板电容设计缺陷等)
• ENV: 环境问题(如高海拔, 震动, 灰尘等)
• CONF: 配置错误(如 BIOS 配置错误导致 CPU 降频, PCIe 插错槽位等)
Fault Conversions to Fail-Slow
fail-slow 并非天然存在, 而往往是其他故障类型"演化"的产物
在大规模系统中, 一些原本"轻微"或"已处理"的故障最终会 “累积成灾”, 转化为 fail-slow 现象, 系统设计必须主动识别和抑制这种转化路径
Fail-Stop -> Fail-Slow
将多个硬件设备连接在一起, 单个设备的失效 fail stop 故障可能导致整个系统变慢
Fail-stop 故障未被有效隔离, 会波及周围模块, 诱发 fail-slow 表现
Fail-Transient -> Fail-Slow
临时性的错误(如偶尔读错, IO失败), 如果这些错误频繁发生, 掩盖过程本身会引发性能劣化
错误掩盖(error masking) 是一种系统机制, 它在检测到硬件错误或故障时, 不直接向上层暴露, 而是通过重试, 校正, 替代等手段"掩盖"问题, 让系统"表面上"继续正常运行, 例如 tcp 传输错误, 在应用层不会感知到丢包而是会重新传递进行掩盖, 但是从性能分析上可以看出速度下降
错误掩盖(Error Masking)不再"廉价", 当错误不再"偶发", 频繁掩盖反而引入性能灾难
Fail-Partial -> Fail-Slow
设备部分不可用或性能下降(如内存模块, 磁盘部分损坏), 导致伴随部分故障规模扩大, 性能瓶颈出现, 例如 某 SSD 内坏块增加, 导致可用空间减少, GC 频率上升, 引发写入延迟
掩盖"部分失效"问题的策略需加以限制, 否则当问题成规模后, 会变成性能杀手
Varying Fail-Slow Symptoms
fail-slow 故障并不是一个单一表现形式, 它可能呈现出多种不同的"慢"状态, 使得诊断与检测难度显著增加
- Permanent Slowdown (永久性性能下降): 一旦性能下降后, 不会自动恢复, 直到手动干预或更换组件
- 硬件设备的性能长时间维持在一个退化状态, 即便系统未报错, 表现始终不正常, 需要人为干预才能恢复
- 容易观察, 但不能自动恢复, 需要替换硬件或重启设备
- Transient Slowdown (间歇性性能下降): 性能时好时坏, 有时正常, 有时明显下降
- 设备性能呈现周期性抖动, 表现为时快时慢, 难以复现
- 磁盘性能因温度变化发生波动(冷气系统循环导致的温差);
- 多个磁盘高并发操作时导致震动增加, 偶发性 IO 速度大幅下降;
- 某应用(Genshen Impact)运行高负载任务时会让 同机其他 CPU 降频, 任务结束后恢复
- 调试难度极高, 问题难以复现, 尤其难以在离线或测试环境中复现
- 设备性能呈现周期性抖动, 表现为时快时慢, 难以复现
- Partial Slowdown (部分变慢): 设备中部分子组件性能下降, 影响范围有限但调试困难
- 例子: 某网卡缓冲区部分损坏, 导致大数据包传输失败, 小数据包无问题(如40%大包丢失, 小包不丢)
- 调试难度在于 “最隐蔽” —— 多数系统监控指标只聚焦整体性能, 很难识别"局部慢"
- Transient Stop (瞬时停止): 硬件偶尔"消失"或自动重启, 表现为极端性能抖动甚至掉线
- 设备偶尔短暂性"宕机", 表现为中断服务, 重启, 自我"消失"然后自动恢复
- SSD 有时从系统"消失", 几秒钟后又重新出现(固件异常触发重启)
- 调试难度非常高 —— 除非有全链路日志和硬件状态回放, 否则很难追溯瞬时错误
- 设备偶尔短暂性"宕机", 表现为中断服务, 重启, 自我"消失"然后自动恢复
Cascading Root Causes and Impacts
fail-slow 故障不仅仅影响本地硬件, 它可以沿着系统组件间的依赖链传播和放大, 从"微小的慢"演化为"全局系统性瓶颈"
可以分为根因连锁 (cascading root cause) 和影响连锁 (cascading system impact) 两种
根因连锁 (Cascading Root Cause)
一个微小问题往往并不单独存在, 它可能引发一系列次生问题, 导致一个本该易修复的局部问题扩散为系统性性能故障
例子: 风扇 A 停止工作 -> 其他风扇被迫以最高速运转 -> 产生剧烈震动 -> 震动影响磁盘精度 -> 最终磁盘 IO 速度降低数十倍
影响连锁 (Cascading System Impact)
即使只有一个硬件子系统 fail-slow, 其"慢"可能会拖垮上层软件服务甚至整个集群, 出现"次生资源枯竭"问题
例子: 节点网卡从 1 Gbps 降至 1 Kbps -> 该节点的任务一直阻塞, 锁定资源 -> 健康节点也无法获得空闲 slot -> 整个集群无任务可调度, 进入死锁状态
Rare but Deadly: Long TTD (time-to-detect)
fail-slow 故障虽然发生频率低, 但其检测和定位极其困难, 代价高昂, 往往拖累系统长时间处于低效状态, 甚至引发集群级资源瓶颈或用户中断
原因1: 现有系统设计未充分考虑 fail-slow
• 多数系统构建于 fail-stop 模型: 只识别"设备是否宕机";
• 对于"变慢"这一非二值状态缺乏容错机制与监控触发条件;
• 结果是系统仍在运行, 但性能下降很久都未被注意;
原因2: 根因不在出故障的那台机器上
• 许多 fail-slow 故障的真正根因来自邻近节点, 共享电源或环境设施;
• 操作人员难以将"问题症状"和"根因源头"连接起来;
原因3: 环境依赖强, 无法在实验环境中复现
• 许多问题依赖"线上部署条件"(如气压, 温度, 负载协同)才能触发;
• 在办公测试环境下, 问题无法复现, 因此测试通过却上线出错;
原因4: 缺乏全栈可见性(full-stack visibility)
• 传统运维工具大多只监控关键组件: CPU, 磁盘, 网络负载等;
• 但 fail-slow 的根因可能在电源, 风扇, 主板传感器, 线缆等 非主流组件 上;
• 各运维团队分散负责不同子系统, 视角分裂, 信息割裂;
Internal Root Cause
这一章主要讨论 firmware bug 和 device error/wear-outs 的故障问题
SSD 相关
- Firmware Bugs: 特定 IO 模式触发了 SSD 控制器中的错误状态, 导致内部线程死锁
- SSD 偶尔变得完全无响应, 几秒后重新出现, 但期间数据丢失/超时, 表现为"间歇性掉盘", 系统表现为"轻度闪断"
- 固件升级可修复, 但部署前无法测试出, 在多节点系统中, 这种抖动极具破坏性
- Read Retries with Different Voltages(多电压重试机制)
- 随着 NAND cell 老化, 其电压窗口变窄, 控制器必须尝试**多个参考电压(read reference voltages)**进行读取
- 每次读取失败后都会触发 read-retry 机制, 大幅增加延迟
- 读取过程仍然成功, 因此不会报错, 系统只感知到延迟增加
- GC Interference and Write Amplification(垃圾回收干扰与写放大)
- SSD 使用 垃圾回收(Garbage Collection, GC) 来管理可用块, 但其运行不透明
- 当 GC 与前台 I/O 请求竞争资源时, 会显著抬高写延迟
- 一些 SSD 固件缺乏良好调度策略, 导致 GC 在高负载时仍强制运行
- 并行性受损: Broken Parallelism by Suboptimal Wear-Leveling
- 理想情况下, 大容量 IO 应该被映射到多个通道或芯片上以提高并行度;
- 但由于 Wear-Leveling(磨损均衡) 策略会持续迁移热页/冷页(Hot/Cold Pages), 导致逻辑页地址(LPN)到物理页地址(PPN)的映射频繁变化;
- 某些特殊负载下, 会导致连续的 LPN 被映射到相同的通道/芯片上, 从而降低 IO 并行性;
- 此外, 如果有坏页或坏芯片, 也会迫使 wear-leveling 做出次优映射决策, 进一步削弱并行性
Disk
Firmware Bugs 固件故障
- 多次报告表明, 硬盘控制器的固件存在 bug, 会显著影响性能;例如:
- 磁盘控制器会 延迟 I/O 请求达数十秒;
- 磁盘出现周期性"抖动"(jitters), 每隔几秒影响一次性能, 调试非常困难;
- 一些 RAID 控制器在主节点上停止响应, 重启后虽能工作, 但频繁出现超时和重试;
- 更糟糕的是, 单块损坏磁盘可耗尽 RAID 卡资源, 导致所有 IO 操作超时;这说明了错误的"坏盘掩盖"机制(bad-disk masking);
硬件损坏(Device Errors / Wear-outs)
• RAID 控制器会在磁盘出现"bit rot"(位腐蚀)时反复进行重建操作, 严重影响正常读写;
• 某些磁盘会反复被标记为"坏盘"并从存储池中剔除, 但后又自动重新添加为"好盘", 引发频繁的好坏切换, 对系统稳定性造成影响;
• 操作者还观察到了一些 介质故障: 磁盘在读取时需多次重试才能成功返回数据, 这种现象 极大拖慢了读操作速度;
• 有研究建议: 在检测到坏盘面(bad platter)时应允许磁盘 部分失效运行(部分禁用), 而不是完全下线, 这种方法可以在带宽降低的情况下保持服务继续运行;
Memory
设备错误(Device Errors)
- 某些内存错误通过自定义芯片进行了掩盖, 不向系统暴露坏地址;
- 但随着时间推移, 错误数量增加, 有效可用的内存容量逐渐减少;
- 这导致缓存命中率下降, 频繁换页(page swapping), 进而降低系统整体性能;
对比: 磁盘或 SSD 空间耗尽时会返回明确错误, 而内存空间减少往往 “悄无声息”, 程序仍能运行但速度显著下降;
SRAM 错误: 控制路径中的"隐形炸弹"
- 报告强调: SRAM(静态随机访问存储器)不像 DRAM 那样有刷新机制, 更容易因电压波动导致错误;
- 虽然数据路径上的错误常被掩盖(例如导致 CRC 错误并重传), 但控制路径上的 SRAM 错误更危险:
- 可能导致 设备重启(transient stop)甚至控制逻辑故障;
- 这些错误并不罕见, 是大规模基础设施中 服务中断的重要诱因;
Network
固件缺陷(Firmware Bugs)
- 错误的动态路由算法:
- 某些交换机固件内置的动态路由算法表现不如预期, 导致网络性能下降至一半;
- 由于固件为黑盒, 调试极其困难, 工程师不得不篡改内核并手动 ping 测试交换机连接;
- MAC 学习(MAC learning)失效:
- 导致交换机无法正确识别新的 MAC 地址, 进而产生广播风暴(flooding), 影响大规模数据传输;
- 多播支持不全:
- 一些固件处理特殊流量(如 multicast)不当, 导致网络严重拥塞;
NIC Driver Bugs
物理硬件缺陷(Device Errors)
- 设计错误造成电流不足:
- 一款网卡芯片由于电路设计问题, 某角落"缺电", 导致其不能全速运行;厂商最后不得不 召回并重制所有网卡;
- 光学模块失效:
- VCSEL 激光器的硬件缺陷导致交换机间性能下降, 影响成百上千条连接线缆;
- 路由器缓存故障:
- 内部 buffer memory 出现比特错误, 触发 TCP 重传机制, 使网络带宽崩溃;
Processors
就目前 CPU 的实现水平而言其非常稳定, 大多数问题都是外部因素造成的
External Root Causes
温度
风扇与散热系统失效: 风扇滤网堵塞
- 现象: 某交换机内光模块因温度升高而失效, 造成 高达 10% 的网络丢包;
- 原因: 风扇滤网(air filter)被灰尘堵塞, 冷却气流受阻;
- 结果: 即使清理后问题暂时缓解, 但由于早期过热, 交换机内部已经出现不可逆硬件损坏;
低温环境导致性能下降: 数据中心温度过低
- 现象: 硬盘进入"读后写"模式(read-after-write), 读取性能下降;
- 原因: 该数据中心采用"地板下送冷风"系统(旧式设计), 使靠近地板的磁盘温度低于正常值;
- 推论: 低温会干扰磁盘预期的工作温度范围, 激发冗余保护机制, 导致性能退化;
风扇之间的"协同崩溃"效应: 一个风扇坏, 全系统震动
- 现象: 一个计算节点的风扇损坏后, 其他节点的风扇 自动提升到最大转速补偿;
- 后果: 高转速风扇产生剧烈噪音和机械震动, 引发附近磁盘性能崩溃;
Power
主板电容不足(Insufficient Capacitors): CPU 在高负载下掉电
- 问题现象:
- 在某些主板上, 供电电容不够强大, 无法满足 CPU 在瞬时高负载下的电压需求;
- 结果是 CPU 工作在低于规范电压的状态, 出现数据错误与重复计算, 性能严重下降;
PCU 固件问题(Power Control Unit Firmware Bugs): 整个机架断电
- 问题现象:
- PCU(电力控制单元)固件进入"异常状态", 未能提供足够电压;
- 最终导致整个机架掉电;
- 处理难点:
- 有时可以通过重启控制器恢复;
- 有时必须重刷固件, 甚至更换整个 PCU;
部分失效(Fail-Partial Power Supply): 一个电源坏, 所有机器降频
- 背景:
- 每 4 台机器共用 2 个电源, 设计为冗余容错;
- 故障机制:
- 其中一个电源失效后, 另一个电源无法独立支撑所有设备;
- 所有 CPU 自动降频 50%;
- 后果:
- 系统运行缓慢, 任务处理积压严重;
- 故障定位困难, 因为另一个电源并未"完全宕机";
邻居机器功耗过高(Power-Hungry Neighbors): “我没问题, 是你太耗电”
- 现象:
- 某些节点运行大负载程序, 拉高整排机架电流;
- 结果导致同机架内其他节点电压下降, 频繁出现性能异常;
- 排查困难:
- 故障不在"慢机器", 也不在电源设备, 而是在"邻居";
- 定位耗时数月, 因无电源层级监控;
Environment
- Altitude and Cosmic Events
- Loose Interconnects
- Vibration (performance vibration)
Configuration
Suggestions
To Vendors
- 显式化错误掩盖机制 Making implicit error masking explicit
- 许多 fail-slow 问题是由硬件"悄悄掩盖"错误造成的(如 ECC, 重试, GC);
- 建议厂商在出现频繁错误掩盖时, 主动抛出告警信号(如 SMART 扩展字段);
- 暴露性能统计指标 Exposing device-level performance statistics
- 当前很多硬件(尤其是新 SSD)不再公开性能统计数据, 如写放大倍数, 擦除计数等;
- 作者呼吁恢复这些数据暴露, 供研究与系统诊断使用;
To Operators
- 在线诊断能力必须提升
- 报告中 39% 故障源自外部环境, 这些问题往往只能在线触发, 离线难以重现;
- 建议建立更多"实地故障分析工具", 而非依赖重启或实验室测试;
- 建立跨组件关联分析
- 推荐运用统计方法分析性能异常之间的联动模式, 比如:
- 风扇故障 -> 振动增加 -> 磁盘速度下降
- 电源波动 -> 多节点降频 -> 集群服务抖动
- 推荐运用统计方法分析性能异常之间的联动模式, 比如:
- 现实中, 运维监控只覆盖"主设备"(如 CPU, 磁盘, NIC), 但问题常出在非主设备(风扇, 电源, 线缆 ;
- 建议扩展监控粒度, 包括:
- 电源供应状况
- 风扇转速与温控响应
- 网络物理链路状态(如链路速率/丢包率)
- 温度/振动/海拔/空气质量
- 建议扩展监控粒度, 包括:
To System Designers
- 避免软件层面"隐性容忍"
- 很多系统在处理 fail-slow 时选择"悄悄 retry 或延时", 从而放大问题并拖慢整系统;
- 建议系统设计层面对 fail-slow 有可见性与诊断友好性;
- 将 fail-slow 转化为 fail-stop
- 当前系统对 fail-stop 容忍度高(如重试, 切换, 冗余), 但对 fail-slow 支持差;
- 可以主动识别并将持续的 fail-slow 节点"下线"或"跳过";
- 引入 fail-slow 注入测试 (Fault Injection)
- 作者建议系统设计者将文中所列的 fail-slow 根因注入到系统中:
- 驱动层重试
- 缓存丢失
- 网络延迟增长
- 风扇/温度异常响应
- 作者建议系统设计者将文中所列的 fail-slow 根因注入到系统中:
Discussion
Limitations and Failed Attempts
本文最大的缺陷是没有定量分析
