perseus: a fail-slow detection framework for cloud storage systems
摘要
最近新出现的 fail-slow 问题困扰着硬件和软件系统,其特点是受影响的组件虽然仍然在运行,但性能已经明显下降。为了解决这个问题,文本提出 perseus,一个实践中的‘fail-slow’存储设备探测框架。perseus创新性的采用了基于轻量级回归分析的模型,能够在驱动器粒度上快速定位并分析慢速故障。在 10 个月的时间内,perseus监控了 24 万块盘,发现了 304 个 fail-slow 的问题。隔离这些设备可以把节点级别的4 个 9 尾延时响应时间减少减少 48%。我们基于生产环境数据构建了大规模慢数据故障集(包含 4 万个正常盘和 315 个验证的 fail-slow 盘),并据此对慢故障盘展开了根因分析,涵盖调度算法缺陷、硬件设计瑕疵及环境因素等多类成因。我们已经公开了这个数据集。
1 介绍
大规模的存储系统容易受到各种故障的影响。学术界和工业界已在故障识别,检测和修复领域取得显著进展,涵盖停机故障,局部故障以及拜占庭故障等多种类型。
近来,fail-slow故障,也被称为 gray-failure 或者 limpware,正受到越来越多的关注。在 fail-slow故障里,软件或硬件组件的实际性能会低于预期。随着硬件性能的提升(Optane SSD,ZNS SSD)和软件栈(用户态驱动)的优化,fail-slow故障正在变得越来越容易检测和识别。最近的研究表明,fail-slow故障的发生率和 fail-stop 的几率相当。
准确的探测fail-slow故障是很有挑战的。性能差异有可能是内部因素引起的(SSD盘内的 GC)或者是外部的因素(负载的突发)都会有跟 fail-slow故障相似的症状。和 fail-stop 故障有明确的标准(软件 crash,数据丢失)不同,确定 fail-slow故障一般都靠经验。此外,fail-slow往往都是暂时的,很难让工程师去分辨,更不用说复现和解析根因了。
尽管已经有人在探测 fail-slow故障上做了一些工作,这些工作在大范围的云环境下就显得比较不够实用和比较低效。首先,这些方法需要访问源代码或者需要软件适配,但云厂商并不会碰用户代码。即使是内部的基础设施,插入一些代码片段也是相当耗费时间的,这些系统有可能跑了非常不同软件栈的服务。其次,现有的这些技术只能探测到节点级别,仍然需要人工才能定位到最后的原因。
本文我们分享了一个实用的,细粒度且通用的fail-slow检测框架,该框架广泛用于阿里巴巴云数据中心的各类服务和设备(仅需少量调整或无需调整)。首先我们分析了fail-slow在设备集群中的特征表现。随后我们探索了三种在实际场景中识别fail-slow的尝试,包括:
采用经验阈值
基于peer评估
IASO系统的重构
从之前的工作中吸取经验,我们设计和实现了 PERSEUS,一种非侵入式的fail-slow检测框架。通过映射关系,PERSEUS 能够自动为每个节点衍生出一个精确的和自适应的阈值,在监控中判断慢速条目。进而,基于慢速条目,PERSEUS 构建了相应的fail-slow事件和利用一个记分板的机制去评估这些事件的严重程度。
PERSEUS已经部署在云环境中超过 10 个月了,监控了高速增长的硬盘数达到了 30w片。PERSEUS 已经发现了超过 300 个fail-slow盘。通过隔离或者替换发现的fail-slow盘,我们显著的降低了节点的尾延时。95 分位,99 分位,9999 分位写延时分别下降了 31% 46% 48%。
我们对比了 PERSEUS和之前的一些 fail-slow检测方法。并发布了一个来自于生产环境的数据集,包含了 315 个确认的 fail-slow故障和大约 41k个集群上其他的盘,并构建了一个测试的 benchmark。benchmark评估显示 PERSEUS 使用了前面的方法,得到了准确率 99,召回率 100。我们也评估了 PERSEUS中组件的有效性和参数的敏感程度。结果显示,PERSEUS可以作为一个非侵入式的(基于监控日志),细粒度的(盘粒度),通用的(一组参数适用于所有场景)和准确的(高准确率和召回率)云计算存储系统的fail-slow检测框架。
我们对 fail-slow的成因进行了深入分析,发现其根本原因呈现多样化特征,主要包括以下几类:
调度机制缺陷:资源争用等非必要调度问题
硬件固有缺陷:以磁盘坏道为代表的物理层故障
环境干扰因素:温度波动和电力供应异常
本文做了以下的工作:
我们分享了在大规模数据中心做 fail-slow检测的三种失败的尝试
提出了 PERSEUS的设计,一个非侵入式的,细粒度的,通用的 fail-slow检测框架
我们组装了一个大规模的 fail-slow数据集,构建了一个 fail-slow测试 benchmark
我们提供了一个 fail-slow多个角度的深入根因分析
2 背景
2.1 系统架构
在本文,我们探索了在 alibaba 数据中心 做fail-slow的检测方法。这些 IDC 遍布于全球,每个IDC都包含了多个存储集群。在每个集群上都部署了一套分布式文件系统,用于支持一些特定的服务(比如块存储,NoSQL 或者大数据分析等)。每个集群都包含了技术个 rack ,最多有 200 个,每个 rack 包含几十个节点(最多 48 个)。有三种类型的存储节点:
全闪:一个节点包含 12 个 NVMe SSD
混合:一个节点包含 60-120 个 HDD用于数据存储,2 个 SSD作为写 cache
HDD:节点包含 70-80 个 HDD用于存储数据
默认每个节点上的盘是同一个型号的。每个节点上最多可以有 3 个盘被同一时间下掉修复。表一列了基础的信息和盘的分布。我们把盘的 model 用厂商-model来明明,比如,I-A意味着I厂商的 A model。


