4. PSI漂移告警数据采集架构:实时流式与离线批量

在可疑交易监测场景中,PSI(群体稳定性指标)漂移告警依赖高质量、低延迟的特征数据。数据采集架构需同时支撑实时流式(秒级/分钟级特征分布监控)与离线批量(T+1全量分布基线计算)两条链路。本章详细拆解基于Kafka/Flink的实时采集与基于Hive/Spark的离线采集架构设计。

4.1 双链路采集架构总览

实时链路负责交易事件流接入、特征提取与滑动窗口PSI计算;离线链路负责历史全量数据重算、分布基线生成与模型回测。两条链路在数据存储层(HDFS/对象存储)交汇,统一供给告警引擎。

架构核心原则:实时链路保证低延迟(P99 < 5s),离线链路保证高吞吐(单日百亿级交易量),两套管道互不阻塞,通过统一的特征元数据中心保持口径一致。
PSI漂移告警双链路数据采集架构 PSI漂移告警双链路数据采集架构 交易事件源(Kafka Topic) 实时流式采集(Flink + Kafka) 离线批量采集(Spark + Hive) 特征提取 & 滑动窗口聚合 实时PSI计算(分钟级) 全量历史数据ETL清洗 分布基线生成(T+1) 统一特征存储(HDFS/OSS) PSI漂移告警引擎

4.2 实时流式数据采集(Kafka + Flink)

实时链路以Kafka作为消息总线,Flink作为流处理引擎,完成从交易事件接入到特征分布聚合的全流程。

4.2.1 核心组件与职责

组件职责关键配置/参数
Kafka Source接入交易事件流,支持多分区高吞吐topic.replication.factor=3, min.insync.replicas=2
Flink DataStream实时特征提取、数据清洗、类型转换checkpoint间隔60s, exactly-once语义
滑动窗口聚合按特征维度统计分布直方图(分钟级)窗口大小10min, 滑动步长1min
PSI计算算子对比当前分布与基线分布,输出PSI值分箱数=20, 平滑因子ε=1e-6
Kafka Sink将PSI结果写入告警Topicacks=all, compression.type=snappy

4.2.2 Flink作业核心代码片段

// 实时PSI计算Flink作业骨架
DataStream<TransactionEvent> eventStream = env
    .addSource(new FlinkKafkaConsumer<>("txn-events", new AvroDeserializationSchema(), kafkaProps));

DataStream<FeatureDistribution> distStream = eventStream
    .keyBy(event -> event.getFeatureName())
    .window(SlidingProcessingTimeWindows.of(Time.minutes(10), Time.minutes(1)))
    .aggregate(new DistributionAggregator());

DataStream<PSIResult> psiStream = distStream
    .connect(baselineStream)  // 从状态后端或外部存储加载基线
    .process(new PSICalculator());

psiStream.addSink(new FlinkKafkaProducer<>("psi-alert", new JsonSerializationSchema(), kafkaProps));
env.execute("RealTime PSI Monitor");
生产环境避坑:实时PSI计算对状态后端压力较大,建议使用RocksDBStateBackend + 增量checkpoint;滑动窗口不宜过小(小于5min会导致频繁触发),推荐10min窗口+1min滑动步长。

4.3 离线批量数据采集(Hive + Spark)

离线链路负责T+1全量数据重算,生成特征分布基线、历史PSI趋势表以及模型回测数据集。采用Spark SQL + Hive分区表架构,支持增量与全量两种调度模式。

4.3.1 离线ETL流程

  1. 数据接入:从Kafka落盘HDFS(Parquet格式,按天分区),或直接从Hive ODS层读取。
  2. 特征清洗:过滤异常值、空值填充、类型统一,生成宽表 feature_wide_table。
  3. 分布计算:按特征+日期分组,计算等频分箱后的样本计数与占比。
  4. 基线生成:取最近N天(默认30天)的分布加权平均作为基线,存入 psi_baseline 表。
  5. PSI计算:逐日对比当日分布与基线,输出PSI值及漂移特征列表。

4.3.2 Spark SQL示例

-- 离线PSI基线生成SQL(Spark SQL)
INSERT OVERWRITE TABLE psi_baseline PARTITION(dt = '${yesterday}')
SELECT
    feature_name,
    bucket_id,
    SUM(cnt) / SUM(SUM(cnt)) OVER (PARTITION BY feature_name) AS baseline_ratio
FROM (
    SELECT
        feature_name,
        ntile(20) OVER (PARTITION BY feature_name ORDER BY feature_value) AS bucket_id,
        COUNT(*) AS cnt
    FROM feature_wide_table
    WHERE dt BETWEEN date_sub('${yesterday}', 29) AND '${yesterday}'
    GROUP BY feature_name, feature_value
) t
GROUP BY feature_name, bucket_id;
离线基线更新策略:建议采用滑动窗口(30天)而非固定全量,避免因业务季节性波动导致基线失真;同时保留快照版本,支持PSI回测与告警回溯。

4.4 实时与离线链路对比

对比维度实时流式(Kafka+Flink)离线批量(Hive+Spark)
延迟秒级~分钟级T+1(小时级)
吞吐单作业10万+ events/s百亿级/天
计算语义Exactly-once(checkpoint)幂等写(分区覆盖)
状态管理RocksDB状态后端Hive元数据 + HDFS
典型产出分钟级PSI告警事件日级PSI趋势表、基线快照
适用场景实时交易监控、快速漂移发现模型回测、报表分析、基线校准

4.5 架构设计关键要点

  • 特征元数据中心:实时与离线共用同一份特征定义(特征名、分箱数、数据类型),避免口径不一致导致PSI计算偏差。
  • 数据质量监控:在采集链路中嵌入数据质量检查(空值率、唯一值数、类型异常),异常数据单独写入死信队列(DLQ)并触发告警。
  • 容错与重试:Flink作业启用checkpoint + 重启策略;离线Spark任务启用shuffle服务 + 推测执行。
  • 存储选型:实时中间结果存RocksDB或Redis;离线基线存Hive ORC格式(高压缩比);PSI告警结果存Elasticsearch用于快速检索。
实时与离线链路数据流对比 实时 vs 离线 数据流对比 实时链路:Kafka → Flink → 滑动窗口 → PSI计算 延迟:秒级~分钟级 | 状态:RocksDB | 产出:告警事件 离线链路:HDFS → Spark → 分区聚合 → 基线生成 延迟:T+1 | 存储:Hive ORC | 产出:基线快照 统一特征存储(HDFS / OSS) 告警引擎 / 报表系统 / 模型回测

4.6 本章小结

PSI漂移告警的数据采集架构采用实时流式(Kafka+Flink)与离线批量(Hive+Spark)双轨并行模式。实时链路负责分钟级PSI计算与快速告警,离线链路负责日级基线校准与历史回测。两条链路通过统一特征存储和元数据中心保持口径一致,确保告警准确性与可回溯性。在实际部署中,需重点关注状态管理、数据质量监控以及基线更新策略,以应对金融交易场景下的高吞吐与低延迟挑战。