告警去重与压缩
运维圈有个老梗:「告警不是怕不来,就怕来得太多太猛」。我记得刚带团队那会儿,碰上过一次底层网络抖动,五分钟内涌进来二十多万条重复告警。监控大屏直接卡死,值班同事手机震到没电。从那之后我就明白——去重压缩不是锦上添花,是保命手段。
这一章咱们把重复识别、压缩策略、时间窗口配置这三件事拆开揉碎了讲。说白了就是:怎么判断两条告警是「同一个事」、怎么把一堆重复告警压缩成一条、以及时间窗口设多大才不误杀也不漏报。
1 重复识别:给告警打「指纹」
判断重复最朴素的方式:比较告警的几个关键字段。我习惯把这套规则叫「告警指纹」——它由一组固定字段拼接而成,指纹相同就视为重复。
- 完全匹配:告警源标识 + 告警类型 + 告警级别 + 发生对象。四个字段一模一样,铁定是重复。
- 模糊匹配:有些字段(比如实例ID里带IP后缀)允许正则剔除变量部分。例如
/app-server-(\d+)/只看前缀app-server。 - 相似度计算:针对文本描述字段,用编辑距离或Jaccard系数算相似度。超过阈值(比如0.85)就算重复。这个慎用——算力开销大,实时流处理扛不住。
我的建议:线上环境优先用完全匹配+正则模糊匹配。相似度计算留给离线分析用,别在实时管道里跑Levenshtein。
2 压缩策略:三种常见模式
确认了重复,接下来怎么「压」?我见过不少团队上来就丢告警,结果重要信息一块儿丢了。压缩不是丢弃,是聚合+保留关键信息。下面三种策略我按推荐程度排了个序。
| 策略 | 做法 | 适用场景 | 我个人踩过的坑 |
|---|---|---|---|
| 相同告警压缩 | 指纹完全一致的告警,取第一条生成,后续只更新计数和时间戳 | 大量重复的CPU/内存/网络抖动告警 | 忘了带上首次/最近发生时间,排查时不知道持续了多久 |
| 相似告警合并 | 模糊匹配或同源规则合并,生成一条「聚合告警」附带子告警列表 | 同台机器多个磁盘分区同时IO高 | 合并后子列表太长,显示时截断反而丢了关键盘符 |
| 风暴抑制 | 设置速率阈值,超过后直接丢弃非关键告警,只输出一条风暴预警 | 网络闪断/机房掉电导致海量告警 | 阈值设低了,把恢复告警也丢了,事后复盘缺了恢复时间点 |
# 以相同告警压缩为例,核心伪代码
def dedup_and_compress(alert):
fingerprint = make_fingerprint(alert, fields=["source","type","severity","object"])
window_key = f"win_{fingerprint}"
# 从时间窗口缓存中取
entry = cache.get(window_key)
if entry:
entry.count += 1
entry.last_occurred = alert.timestamp
# 不产生新告警,只更新缓存
return None
else:
cache.set(window_key, AlertEntry(alert, count=1))
return alert # 产生一条
3 时间窗口配置:小了误报,大了漏报
去重压缩都离不开一个核心参数——时间窗口。窗口定义「多长时间内的重复算作一波事件」。我最早配置的时候随手填了个3秒,结果大量P0告警被压缩成一条,影响面都看不出来。后来改成60秒,又发现业务抖动恢复后,新一波告警因为还落在旧窗口里被错误压缩成老的。
窗口类型分两种:
- 固定窗口:整点对齐,每分钟/每5分钟一个桶。实现简单,但会切断连续事件。举个例子:告警发生在12:00:59和12:01:01,明明只差2秒,却被分到了两个窗口。
- 滑动窗口:以每条告警的真实发生时间为起点向后看一段时长。更自然,但内存开销更大。我一般用滑动窗口+过期淘汰,窗口大小设置成告警平均持续时间的1.5倍。
我曾经犯过的一个错误:给所有告警类型统一设了一个60秒窗口。结果内存告警是分钟级持续、网络告警是秒级抖动,压缩效果天差地别。现在我的做法:按告警类型/级别独立配置窗口。比如P0设120秒,P3设30秒。
还有两个常被忽略的参数:
- 静默期:一条告警被压缩后,下次再出现相同指纹是否立刻输出?建议加一个最小间隔,比如30秒内即使窗口过期也不重复上报。
- 最大压缩计数:聚合告警正文里显示的count上限。我见过count显示999999的,毫无意义。设个100,超过后用「100+」表示就够了。
4 避坑指南 & 最佳实践
说白了,这套方案跑得好不好全看参数调教。我把自己踩过的坑列出来,希望能帮各位省几周调参的时间。
- 不要全局用一套窗口。P0持续告警和P3瞬发告警行为完全不同。我习惯给每个告警级别打标签,窗口配置从标签继承。
- 去重前先做归一化。不同采集器上报的时间格式可能差毫秒级,字符串里的空格、大小写、IP前导零都得统一。不然指纹永远对不上。
- 压缩告警也要保留原始明细。压缩后的聚合告警里带一个外键,指向原始告警表的ID范围。复盘时能钻取查看每条原始记录。
- 设置告警压缩占比告警。如果某类告警的压缩比超过99%(比如10000条重复压缩成1条),说明可能基础配置有问题,触发一条「告警压缩异常」的运营告警。
一个小提醒:去重压缩不是万能的。对「同一个根因产生不同表象」的告警(比如主机CPU高引发多个进程告警),压缩解决不了,需要用后续的告警关联分析。所以压缩是第一步,别以为做完压缩就高枕无忧了。
总结一下我自己的配置模板——滑动窗口 + 完全匹配指纹 + 按级别差异化窗口 + 静默期30s + 最大计数200。这套配置在千亿级监控数据量的场景下跑过,压缩率稳定在85%~97%。你可以拿这个当起点,再根据业务调优。