一粟 · yisu.app
· 13 min read
异常检测

流量异常检测:从规则到时序模型

阈值告警的弊端显而易见,但又不能不设。本文梳理从固定阈值到 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 分钟内只告警一次。
  • 分桶:相同服务的告警合并。
  • 值班轮换:避免「同一时间只打扰一个人」。

值班与响应:比检测更关键

检测只是开始,响应才是闭环。健康的值班流程要求:

  1. 告警多通道(电话、IM、邮件)。
  2. 5 分钟内首响应,15 分钟内给方向。
  3. 值班交接要明确,uptime 流转在文档里。
  4. 所有 ack / close 都要写明原因。

否则再聪明的模型也只是「在墙上挂一个会叫的钟」。

让告警体系「自己学」

告警疲劳最危险的趋势是「人不管了」。我们要设计一套自动学习机制:

  • 每天统计未被处理的告警。
  • 如果某告警连续 7 天都没人 ack,就降级或剔除。
  • 事故复盘时让算法工程师参与更新阈值。

给团队的几条具体建议

  • 从 STL + MAD 起步,再考虑 Prophet、LSTM。
  • 把告警分级写到事故 Runbook。
  • 值班表与告警格式都做成模板。
  • 所有误报 / 漏报都要留样本,季度回顾。
  • 让告警系统是「活的」而不是「静态配置」。

异常检测不是技术问题,是治理问题。把告警做对,是把团队的注意力还回到真正重要的事——修复线上、保护用户。

季度回顾模板

一个简单的回顾会议议程:

  1. 本季度共触发多少条告警?答率多少?
  2. 无效告警占比?是否能剔除?
  3. 漏检的故障有哪些?后续加什么规则?
  4. 算法侧是否需要补充维度?
  5. 值班体验:工程师最抱怨哪条规则?

把回顾形成文档,运维、算法、产品都要签字。让告警治理与系统建设一样正式。

几个真实的小细节

我以前趟过的坑:

  • 用户流量里固定时段会有个 spike,把它「识别成异常」反而误报。结果发现是某 cron job 引发的用户操作。
  • 某个核心业务每天有 8 个长连接收拢,导致延迟 P99 抖成锯齿。把它并入基线。
  • 周末的低峰永远低于阈值,结果告警规则被反复禁用。

这些细节告诉我们:异常检测要细到「业务画像」,不是「通用规则」。把同样的心得总结下来,写进值班手册,下次就少踩一次。