4. Flink Table & SQL:动态表概念、流式SQL查询、窗口聚合与Top-N

在反欺诈实时特征工程中,Flink Table & SQL API 提供了声明式的流处理范式。本章将深入解析动态表(Dynamic Table)的核心原理,并演示如何通过流式 SQL 完成窗口聚合与 Top-N 排序,构建实时特征指标。

4.1 动态表(Dynamic Table)概念

传统数据库表是静态的,而 Flink 将流(Stream)抽象为动态表——一个随时间不断演变的逻辑视图。每次数据到达,动态表都会触发 INSERT、UPDATE 或 DELETE 操作。

核心映射关系: 流 → 动态表(Append / Retract / Upsert) → 连续查询(Continuous Query) → 结果动态表 → 流
动态表与流的关系 数据流 INSERT 事件 转换 动态表 INSERT / UPDATE / DELETE 随时间演变 连续查询 结果动态表 聚合 / 窗口 / Top-N 持续更新 输出 流 💡 关键理解 • Append 模式:只追加 INSERT,适用于简单过滤、投影 • Retract 模式:INSERT + DELETE,适用于 GROUP BY 聚合 • Upsert 模式:INSERT + UPDATE,适用于 Keyed 表(如 Kafka 消息带 Key)

4.2 流式 SQL 查询基础

Flink SQL 支持标准 DML 和 DDL,但流式查询必须考虑无界数据和事件时间。以下是在反欺诈场景中常用的流式查询模式。

4.2.1 创建基于 Kafka 的动态表

-- 定义 Kafka 源表(交易事件流)
CREATE TABLE transaction_events (
  trans_id      STRING,
  user_id       STRING,
  amount        DECIMAL(10, 2),
  trans_time    TIMESTAMP(3),
  trans_type    STRING,
  -- 事件时间属性
  WATERMARK FOR trans_time AS trans_time - INTERVAL '5' SECOND
) WITH (
  'connector' = 'kafka',
  'topic' = 'transactions',
  'properties.bootstrap.servers' = 'kafka:9092',
  'format' = 'json',
  'scan.startup.mode' = 'latest-offset'
);
反欺诈实践提示: WATERMARK 延迟设为 5 秒,允许乱序交易事件在 5 秒内被正确分配到窗口,避免因网络延迟导致特征计算偏差。

4.2.2 简单过滤与投影

-- 筛选高风险交易(大额 + 特定类型)
SELECT trans_id, user_id, amount, trans_time
FROM transaction_events
WHERE amount > 10000
  AND trans_type IN ('TRANSFER', 'WITHDRAW');

4.3 窗口聚合(Window Aggregation)

窗口聚合是实时特征的核心。Flink SQL 支持三种窗口类型:Tumble(滚动窗口)、Hop(滑动窗口)、Session(会话窗口)。

窗口类型 语义 反欺诈场景示例 SQL 示例
Tumble 固定大小,不重叠 每 5 分钟统计用户交易总额 TUMBLE(trans_time, INTERVAL '5' MINUTE)
Hop 固定大小,可重叠(滑动步长) 每 1 分钟统计过去 10 分钟交易次数 HOP(trans_time, INTERVAL '1' MINUTE, INTERVAL '10' MINUTE)
Session 基于不活动间隔划分 用户连续操作间隔超过 30 秒视为新会话 SESSION(trans_time, INTERVAL '30' SECOND)

4.3.1 滚动窗口聚合:用户 5 分钟交易总额

-- 每 5 分钟计算每个用户的交易总额和交易次数
SELECT
  user_id,
  TUMBLE_START(trans_time, INTERVAL '5' MINUTE) AS window_start,
  TUMBLE_END(trans_time, INTERVAL '5' MINUTE)   AS window_end,
  SUM(amount)   AS total_amount,
  COUNT(*)      AS trans_count
FROM transaction_events
GROUP BY
  user_id,
  TUMBLE(trans_time, INTERVAL '5' MINUTE);

4.3.2 滑动窗口聚合:实时滑动平均交易额

-- 每 1 分钟计算过去 10 分钟的平均交易额
SELECT
  user_id,
  HOP_START(trans_time, INTERVAL '1' MINUTE, INTERVAL '10' MINUTE) AS window_start,
  HOP_END(trans_time, INTERVAL '1' MINUTE, INTERVAL '10' MINUTE)   AS window_end,
  AVG(amount)   AS avg_amount_10min