2.2 数据集描述
在我们的数据中心,每个节点上都部署了一个监控守护进程,用于收集运营数据,主要是盘的延时和吞吐。守护进程会计算 15 秒的平均延时然后把他们用时序数据的形式记录下来。守护进程每天跑3 个小时(9PM到 12AM)。每个盘每天产生 720 个 entry。总计,我们收集了 100 billion entry的数据,表 2 列举了日常的 9 种云服务的分布。
2.3 fail-slow故障的影响
fail-slow故障,特别是很短暂的那种,经常会被忽略或者误认为是性能的抖动。此外,存储栈通常有多层(软件,固件,硬件)的容错,比如重试和荣誉,静默了这些 fail-slow错误。然后在实际生产环境中,此类慢速故障对于 i/o 性能影响往往更为显著。接下来,我们会使用一个来自于对象存储有代表性的例子来说明fail-slow故障的影响和做 fail-slow故障探测的重要性。


上图显示了fail-slow hdd和其他 同节点 hdd的延时对比。垂直的线代表 fail-slow盘的隔离。fail-slow的盘有更高的读写时延(写2.06~3.65倍,读 1.01~1.50 倍),它的其他指标,比如 IOPS,相对稳定。
相比于时延,利用率更容易让我们找到 fail-slow故障。我们的监控系统发现受伤害的节点处理的写请求比其他节点要少很多。日志分析进一步表明,分布式对象存储系统的负载均衡器倾向于避免将写入请求分配给故障节点,这是由于该节点因尾部延迟过高而导致的异常重试太多。表二描述了p50 p90 p95 p99 p9999 的故障节点在剔除 fail-slow 盘之前和之后的百分位延时。隔离前 p9999 尾延时是隔离后中位数的 2.43 ~ 3.29倍。
这个例子,和其他相似的例子,都说明 fail-slow 的故障影响不只是有问题的盘,还影响了整个节点很长时间。这催促我们去探索在云环境下有效检测 fail-slow故障的方法。
3 不太成功的尝试和教训
本节我们描述了检测框架的设计目标和之前的几次不成功的尝试。
3.1 设计目标
从我们的角度,一个实用的fail-slow检测框架应该有这些属性:
非侵入式的,作为云服务商,我们既不能修改用户代码也不能让用户跑指定的软件版本或者软件栈。所以我们只能依靠外部的性能统计
细粒度的,fail-slow的根因诊断往往需要很久(几天或者几周),我们期望检测框架能够精确的定位到故障源头
精确度,框架需要具备足够的精确度和召回率,以避免在误诊的情况下进行不必要的诊断
通用,框架可以部署到 ssd 和 hdd 集群,以及很简单的修改就可以应用到对象存储块存储等服务中。
3.1 尝试1:分级阈值
方法:直观的,我们可以基于 SLO 对盘的访问延时设置一个硬的时间阈值。为了避免因 ssd 盘内部的 gc等原因导致的误判,我们进一步规定:只有当可疑驱动器的性能下降持续达到最小时间跨度(minimum slowdown span),才会被判定为慢故障驱动器。
局限:对设备延迟实施硬性阈值约束,显然具备非侵入性与细粒度管控特性。然而,基于阈值识别的慢故障检测准确率较低,因为延迟时间极易受工作负载影响。此处我们以块存储服务中某NVMe SSD的延迟与吞吐量追踪数据为例进行说明。
图 3 左边说明盘上延时的变化,水平线是阈值(45us)。右边是相应的吞吐。我们可以看到三个延时的尖峰。通过对比延时和吞吐,就可以明确得出就是工作负载引起了延时的抖动。
因此,这就面临了一个进退两难的困境,设置宽松的阈值容易将正常性能波动误判为 fail-slow事件,而严格的阈值又会导致大量的fail-slow故障案例无法被检测到。此外,如我们实验所示,由于延时波动程度和磁盘的型号以及工作负载密切相关,通过为不同场景精细调校多组阈值可能相当浪费人力。在实际应用中,我们将基于阈值的检测机制作为类似超时的最后防线来使用。
3.3 尝试 2:同级评估
方法:第一种方法的问题是没有自适应的探测阈值。为了解决这个问题,我们探索了peer evaluation的方法。这个做法背后的根因是,工作复杂在分布式存储系统上是均衡的,磁盘在一个节点上应该会是类似的负载压力。由于 fail-slow故障相对来说是比较罕见的,一个节点上大部分盘应该是正常的,所以我们可以通过比较同一个节点上其他盘的性能来定义 fail-slow。
具体流程如下:我们首先以 15 秒为间隔,在每个采样时间点计算节点级别的延时中位数,随后评估在监控事件窗口内是否存在持续表现异常(延时超过中位数两倍)的盘(异常事件占比超过 50%)。当检测到此类情况时,框架将 触发fail-slow故障告警,并滑动监控窗口开启下一轮评估。

