2. 特征服务架构概览:实时特征计算、离线特征存储、特征网关的典型架构与数据流
在信用评分系统中,特征服务是连接原始数据与模型推理的核心中间层。一个生产级的特征服务架构通常由实时特征计算、离线特征存储和特征网关三大模块构成。理解这三者的职责划分与数据流转,是后续缓存策略优化的基础。
2.1 三大核心模块的职责与对比
| 模块 | 核心职责 | 典型技术选型 | 数据时效性 | 存储特征 |
|---|---|---|---|---|
| 实时特征计算 | 在请求到达时,基于原始事件流或在线数据源,实时计算派生特征(如近30天消费总额、当前负债率)。 | Flink、Spark Streaming、自研规则引擎 | 毫秒~秒级 | 内存/热数据 |
| 离线特征存储 | 存储经过批处理加工的历史特征宽表,用于模型训练、批量推理和冷启动场景。 | Hive、HBase、ClickHouse、Iceberg | T+1 或小时级 | 全量历史 |
| 特征网关 | 统一特征获取入口,负责路由、合并、缓存、降级与限流,对上游屏蔽底层存储和计算细节。 | 自研网关、Spring Cloud Gateway + Redis | 亚毫秒级路由 | 缓存层 |
架构原则:实时计算负责"新鲜度",离线存储负责"完整性",特征网关负责"可用性"。三者通过明确的接口契约解耦,任何一方的变更不应影响其他模块的稳定性。
2.2 典型架构与数据流
下图展示了信用评分场景下,一次在线评分请求经过特征服务架构的完整数据流。请求从业务端发起,经特征网关统一调度,按需从缓存、实时计算引擎或离线存储中获取特征值,最终组装成特征向量返回给评分引擎。
关键数据流路径:
- 主路径(缓存命中):请求 → 特征网关 → 缓存层 → 直接返回特征向量。延迟通常 < 5ms。
- 次路径(缓存未命中 + 实时特征):请求 → 特征网关 → 缓存未命中 → 路由至实时计算引擎 → 特征组装 → 回填缓存 → 返回。延迟 20~100ms。
- 次路径(缓存未命中 + 离线特征):请求 → 特征网关 → 缓存未命中 → 路由至离线存储 → 特征组装 → 回填缓存 → 返回。延迟 10~50ms(取决于存储引擎)。
2.3 特征网关的内部处理流程
特征网关是整个架构的"交通枢纽",其内部处理流程可拆解为以下步骤:
- 协议解析与鉴权:解析请求中的用户ID、场景ID、所需特征列表,校验调用方权限。
- 缓存查询:批量查询本地缓存(Caffeine)和分布式缓存(Redis),标记命中和未命中特征。
- 路由决策:对未命中特征,根据特征元数据(时效性要求、计算成本、数据源类型)决定走实时计算还是离线存储。
- 并行获取:异步并发调用实时计算引擎和离线存储,设置超时熔断(默认 200ms)。
- 特征合并与回填:合并缓存命中结果和远程获取结果,异步回填缓存(设置 TTL),返回完整特征向量。
⚠️ 常见陷阱:特征网关不应在请求路径中同步等待离线存储的批量扫描结果。对于需要全量历史数据的特征(如"近 2 年逾期次数"),应通过预计算+定时预热的方式提前写入缓存,避免在线请求穿透至离线存储导致超时。
2.4 实时特征计算与离线特征存储的协作模式
实时与离线并非完全独立,二者通过特征对齐和数据补偿机制协同工作:
| 协作场景 | 实时计算角色 | 离线存储角色 | 典型处理方式 |
|---|---|---|---|
| 冷启动 | 无历史数据,无法计算 | 提供历史宽表作为初始特征 | 离线批处理生成特征快照,导入缓存 |
| 在线评分 | 计算近实时特征(如当日交易次数) | 提供长周期统计特征(如近 6 个月平均额度使用率) | 网关合并实时+离线结果 |
| 数据回填 | 产生实时事件日志 | 消费日志,更新离线宽表 | 实时计算写入消息队列 → 离线批处理消费 |
| 特征一致性校验 | 提供在线特征快照 | 提供离线特征快照 | 定时比对,偏差超过阈值则告警 |
2.5 架构设计对缓存策略的影响
特征服务架构的上述特点,直接决定了缓存策略的设计要点:
- 特征粒度:缓存以单个特征为最小单位(如
user:12345:consume_30d_sum),而非整个特征向量,便于局部更新和复用。 - TTL 差异化:实时计算产出的特征 TTL 通常较短(30~300 秒),离线特征 TTL 可设置较长(1~24 小时),由特征元数据驱动。
- 缓存穿透防护:对于不存在于任何数据源的特征(如新用户无历史数据),网关应缓存空值或默认值(TTL 30 秒),避免每次请求都穿透至后端。
- 缓存预热:每日凌晨离线批处理完成后,主动将高频特征批量写入缓存,减少次日在线请求的缓存未命中率。
架构视角:缓存不是独立组件,而是特征网关内部的一个可插拔模块。优秀的架构设计允许在不修改业务代码的前提下,切换缓存实现(如从 Redis 切换到 Redis Cluster 或自研缓存),甚至动态调整每个特征的缓存策略。