流量异常检测:从规则到时序模型
阈值告警的弊端显而易见,但又不能不设。本文梳理从固定阈值到 STL + MAD、再到 Prophet / LSTM 的演进,结合告警分级、值班制度,构建一套可以自我演化的检测体系。
为什么这是每个团队都要解决的事
流量异常检测,听上去是 SRE 工程师的事。但今天,它更是数据、算法、产品需要共同把控的能力:从「页面卡顿」到「业务被薅羊毛」,一个好的检测体系能省下无数人力。
而糟糕的检测体系要么让告警泛滥要么让真正的异常淹没。我们的目标不是把告警做得更多,而是做得更准。
固定阈值:最朴素也最容易翻车
最开始我们用的就是「CPU 高于 80%」「QPS 高于 1 万」。这种规则的缺点是显然的:
- 无法适应业务的自然波动(白天 / 凌晨、平时 / 周末)。
- 漏检非常多,只在严重异常时触发。
- 无法区分「业务活动拉升」与「真实异常」。
但新手团队还在用,因为它易于理解、便于撰写。
STL + MAD:让阈值跟着趋势走
第一步升级是用「趋势 + 残差」的方式。其中 STL(季节-趋势分解)把时序拆成 trend + seasonal + residual,再用 MAD(中位数绝对偏差)对残差做稳健估计:
import pandas as pd
from statsmodels.tsa.seasonal import STL
import numpy as np
series = pd.read_csv('qps.csv', index_col='ts', parse_dates=True)
result = STL(series, period=1440).fit() # 一天 1440 分钟
resid = result.resid
mad = np.median(np.abs(resid - np.median(resid)))
threshold = 3.5 * 1.4826 * mad
alerts = (np.abs(resid) > threshold)
这种做法的优势是:阈值跟着历史节奏走,不会被业务高峰误判。
Prophet:业务假期友好
当时间序列里包含「双十一」「春节」这种事件时,Prophet 几乎是首选。它的设计目标就是「业务侧节假日友好」。
- 内置趋势 + 季节项。
- 支持事件影响(holidays, special_promotions)。
- 接口简单,可解释性强。
Prophet 不只是预测工具,更是「业务沟通工具」。它的多项式趋势 + 节假日先验与业务语言接近。
LSTM 与更复杂模型
当数据源非常复杂、又有大量历史时,LSTM / Temporal Fusion Transformer 等深度模型能捕获非线性模式。但它们的代价是:
- 训练 / 推理成本高。
- 解释性差,业务解释「为什么告警」很费劲。
- 需要持续重训,否则漂移。
对大多数中小团队,Prophet 已经足够;只有需要更精细预测时才上 LSTM。
多维度异常
单维度的「QPS 高于阈值」容易误判。更高质量的检测是把多维度组合起来:
| 维度 | 关注点 |
|---|---|
| 流量 | QPS、UV、API 命中 |
| 延迟 | P50、P95、P99 延迟 |
| 错误 | 5xx、4xx、超时 |
| 资源 | CPU、内存、连接 |
| 业务 | 转化率、订单量 |
把多个维度的偏离合成 Z-score(或机器学习打分),得到综合异常概率。这避免「QPS 升高是因为活动」被误报。
告警分级与降噪
即便检测准确,告警也可能淹没值班工程师。常见降噪手段:
- 分级:P0(业务中断)/ P1(严重)/ P2(退化)/ P3(提示)。
- 抑制:相同故障源在 15 分钟内只告警一次。
- 分桶:相同服务的告警合并。
- 值班轮换:避免「同一时间只打扰一个人」。
值班与响应:比检测更关键
检测只是开始,响应才是闭环。健康的值班流程要求:
- 告警多通道(电话、IM、邮件)。
- 5 分钟内首响应,15 分钟内给方向。
- 值班交接要明确,uptime 流转在文档里。
- 所有 ack / close 都要写明原因。
否则再聪明的模型也只是「在墙上挂一个会叫的钟」。
让告警体系「自己学」
告警疲劳最危险的趋势是「人不管了」。我们要设计一套自动学习机制:
- 每天统计未被处理的告警。
- 如果某告警连续 7 天都没人 ack,就降级或剔除。
- 事故复盘时让算法工程师参与更新阈值。
给团队的几条具体建议
- 从 STL + MAD 起步,再考虑 Prophet、LSTM。
- 把告警分级写到事故 Runbook。
- 值班表与告警格式都做成模板。
- 所有误报 / 漏报都要留样本,季度回顾。
- 让告警系统是「活的」而不是「静态配置」。
异常检测不是技术问题,是治理问题。把告警做对,是把团队的注意力还回到真正重要的事——修复线上、保护用户。
季度回顾模板
一个简单的回顾会议议程:
- 本季度共触发多少条告警?答率多少?
- 无效告警占比?是否能剔除?
- 漏检的故障有哪些?后续加什么规则?
- 算法侧是否需要补充维度?
- 值班体验:工程师最抱怨哪条规则?
把回顾形成文档,运维、算法、产品都要签字。让告警治理与系统建设一样正式。
几个真实的小细节
我以前趟过的坑:
- 用户流量里固定时段会有个 spike,把它「识别成异常」反而误报。结果发现是某 cron job 引发的用户操作。
- 某个核心业务每天有 8 个长连接收拢,导致延迟 P99 抖成锯齿。把它并入基线。
- 周末的低峰永远低于阈值,结果告警规则被反复禁用。
这些细节告诉我们:异常检测要细到「业务画像」,不是「通用规则」。把同样的心得总结下来,写进值班手册,下次就少踩一次。