图 4 提供了一个 peer evaluation检测的例子,红线是 fail-slow的盘,蓝色线是自适应的阈值(2 倍的中位数),灰色线是正常盘。三个阴影区域表示盘正处于 fail-slow 故障的三个监控窗口。
局限:peer evaluation 可以获取一个自适应的阈值,但是它需要更依赖经验的参数,比如慢的程度和监控窗口的大小。尽管可以在一些集群上为了特定的存储服务很好的调优了这些参数,但是如果将这种评估机制扩展到其他服务的不同盘的型号,工作量会变得极其庞大。举个例子,他需要工程师 2 个小时的试衣间去调整一个 300 个节点的集群,然后这些参数在另外一个集群同样的服务深圳同样的盘也会失败。
3.4 尝试 3:基于IASO的模型
方法:IASO是一个聚焦于慢速节点的 fail-slow 检测框架。IASO的设计原则是将软件超时机制转化为可量化的指标,以此建立 fail-slow的基准评估体系。然而直接用 IASO对我们来说并不合适。首先,IASO需要修改代码,通过捕捉软件层面的超时时间来试写 fail-slow 事件。其次,IASO是节点级别的探测,而我们需要的是设备级别。尽管如此,我们尽力对 IASO进行了重构,为了避免修改软件,我们复用了基于peer evaluation的 fail-slow故障事件上报机制。
局限:基于 IASO的模型在我们的 benchmark 测试中表现欠佳,准确率只有 48%。我们怀疑主要原因是用 fails-slow事件上报去替换软件的超时时间是不够有效的。所以 IASO 重构也没有达到我们的目标。
3.5 PERSEUS 的指导原则
上述方法要么需要大量人工调参,要么在实际生产环境中效果不佳。本节我们用了一系列研究问题作为下一代 fail-slow 故障探测机制的指导原则。
RQ1: 我们应该用什么指标?
在早期研发阶段,我们主要聚焦于写入性能(即写入操作的延迟/吞吐量)的优化,这主要基于两方面的考虑:首先,在已经验证的 fail-slow案例中,超过 50% 的案例仅对写入操作产生显著影响,其余的,对于读性能的影响也是要远远小于写的影响。其次,fail-slow 故障对于写有更严重的影响。在我们的存储系统中,大部分集群需要写请求返回 3 个副本都成功。同时,读请求只要一个副本成功即可返回给用户。在这种场景下,fail-slow故障对于写来说影响更为频繁,单个 fail-slow写操作在大多数情况下都会导致写入请求延迟,而仅 1/3的概率会影响读取请求。需要注意的是,写入重分配机制无法修复fail-slow写入请求,因为重分配需要等待超时触发(该超时阈值往往远超fail-slow故障的事件)。尽管如此,我们仍基于读性能对于 fail-slow故障检测进行了评估,结果正式了上述假设。
RQ2: 怎样对模型的 workload 进行建模?
只简单依赖延时去检测 fail-slow 是不现实。我们之前的探索表明工作负载的压力可以显著的影响着盘的时延。而且,为深入理解延迟波动特性,我们进一步探索了其他用于建模工作负载压力的指标。
分析表格 3a和 3b激发了我们用盘的吞吐或者 IOPS 去建模的可能性。现在,盘的吞吐,iops和盘的延时一样被储存了起来。在表 6 中,我们在三种有代表性的服务中用 SRCC 衡量了盘的平均延时和吞吐以及 iops的相关性。一个更高的 SRCC 的值表明了一个更强的相关性。我们可以看到延时和吞吐的相关性比 iops 更高。此外,在一些服务里,延时和 iops 甚至有负相关性(数据库和块存储)。所以,我们决定用吞吐来对工作负载建模。
RQ3: 如何获得自适应性的阈值?
在尝试 2 种,我们发现尽管 peer-evaluation可以提供自适应的阈值,这种方案仍需要针对服务类型和盘的类型对于参数进行调优。现在,用基于吞吐的负载模型,我们可以构建 latency-vs-throughput (LvT)分布。然后,我们可通过回归分析定义统计学意义上的正常盘的基准,并将上限作为适用于多种环境的自适应阈值。
为了构建回归模型,我们需要明确纳入 LvT分布分析的磁盘范围。需要权衡的是,纳入更多的样本虽然能够提升统计的置信度,但会导致数据分布过度分散,从而难以得出清晰的上线阈值。所以我们在图 5 上描绘了三种分布,接下来会讨论他们的长处和短处。

