3. 商户风险数据模型:风险事件表结构、商户画像字段、批次偏移量定义
在构建批次偏移诊断系统之前,必须统一数据模型。本章定义三个核心数据实体:风险事件表(记录单次风险行为)、商户画像字段(描述商户静态与动态特征)、批次偏移量(衡量风险迁移的量化指标)。三者共同构成Flink实时计算的输入与输出基础。
3.1 风险事件表结构
风险事件表是实时流的事实表,每行代表一次被检测到的风险行为。表结构设计需兼顾写入吞吐与查询效率,以下为标准化定义:
| 字段名 | 类型 | 说明 | 示例 |
|---|---|---|---|
event_id |
STRING | 全局唯一事件ID,由Flink算子生成 | evt_20250321_001234 |
merchant_id |
STRING | 商户唯一标识 | mch_887766 |
risk_type |
INT | 风险类型编码:1-欺诈 2-洗钱 3-套现 4-违规经营 | 2 |
risk_level |
INT | 风险等级:1-低 2-中 3-高 4-严重 | 3 |
event_time |
BIGINT | 事件发生时间戳(毫秒) | 1742524800000 |
batch_id |
STRING | 所属批次ID,用于批次聚合 | batch_20250321 |
amount |
DECIMAL(18,2) | 涉及交易金额 | 15000.00 |
source_channel |
STRING | 风险来源渠道:online/offline/api | online |
raw_data |
JSON | 原始风险报文,用于回溯 | {...} |
设计要点:
event_time 使用毫秒级BIGINT而非TIMESTAMP,可避免时区转换歧义,同时提升Flink窗口聚合性能。batch_id 字段是批次偏移计算的分组键,必须保证在数据源端或上游算子中正确赋值。
3.2 商户画像字段
商户画像属于维度表,描述商户的静态注册信息与动态行为特征。画像字段每24小时由批处理任务更新一次,并加载到Flink的BroadcastState中供实时流关联。
| 字段分类 | 字段名 | 类型 | 说明 |
|---|---|---|---|
| 静态画像 | merchant_name |
STRING | 商户注册名称 |
industry_code |
STRING | 行业分类编码(如 5411-食品零售) | |
register_date |
STRING | 注册日期 yyyyMMdd | |
| 动态画像 | total_risk_count_7d |
INT | 近7天风险事件总数 |
avg_risk_level_30d |
DECIMAL(3,2) | 近30天平均风险等级 | |
last_risk_time |
BIGINT | 最近一次风险事件时间戳 | |
risk_migration_flag |
INT | 风险迁移标记:0-无迁移 1-正向迁移 2-负向迁移 |
Flink关联策略: 动态画像字段由离线数仓每日凌晨产出,通过
BroadcastProcessFunction 广播到所有并行子任务。实时风险事件流在 processElement() 中根据 merchant_id 从 BroadcastState 读取画像,完成风险迁移判断。
3.3 批次偏移量定义
批次偏移量是衡量商户风险在不同批次之间变化程度的量化指标。定义如下:
// 批次偏移量计算公式
batch_offset = (current_batch_risk_score - previous_batch_risk_score)
/ (max_possible_risk_score - min_possible_risk_score)
// 其中:
// current_batch_risk_score = Σ(事件风险等级 × 事件权重) / 批次内事件总数
// previous_batch_risk_score = 上一批次同商户的加权风险得分
// 分母归一化到 [0, 1] 区间
偏移量的取值范围与业务含义:
| 偏移量区间 | 业务含义 | 诊断动作 |
|---|---|---|
| [-0.1, 0.1] | 风险稳定,无显著迁移 | 维持现有监控频率 |
| (0.1, 0.4] | 轻度正向迁移(风险上升) | 提升监控等级至中 |
| (0.4, 1.0] | 重度正向迁移(风险急剧上升) | 触发人工审核 + 临时冻结 |
| [-0.4, -0.1) | 轻度负向迁移(风险下降) | 降低监控频率 |
| [-1.0, -0.4) | 重度负向迁移(风险显著下降) | 移出高风险名单 |
注意: 批次偏移量计算依赖 连续两个批次 的数据。若商户在上一批次无风险事件,则
previous_batch_risk_score 取默认值 0,此时偏移量仅反映当前批次绝对风险水平,不反映真实迁移趋势。建议在Flink中增加 batch_count 计数器,仅当连续批次数 ≥ 2 时才输出偏移量。
3.4 数据模型关系图
下图展示风险事件表、商户画像与批次偏移量之间的数据流转与关联关系:
3.5 批次偏移量计算示例
以下Flink SQL示例展示如何基于风险事件表计算商户的批次偏移量:
-- 步骤1:按批次和商户聚合风险得分
CREATE VIEW batch_risk_score AS
SELECT
merchant_id,
batch_id,
AVG(risk_level) AS avg_risk_level,
COUNT(*) AS event_count
FROM risk_events
GROUP BY merchant_id, batch_id;
-- 步骤2:关联上一批次得分,计算偏移量
SELECT
curr.merchant_id,
curr.batch_id AS current_batch,
prev.batch_id AS previous_batch,
curr.avg_risk_level AS current_score,
COALESCE(prev.avg_risk_level, 0) AS previous_score,
(curr.avg_risk_level - COALESCE(prev.avg_risk_level, 0)) / 3.0 AS batch_offset
FROM batch_risk_score curr
LEFT JOIN batch_risk_score prev
ON curr.merchant_id = prev.merchant_id
AND prev.batch_id = (
SELECT MAX(batch_id)
FROM batch_risk_score
WHERE merchant_id = curr.merchant_id
AND batch_id < curr.batch_id
);
Flink优化建议: 上述SQL在数据量较大时建议改用
OVER 窗口函数或 IntervalJoin 实现,避免自关联带来的性能瓶颈。生产环境中可将上一批次得分预存入 ValueState,在 KeyedProcessFunction 中逐条计算偏移量,延迟更低。