FROM transaction_events
GROUP BY
  user_id,
  HOP(trans_time, INTERVAL '1' MINUTE, INTERVAL '10' MINUTE);
Flink SQL 三种窗口类型对比 时间轴 T1 T2 T3 Tumble(5min) 不重叠,固定间隔 窗口1(10min) 窗口2(10min) 窗口3(10min) Hop(滑动步长1min,窗口10min) 重叠,高时间分辨率 会话1 会话2 会话3 Session(间隔30s) 按不活动间隔切分

4.4 Top-N 查询:实时特征排名

在反欺诈中,Top-N 用于识别高频交易用户、最大金额交易、异常设备登录次数等。Flink SQL 通过 ROW_NUMBER() 窗口函数实现高效 Top-N。

4.4.1 全局 Top-N:每个窗口内交易金额最高的 3 笔

-- 每 5 分钟窗口内,按交易金额降序取前 3 笔
SELECT *
FROM (
  SELECT
    trans_id,
    user_id,
    amount,
    trans_time,
    TUMBLE_START(trans_time, INTERVAL '5' MINUTE) AS window_start,
    ROW_NUMBER() OVER (
      PARTITION BY TUMBLE(trans_time, INTERVAL '5' MINUTE)
      ORDER BY amount DESC
    ) AS rn
  FROM transaction_events
) WHERE rn <= 3;

4.4.2 分组 Top-N:每个用户最近 3 笔交易

-- 每个用户按交易时间降序取最近 3 笔
SELECT *
FROM (
  SELECT
    trans_id,
    user_id,
    amount,
    trans_time,
    ROW_NUMBER() OVER (
      PARTITION BY user_id
      ORDER BY trans_time DESC
    ) AS rn
  FROM transaction_events
) WHERE rn <= 3;
⚠️ 性能注意事项: Top-N 查询需要在 PARTITION BY 键上维护排序状态。对于高频用户(如每秒数百笔交易),建议配合窗口使用,避免无界状态膨胀。可设置 table.exec.state.ttl 控制状态存活时间。

4.5 反欺诈实战:实时特征组合

将窗口聚合与 Top-N 结合,构建完整的反欺诈特征管道。

-- 特征1:用户 5 分钟交易总额(滚动窗口)
-- 特征2:用户 5 分钟交易次数
-- 特征3:用户 5 分钟内最大单笔交易
-- 特征4:用户 5 分钟内交易金额 Top-3 的平均值

CREATE VIEW user_5min_features AS
SELECT
  user_id,
  window_start,
  window_end,
  total_amount,
  trans_count,
  max_amount,
  top3_avg_amount
FROM (
  SELECT
    user_id,
    TUMBLE_START(trans_time, INTERVAL '5' MINUTE) AS window_start,
    TUMBLE_END(trans_time, INTERVAL '5' MINUTE)   AS window_end,
    SUM(amount)   AS total_amount,
    COUNT(*)      AS trans_count,
    MAX(amount)   AS max_amount,
    AVG(CASE WHEN rn <= 3 THEN amount END) AS top3_avg_amount
  FROM (
    SELECT *,
      ROW_NUMBER() OVER (
        PARTITION BY user_id, TUMBLE(trans_time, INTERVAL '5' MINUTE)
        ORDER BY amount DESC
      ) AS rn
    FROM transaction_events
  )
  GROUP BY
    user_id,
    TUMBLE(trans_time, INTERVAL '5' MINUTE)
);
输出到反欺诈特征存储: 上述视图结果可写入 Redis、HBase 或 Kafka 特征主题,供实时规则引擎或模型推理使用。每个窗口输出一条特征记录,key 为 user_id + window_start。

4.6 本章小结

  • 动态表是 Flink 流式 SQL 的基石,将无界流映射为持续更新的表。
  • 流式 SQL 支持标准查询语法,但需关注 WATERMARK 和事件时间语义。
  • 窗口聚合(Tumble / Hop / Session)是实时特征计算的核心模式。
  • Top-N 通过 ROW_NUMBER() 实现高效排名,适用于异常检测和特征筛选。
  • 反欺诈实战中,将窗口聚合与 Top-N 组合,可生成高价值的多维度实时特征。