service-wise:5a中显示了数据库服务中 3 个集群的 LvT分布。首先,我们可以观察到同一个服务中的不同集群在 LvT分布上可以有巨大的不同。比如,红色集群的样本几乎全部在黄色样本以下。这说明用服务中的全部硬盘来构建分布是不恰当的。
cluser-wise:在 5a中,我们发现即使是一个集群中的样本也有这明显区分的分布特征。通过统计学的分析,我们发现此类分布差异现象普遍存在。为了更清晰,在 5b中,我们描绘了在统计群两个不同节点上的 LvT分布。这种巨大的分布差异说明我们不能依赖于集群级别的 peer evaluation。
node-wise:最后,在 5c中,我们描绘了一个全闪节点(12 SSD)上的 LvT分布。每个盘代表了一个颜色。我们可以看到颜色聚集在一起,说明一个节点上的盘有相似的 LvT分布。我们也检查了其他服务的节点,确认了这种行为存在于很种节点的配置(全闪或者混存)和服务(块存储或者对象存储)。所以,我们决定用node-wise的样本去构建 LvT的分布。
RQ4:怎么在没有标准的情况下定义 fail-slow
和 fail-stop故障不同,在探测 fail-slow 故障时没有明确的标准。首先,设备(SSD)和软件对于运维工程师都是黑盒子。其次,fail-slow 故障可能呈现时变性特征,其症状表现存在动态波动。更多的,fail-slow 故障的根因可能非常难以定位。所以,我们无法完全排除 fail-slow故障的可能性。
所以,我们重新思考了对于 fail-slow探测的策略。与其依赖框架输出一个二元判定结果,探测工具更应该输出硬盘成为fail-slow的潜在概率。通过足够的精准度,运维工程师可以聚焦于最最有问题的盘。尽管这种做法可能导致部分fail-slow盘没有被检测到,但由于其表现与正常性能波动相似,所以这种情况时可以接受的。
4 PERSEUS
基于先前尝试的经验教训,我们剔除了 PERSEUS,一种非侵入式的,细粒度且通用的 fail-slow 检测框架。PERSEUS 的核心思想是基于节点级别的 LvT 分布构建多项式回归模型,从而为每个节点自动生成自适应阈值。本章节中,我们将首先介绍高层级工作流程,随后详细阐述每个步骤的设计方案。
我们的数据集可以看成是一个时间序列的数据集,每个 entry 有 5 个字段(avg_latency, avg_throughput, drive_id, node_id, timestamp)。每天,监控进程会从每个盘上收集超过 720 entry(180 min * 4 entries / min),并把他们发送到 PERSEUS 中进行一个四步的探测过程。
4.1 工作流
异常检测,对于每个节点,PERSEUS 首先收集所有的 entry。然后我们用一个 PCA 和 DBSCAN 联合的方法去发现和丢弃异常值。
构建回归模型,基于干净的数据集,PERSEUS 执行多项式回归,并把预测上限作为 fail-slow的探测阈值。然后 PERSEUS 把这个模型应用于原始的数据集去辨别out-of-bound entries 然后把他们标记为慢 entry。
确认fail-slow事件,PERSEUS 采用滑动窗口和慢速比例结合的方法,通过识别连续慢操作的 entry,进而精确定义对应的fail-slow故障事件。
评估风险,基于故障分的机制,PERSEUS 预测 fail-slow 的持续时间和影响程度,并为每个盘基于日常采集 的 fail-slow 事件定义一个故障分。值班的工程师就可以根据故障严重程度分级排查相关案例。
4.2 异常检测
在应用任何回归模型之前,必须先去掉噪声样本。LvT的样本数据一般都是一个节点聚集在一起,来自 fail-slow盘的日志或者是正常盘的性能波动仍有显著变差。所以在构建多项式回归模型之前,需要先进行异常值筛选。
使用 DBSCAN。基于密度的聚类算法(通过测量空间距离)是识别潜在差异化群体的有效方法。起初,我们使用 DBSCAN 来标记异常值。
简而言之,DBSCAN算法通过空间密度聚类将数据点分组,其核心逻辑是:当数据点之间的空间距离小于设定阈值(ε)时,这些点将被归为同一簇群。需要特别注意的是,来自长期或永久性故障慢速驱动器(fail-slow drives)的<延迟,吞吐量>数据对可能会形成独立于主集群的孤立簇群。因此,在后续建模过程中,我们仅保留数据点数量最多的主簇群。

