背景
开发环境、生成环境,通常会有很多种告警,用来及时发现问题
粗暴的处理告警,通常会导致刷屏,进而麻木,最后起不到告警的作用
这里设计一个简单的去重机制
实现方案
方案一:把告警信息打到 alarm 服,让 alarm 服去重处理
方案二:每个服通过 Redis 共享 alarm 信息,自己处理去重
因为 alarm 去重逻辑很简单,方案一显得稍重,需要额外维护服务
因此采用方案二
Redis 数据结构设计
对于每类告警日志,设计以下 key-value :
内容 | 格式 | 说明 |
---|---|---|
key | alarm_{{yyyyMMdd}}_{{文件名}} _{{行号}} | 过期时间:当日剩余秒数 |
value | 正数 | 值:当日告警次数 |
cmd | INCRBY |
使用 Redis INCRBY 命令有以下作用:
- 多进程避免竞态
- 根据返回值可以知道是否是当日首次告警
- 进而处理首次逻辑:告警;设置过期时间
- 可以批次维护告警次数值,避免频繁访问 Redis
告警流程
- 触发需要告警时,执行:
n=INCRBY alarm_{{yyyyMMdd}}_{{文件名}} _{{行号}} addNum
- 如果
n == addNum
,则执行告警,并设置 key 的过期时间 - 单日累计次数告警。如 1000 次,告警下:
{{文件名}}:{{行号}} 当日累计 {{次数}} 次
- 可以根据
(n-addNum)/1000 + 1 = n/1000
,判断是否需要告警单日累计次数
- 可以根据
编码优化:
- 执行
INCRBY
命令期间,若又来告警:- 本地计数
- 退让算法,计算下次 INCRBY 时间