3. 历史数据基础:告警时间序列数据的采集、清洗与存储格式

告警降噪阈值策略的 A/B 测试,其核心假设是“历史告警行为能够预测未来模式”。因此,历史数据的质量直接决定了阈值验证的可信度。本章聚焦于如何从生产环境中可靠地采集、清洗并格式化存储告警时间序列数据,为后续的统计分析和策略模拟打下坚实基础。

3.1 告警时间序列的数据特征与采集源

告警数据本质上是一种带有时间戳、状态和属性的离散事件流。与连续型监控指标(如 CPU 使用率)不同,告警事件具有突发性、稀疏性和多维度标签的特点。常见的采集源包括:

采集源 数据格式 典型字段 采集方式
Prometheus Alertmanager JSON / Webhook alertname, instance, severity, startsAt, endsAt, annotations Webhook Receiver / API 拉取
Zabbix JSON / XML eventid, clock, value, triggerid, host, priority API 轮询 / 数据库直连
自研监控系统 Protobuf / Avro rule_id, entity, status, first_occurred, last_occurred, count 消息队列(Kafka)订阅
日志告警系统 JSON Lines log_source, pattern, level, timestamp, host, message Filebeat / Fluentd 采集
关键原则:采集时务必保留告警的 开始时间 和 结束时间(或恢复时间)。仅保留触发时间会导致无法计算告警持续时间、恢复时长等关键特征,严重影响降噪策略的评估。

3.2 数据清洗:从原始事件到可用时间序列

原始告警数据通常包含大量噪声、重复和格式不一致问题。清洗流程分为以下四个核心步骤:

  1. 去重与合并(Deduplication & Merging):同一告警规则在短时间内可能多次触发。需根据 alertname + instance + fingerprint 进行分组,合并重叠的告警区间,保留最早开始时间和最晚结束时间。
  2. 时间戳对齐(Timestamp Alignment):不同采集源的时间戳精度可能不同(秒级 vs 毫秒级)。统一转换为 Unix 时间戳(秒级),并处理时区偏移,确保所有数据在同一时间轴上。
  3. 异常值过滤(Outlier Filtering):剔除明显异常的数据点,例如:开始时间晚于结束时间、时间戳为未来时间、持续时间超过 30 天(通常为误报或系统故障)。
  4. 标签标准化(Label Normalization):统一标签键名(如 host 与 instance 统一为 entity),去除无意义的标签(如 alert_id 自增 ID),保留用于分组和聚合的维度。
清洗效果指标:经过上述清洗后,数据量通常减少 20%~40%,但数据质量显著提升。建议在清洗前后分别记录行数、唯一告警规则数、时间跨度,作为数据质量报告的基础。

3.3 存储格式:面向分析的时间序列表设计

清洗后的数据需要以适合分析查询的格式存储。推荐使用列式存储(如 Parquet)或时序数据库(如 ClickHouse、InfluxDB)。以下是一个通用的告警事件表结构设计:

-- 告警事件明细表 (alert_events)
CREATE TABLE alert_events (
    event_id        UInt64,          -- 全局唯一事件 ID
    rule_name       String,          -- 告警规则名称
    entity          String,          -- 告警对象(主机、服务、容器)
    severity        String,          -- 严重级别 (critical, warning, info)
    status          String,          -- 当前状态 (firing, resolved)
    start_ts        DateTime,        -- 告警开始时间
    end_ts          DateTime,        -- 告警结束时间(NULL 表示未恢复)
    duration_sec    UInt32,          -- 持续时间(秒),由 end_ts - start_ts 计算
    labels          Map(String, String), -- 其他标签键值对
    annotations     String,          -- 告警注释信息
    ingestion_ts    DateTime,        -- 数据写入时间
    partition_date  Date             -- 分区字段,按天分区
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(partition_date)
ORDER BY (rule_name, entity, start_ts);
避坑提示:不要将告警事件直接存储在关系型数据库的单表中而不做分区。告警数据量增长极快,未分区的表在查询数月数据时会导致全表扫描,A/B 测试的模拟计算将变得不可用。务必按时间(月/周)进行分区。

3.4 数据管道架构:从采集到存储的完整链路

为了支撑 A/B 测试的反复回放与验证,数据管道需要具备高吞吐、低延迟和可回溯的特性。下图展示了推荐的告警数据采集与存储架构:

告警时间序列数据采集与存储架构 Prometheus Zabbix 自研系统 Kafka / Pulsar 统一事件总线 流式清洗引擎 去重 · 对齐 · 过滤 ClickHouse / Parquet 列式存储 · 按天分区 A/B 测试分析引擎 阈值回放 · 效果评估 数据管道关键说明 1. 所有采集源统一推送至消息队列,实现解耦与缓冲。 2. 流式清洗引擎实时处理,保证数据到达存储层时已是标准化格式。 3. 分析引擎直接读取列式存储,支持快速回放任意时间窗口的历史告警。

3.5 数据质量校验清单

在将数据用于 A/B 测试之前,建议执行以下校验,确保数据集的完整性和一致性:

校验项 检查方法 合格标准
时间连续性 按小时统计告警事件数,检查是否存在长时间无数据窗口 连续缺失不超过 1 小时
状态完整性 检查每条告警是否都有对应的 resolved 事件 未恢复告警占比 < 5%
标签一致性 统计 rule_name 和 entity 的枚举值,检查是否有异常空值 空值占比 < 0.1%
时间戳合理性 检查 start_ts 是否在数据采集时间之前 未来时间戳占比 = 0%
最佳实践:建议将清洗后的数据同时保存一份原始快照(Raw Snapshot),以便在发现清洗逻辑有误时能够重新处理。原始快照可以存储在廉价的对象存储(如 S3、MinIO)中,按天归档。