加入 PCA。遗憾的是,直接对原始数据集应用DBSCAN算法进行筛选的效果有限。我们选择一个已确认存在故障慢速驱动器(fail-slow drive)的样本节点来说明该局限性。如图8a所示,在对该节点每日原始数据集应用调优后的DBSCAN算法(红色散点为识别出的异常值)后,将剩余数据(灰色散点)拟合为多项式回归模型(蓝色曲线为拟合结果,绿色虚线表示99.9%预测上限)。本案例中,DBSCAN算法仅识别出63.83%的慢速操作记录。
根本原因在于吞吐量与延迟存在正相关性,导致样本(即<延迟,吞吐量>数据对)在特征空间中呈现定向偏斜分布。这种特性使得异常值(来自故障慢速驱动器的样本)可能被误判为正常数据(如图8a中黑色圆圈所示)。为此,我们采用主成分分析(PCA)进行坐标变换,沿数据偏斜方向的垂直维度增强异常值惩罚权重,从而显著降低误标率。经实验验证,结合PCA的DBSCAN算法可实现92.55%的慢速操作检出率(见图8b)。
异常值的使用。回顾研究问题RQ4中的讨论,我们发现仅使用二元检测无法准确反映性能劣化程度。因此,我们摒弃了直接将异常检测结果二值化的常规做法(例如简单地将异常点标记为慢速操作而跳过§4.3节流程,或直接判定为故障慢速事件而跳过§4.3-§4.4节分析)。相反,我们通过排除异常样本构建高精度回归模型,以此量化每个操作记录的劣化程度。
4.3 回归模型
由于一个节点内正常的盘一般都有类似的 lvt分布,我们可以使用一个回归模型来解释这种正常盘的行为和划定性能波动的边界来进行fail-slow的探测。经典回归模型主要包含以下三大类,线性回归,多项式回归,kernel 回归。我们没有使用线性回归,因为延时和吞吐的关系明显是非线性的。由于延时和吞吐明显存在单调递增关系,所以使用kernel回归等复杂模型存在过拟合风险。多项式回归因其在保留模型简洁性的同时能有效处理非线性关系而成为更优选择——即用最少的参数实现理想的拟合优度。
4.4 辨认 fail-slow 事件
区分慢速日志。在建立回归模型后,可通过计算预测值上限来识别慢速操作记录,并据此检测故障慢速驱动器事件。例如,99.9%的预测上限意味着99.9%的波动范围被视为正常值。实际应用中,我们采用宽松(95%)与严格(99.9%)双上限组合策略,在避免过拟合的同时最大化故障驱动器的识别率。

