凌晨 2 点的 2σ 异常哨兵:在你醒来前抓住广告系列下滑
摘要
每晚 02:00 定时以 2σ 统计阈值扫描全部广告系列:统计发现异常(如展示量 −67%)、LLM 解释、证据链持久化留档——同日去重,外加 01:30 快照任务保证检测运行时必有昨日全量数据。
快速答案
凌晨哨兵有效的前提是数据先行:专门的 01:30 快照任务保证 02:00 扫描前必有昨日全量数据。检测用每个指标自己的 2σ 阈值而非固定数值,对同 campaign+metric 每日去重,且每个事件都带上历史均值、偏离幅度与异常分。
每天晚上 2:00,一个定时任务会扫描所有广告系列的指标,并用统计学阈值——两倍标准差(2σ)——与各自的历史分布对比。当一个系列的展示量从均值 301 跌了 67%,不再需要人类盯着看觉得“好像低了”:它偏离均值超过 2σ,自动变成带异常分的告警事件。你醒来收到的是诊断结果,而不是一个意外。
三层架构:检测、推理、持久化
这套系统刻意做成三层。第一层是纯统计:基于历史均值与标准差的阈值检测——没有启发式,没有“感觉不对”。第二层是 LLM 推理,把统计信号转成可读的因果解释。第三层把整个过程持久化——事件、异常分、最终证据链全部落盘,讨论不会丢失,同一个异常以后可复查、可用来训练判断。统计决定“发生了异常”,模型负责解释,记录让两者都对得起事实。
去重规则:同系列同指标,每天一次
没有去重,一个缓慢下滑的指标会被每次扫描反复标记,告警渠道变成噪音。我们的规则很简单:同一 campaign + 同一 metric 当天已经产生过异常事件,就跳过。每个系列每个指标每天最多一条。信号之所以还响,恰恰因为它足够稀有、值得读。
数据管道是命脉
异常检测只忠实于它读到的数据,这一点我们交过学费。早期 campaign_stats 由另一个 Agent 顺带写入,通常晚于凌晨 2:00 的检测运行——检测器把昨天的旧数据当成今天的在算,安静而系统性的陈旧。修复方式是把快照独立出来:现在由专门的定时任务在 1:30 生成每日 campaign_stats 快照,2:00 的检测运行保证每天都能读到昨天完整的数据集。
铁律:快照未被保证之前,检测绝不运行。数据完整性靠调度保证,不靠祈祷。
搭建你自己的凌晨 2 点哨兵
- 先快照,后检测。把每日状态采集做成独立的定时任务,运行在检测之前;数据缺失时检测要大声报错。
- 用统计阈值,不用固定数值。“偏离各自均值 2 个标准差”会随指标自适应,而写死的“-30%”是拍脑袋。
- 同日去重。同一系列同一指标每天一条,否则告警会变成没人看的噪音。
- 让异常事件自带上下文。每个事件同时存下历史均值、偏离幅度与异常分,任何人判断时都不用重新推一遍数字。
- 告警不是终点。把事件接上推理与人工复核——异常在那里才变成行动。
数学负责盯,管道负责等,人负责拍板。这正是我们 iport 归因增长引擎的架构:2σ 扫描、证据链、复核闭环,点一下就能调度。
常见问题
为什么用 2σ 而不是 -30% 这类固定阈值?
固定数值是拍脑袋且一成不变的;而偏离各自历史均值 2 个标准差,会随该指标的自然波动自适应。同一套逻辑就能覆盖基线差异巨大的各种系列,真正的偏离由统计定义,而不是靠人猜。
这套管道之前为什么出过问题?又是怎么修的?
早期 campaign_stats 由另一个 Agent 顺带写入,通常晚于 02:00 的检测运行,检测器把昨天的旧数据当成今天的在算。我们把快照生成改成专门的 01:30 定时任务,保证 02:00 扫描每天都能读到昨天完整的数据集。
出现异常告警就代表问题是真的吗?
不是——告警是起点,不是结论。统计标记显著偏离,LLM 把它推理成证据链,人类在任何行动之前先复核。同日去重保证每个系列-指标每天最多一条事件,让告警流始终可读。