4. 特征工程与实时特征计算:离线特征与在线特征对齐、实时特征存储、特征时间窗口计算

在实时交易风控系统中,特征工程是连接原始数据与模型决策的核心桥梁。离线训练阶段构建的数百个特征,必须在毫秒级的在线推理中精确复现,否则模型效果将急剧下降。本章聚焦于离线与在线特征的对齐策略、实时特征存储选型以及时间窗口计算的技术实现。

4.1 离线特征与在线特征对齐

离线特征通常基于全量历史数据批量计算,而在线特征依赖实时流式数据。两者在数据源、计算时间、特征值上必须严格一致,否则会导致训练-推理偏差(Training-Serving Skew)。

核心对齐原则: 离线特征计算逻辑必须作为在线特征计算的可执行规范,同一份代码、同一份配置、同一份时间窗口定义。

4.1.1 对齐的三大维度

维度 离线环境 在线环境 对齐策略
数据源 Hive / HDFS 历史分区 Kafka 实时消息 Schema 校验 + 字段映射表
计算逻辑 Spark / Hive SQL Flink / 自定义 C++ 算子 特征函数库统一(Java/Python)
时间窗口 固定时间范围(如 T-7d) 滑动窗口(如 7d 回溯) 窗口语义一致 + 边界对齐

4.1.2 特征对齐的工程实践

  1. 特征定义中心化:所有特征元数据(名称、类型、计算表达式、窗口参数)存储在统一的 Feature Registry 中。
  2. 离线-在线共用特征代码:将特征计算逻辑封装为独立函数库,离线批处理与在线流处理引用同一份 JAR 或共享库。
  3. 回放验证(Replay Test):将离线特征计算代码在在线数据流上回放,对比输出结果的一致性。
  4. 特征快照比对:在离线特征表与在线特征存储之间,定期抽样比对特征值,偏差超过阈值则触发告警。
经验提示: 建议在特征上线前执行“影子模式(Shadow Mode)”,在线服务同时计算新旧两版特征,对比差异并记录日志,确认无误后再切换。

4.2 实时特征存储:Redis 与 Feature Store

实时特征存储需要支持高频写入、低延迟读取、以及特征数据的时效性管理。Redis 和专用 Feature Store 是两种主流方案,各有适用场景。

4.2.1 Redis 作为实时特征缓存

Redis 凭借其内存数据结构和高吞吐能力,成为实时特征存储的首选缓存层。典型用法是以 entity_id + feature_name 为 Key,特征值为 Value,并设置 TTL 控制数据生命周期。

# 特征写入示例(Python + redis-py)
import redis
import json

r = redis.Redis(host='localhost', port=6379, decode_responses=True)

# 写入用户实时特征
user_id = "user_10086"
feature_key = f"feat:user:{user_id}:realtime"
feature_value = {
    "txn_count_1h": 12,
    "avg_amount_1h": 345.67,
    "device_risk_score": 0.87
}
r.hset(feature_key, mapping=feature_value)
r.expire(feature_key, 7200)  # 2小时过期

# 读取特征
features = r.hgetall(feature_key)
print(features)

4.2.2 专用 Feature Store(如 Feathr / Tecton)

Feature Store 在 Redis 之上增加了特征血缘管理、时间旅行、离线-在线一致性校验等能力,适合大规模特征治理场景。

能力 Redis 原生 Feature Store
读写延迟 < 1ms < 5ms(含序列化)
特征血缘 无 内置
时间旅行 不支持 支持
离线-在线一致性 需自建校验 自动对齐
运维复杂度 低 中高
选型建议: 若团队特征数量 < 200 且对血缘管理要求不高,优先使用 Redis + 自研封装;若特征规模上千且需要严格离线-在线一致性,建议引入 Feature Store。

4.3 特征时间窗口计算

交易风控中大量特征依赖时间窗口聚合,如“过去1小时交易次数”、“过去7天最大金额”。实时场景下,窗口计算面临数据乱序、延迟到达、窗口边界对齐等挑战。

4.3.1 窗口类型与适用场景

窗口类型 计算方式 典型特征 实时实现
滑动窗口 固定长度,每次滑动步长 过去1小时交易次数 Redis Sorted Set + 时间戳
滚动窗口 固定长度,不重叠 每小时交易总额 Flink Tumbling Window
会话窗口 基于不活动间隔 用户连续操作次数 Flink Session Window
累计窗口 从起点到当前 当日累计交易金额 Redis Counter + 每日重置

4.3.2 基于 Redis 的滑动窗口实现

利用 Redis Sorted Set 的 score 存储时间戳,可以高效实现滑动窗口聚合,避免全量扫描。