创建事件。接下来,我们通过真实案例与模拟数据相结合的方式,演示如何准确定义故障慢速事件。如图 9a所示,灰色曲线表示盘的实际延时,蓝色曲线为模型拟合值,绿色曲线则是 99.9% 预测上限。通过将每个数据点的盘时延除以对应时刻的上限制,即可得到劣化比率(Slowdown ratio, SR)。例如:某盘在 1 分钟内的延时序列为15,20,25,10,5 毫秒,对应上限值为5,5,5,5,5 毫秒,则计算得到的 SR序列为 3 4 5 2 1。图 9b展示了候选盘的SR时序变化情况。
接下来,我们使用滑动窗口的机制来定义一个fail-slow事件(和尝试 2 类似)。滑动窗口有一个固定的长度,从第一个 entry 起始。在检测窗口内,当劣化比率序列的中位数超过设定阈值时,PERSEUS 将判定该盘在此时间段内发生了 fail-slow 事件,并根据后续数据点动态评估是否延长事件持续事件。
上面的例子(SR 序列 3 4 5 2 1),我们把最小的时间 span 是 1 分钟,比例阈值为 50%,SR 中位数阈值时 1 时,前四个 entry 会产生一个 fail-slow 事件,因为超过了 50% 的 SR 比阈值(1)有一个更高的中位值(3.5)。因为同样的原因,这个 fail-slow事件因该包含第五个 entry 。
实际上,我们把最小的 span 设为 5 分钟,比例是 50%,阈值是 1,意味着事件肯定是比上限要慢的。我们的逻辑是,仅当出现持续性的劣化记录序列时才判定为 fail-slow 事件,而短暂突发的性能波动则视为可接受的正常变化。在 9b 中 1 和 2 都有很高的SR值,但只有 2 会被当成 fail-slow事件。
4.5 Risk Score
最后更新于