3、指标异常检测:从统计到机器学习的实战路径
大家好,我是老赵。今天咱们聊聊指标异常检测。
做运维的,谁没被半夜的告警电话吵醒过?我印象最深的一次,凌晨三点,某核心业务的响应时间突然飙到 5 秒,值班同事慌了,直接重启了所有节点。结果呢?业务恢复了,但根因到底是什么,谁也不知道。说白了,这就是典型的「告警疲劳」——我们收到了太多无效的波动,却错过了真正的故障。
所以,异常检测的核心不是「检测异常」,而是「找到真正需要你关注的异常」。今天我就把三种主流方法掰开揉碎了讲给你听。
一、基于统计学的检测方法:简单但有效
先聊最基础的。统计学方法,说白了就是假设你的数据服从某种分布,然后看新来的点是不是「离群」了。
1. 3-Sigma 法则
这个方法我估计大家都听过。假设数据服从正态分布,那么 99.7% 的数据会落在均值 ±3 个标准差之内。超出这个范围的,就算异常。
公式很简单:
异常阈值 = μ ± 3σ
但这里有个坑。我在项目中遇到过,某业务的 CPU 使用率长期在 10% 左右波动,突然有一天升到 30%。按 3-Sigma 算,30% 远没到阈值,但业务方已经炸了。为什么?因为数据本身不是正态分布,而是偏态的。
2. 绝对中位差(MAD)
MAD 是 3-Sigma 的「鲁棒版」。它用中位数代替均值,用 MAD 代替标准差,对异常点不那么敏感。
MAD = median(|x_i - median(x)|)
异常阈值 = median(x) ± 3 * MAD
嗯,这里要注意:MAD 的系数 3 不是固定的。我习惯用 2.5 或 3.5,取决于你对异常的容忍度。比如监控磁盘 IO,我一般用 3.5,因为磁盘波动本来就大。
| 方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 3-Sigma | 正态分布数据 | 计算简单,直观 | 对异常点敏感 |
| MAD | 偏态分布、有离群点 | 鲁棒性强 | 计算稍复杂 |
二、基于时间序列的检测:让数据自己说话
统计学方法有个问题:它不考虑时间顺序。你想想看,上午 10 点的 CPU 和凌晨 2 点的 CPU,能一样吗?所以我们需要时间序列方法。
1. 移动平均(Moving Average)
移动平均,说白了就是用过去 N 个点的平均值来预测当前点。如果实际值和预测值差太多,就是异常。
预测值 = (x_{t-1} + x_{t-2} + ... + x_{t-N}) / N
异常 = |实际值 - 预测值| > 阈值
我一般用 5 分钟窗口做移动平均。为什么是 5 分钟?因为大多数告警的响应时间在 5 分钟内是合理的。太长会漏报,太短会误报。
2. 指数平滑(Exponential Smoothing)
移动平均有个问题:它对所有历史数据一视同仁。但直觉告诉我们,越近的数据越重要。指数平滑就是干这个的——它给近期的数据更高的权重。
预测值 = α * x_{t-1} + (1-α) * 上一时刻预测值
α 是平滑系数,范围 0 到 1。α 越大,对近期数据越敏感。我习惯设 α=0.3,这样既不会太敏感,也不会太迟钝。
我记得有一次,某业务的流量突然下降 20%,移动平均没检测到,但指数平滑在 3 分钟内就告警了。为什么?因为指数平滑对「趋势变化」更敏感。
三、基于机器学习的检测:当规则不够用时
前面两种方法,说白了都是「规则驱动」的。但现实中的指标往往有复杂的非线性关系,比如 CPU 和内存的交互影响。这时候,机器学习就派上用场了。
Isolation Forest(孤立森林)
这个名字很有意思。它的核心思想是:异常点更容易被「孤立」出来。你想想看,正常数据往往聚在一起,要切很多刀才能分开;而异常点孤零零的,一刀就能切出来。
算法流程:
- 随机选一个特征,随机选一个切分点
- 把数据分成左右两部分
- 重复,直到每个点都被孤立
- 异常得分 = 路径长度的倒数(路径越短,越可能是异常)
from sklearn.ensemble import IsolationForest
model = IsolationForest(contamination=0.01) # 假设 1% 是异常
model.fit(data)
predictions = model.predict(new_data) # -1 表示异常
这里有个参数 contamination,它表示你预期数据中异常的比例。我一般设 0.01 到 0.05。设得太高,会把正常点误判为异常;设得太低,会漏掉真正的故障。
四、三种方法怎么选?一张图说清楚
说了这么多,你可能会问:到底用哪种?我的建议是:
- 数据简单、分布已知 → 用 3-Sigma 或 MAD
- 有时间趋势、周期性 → 用移动平均或指数平滑
- 多维指标、复杂关系 → 用 Isolation Forest
但说实话,生产环境中我从来不会只用一种方法。我习惯「组合拳」:先用移动平均做快速检测,再用 Isolation Forest 做深度分析。这样既能保证实时性,又能提高准确率。
最后说一句:没有银弹。每种方法都有它的适用场景,也有它的坑。我见过有人用 3-Sigma 检测 CPU 异常,结果因为数据不是正态分布,误报率高达 50%。也见过有人用 Isolation Forest 检测简单的阈值问题,结果模型训练时间比告警时间还长。
所以,我的建议是:先理解你的数据,再选方法。如果时间允许,三种方法都跑一遍,看哪个效果最好。毕竟,运维的本质不是炫技,而是解决问题。
- 统计学方法:简单快速,适合正态分布数据
- 时间序列方法:考虑趋势和周期性,适合有规律的指标
- 机器学习方法:处理复杂关系,适合多维数据
- 组合使用:先快速检测,再深度分析