# 滑动窗口:记录交易时间戳并统计过去1小时交易次数
import time
import redis

r = redis.Redis(host='localhost', port=6379, decode_responses=True)
user_id = "user_10086"
window_key = f"window:txn:{user_id}"
window_seconds = 3600  # 1小时

# 记录新交易
now = time.time()
r.zadd(window_key, {str(now): now})

# 移除窗口外的旧数据
r.zremrangebyscore(window_key, 0, now - window_seconds)

# 统计窗口内交易次数
count = r.zcard(window_key)
print(f"Past 1h txn count: {count}")

# 设置过期防止内存泄漏
r.expire(window_key, window_seconds + 600)

4.3.3 时间窗口计算的工程挑战

  • 数据乱序:使用事件时间(Event Time)而非处理时间(Processing Time),并设置 allowed lateness 处理迟到数据。
  • 窗口边界对齐:离线窗口以自然时间(如整点)划分,在线窗口需使用相同的对齐策略(如 TumblingWindow 的 offset)。
  • 内存与性能平衡:对于高频实体,窗口数据量可能膨胀,需设置最大窗口大小或使用近似算法(如 HyperLogLog)。
  • 状态容错:Flink 等流处理引擎需启用 Checkpoint,确保窗口状态在故障后可恢复。
关键指标: 实时特征计算延迟应控制在 10ms 以内(从事件到达 Redis 到特征就绪),窗口聚合延迟不超过 50ms。

4.4 离线-在线特征对齐与实时存储架构

下图展示了离线特征与在线特征从定义、计算到存储的完整对齐流程,以及实时特征存储的读写路径。

离线-在线特征对齐与实时存储架构 离线-在线特征对齐与实时存储架构 离线特征计算 Spark / Hive SQL 离线特征表 Hive / HDFS 在线特征计算 Flink / 实时算子 实时特征存储 Redis / Feature Store 特征注册中心 Feature Registry / 元数据 拉取定义 拉取定义 回放验证 / 影子模式 在线推理服务 读取特征 对齐校验点: ① 特征定义一致性 ② 计算逻辑一致性 ③ 时间窗口边界一致性 ④ 特征值偏差监控

4.5 实时特征计算的性能优化

在每秒处理数千笔交易的场景下,特征计算必须兼顾延迟与吞吐。以下是经过生产验证的优化策略:

  • 特征预计算:对于固定窗口的聚合特征(如过去1小时交易次数),在数据写入时同步更新预计算值,避免查询时实时聚合。
  • 批量管道(Pipeline):使用 Redis Pipeline 或批量读取接口,减少网络往返次数。
  • 特征分级缓存:将高频访问的全局特征(如设备指纹库)放入本地缓存(如 Caffeine),减少对 Redis 的依赖。
  • 异步特征加载:在线推理时,将特征加载与模型计算异步化,利用 CompletableFuture 或协程提升吞吐。
  • 特征淘汰策略:对低频实体或过期特征,使用 LRU 或 TTL 机制及时清理,防止内存膨胀。
生产案例: 某支付平台将 80% 的滑动窗口特征改为预计算模式后,特征读取 P99 延迟从 15ms 降至 2ms,Redis 内存使用降低 40%。

4.6 特征时间窗口计算的实时流处理架构

下图展示了基于 Flink + Redis 的实时特征时间窗口计算架构,涵盖数据接入、窗口聚合、特征存储与在线读取的全链路。

实时特征时间窗口计算架构 实时特征时间窗口计算架构 Kafka 实时事件 交易 / 行为日志 Flink 流处理引擎 事件时间分配 + Watermark 滑动 / 滚动 / 会话窗口 Redis 特征存储 Sorted Set / Hash 预计算聚合值 在线推理服务 窗口计算示例(Flink SQL) -- 滑动窗口:过去1小时交易次数,每5分钟更新 SELECT userId, COUNT(*) AS txn_count_1h FROM txn_stream GROUP BY HOP(ts, INTERVAL '5' MINUTE, INTERVAL '1' HOUR), userId; 性能目标: 事件处理延迟 < 10ms | 窗口聚合延迟 < 50ms | 特征读取 P99 < 5ms | 吞吐 > 10,000 TPS

4.7 本章小结

特征工程在实时交易风控中承担着承上启下的关键角色。离线与在线特征的对齐是模型效果稳定的基石,实时特征存储的选型直接影响推理延迟,而时间窗口计算的准确性决定了风控策略的时效性。通过统一特征注册中心、回放验证机制、以及基于 Redis 或 Feature Store 的高效存储方案,可以构建一套高一致性、低延迟的实时特征计算体系,为后续的模型 Serving 提供可靠的特征输入。