1. 实时特征计算概述

大家好,我是你们的讲师。今天咱们正式开始《实时召回特征计算与存储》的第一章。说实话,每次讲这门课的开头,我都会想起自己刚接触推荐系统时的一个困惑:特征到底是怎么从原始日志变成模型能用的东西的? 这个过程,就是特征计算的核心。

这一章,我们先搭个框架。搞清楚实时特征计算在整个推荐系统里到底扮演什么角色,它和离线特征有什么本质区别。嗯,这部分概念虽然基础,但很多线上事故的根源,恰恰是对这些基础认知的偏差。

1.1 实时推荐系统架构概览

我们先看一张图。这是我个人习惯用的一个简化架构,去掉了那些花哨的组件,只保留最核心的链路。

核心观点: 实时推荐系统,说白了就是一条「数据进,结果出」的流水线。特征计算是这条流水线的中游枢纽。

实时推荐系统核心架构图 实时推荐系统核心架构 数据源层 用户行为日志 / 物品属性流 特征计算层 实时聚合 / 特征拼接 / 时间窗口 召回层 向量检索 / 多路召回 特征存储 Redis / Faiss / 特征服务 💡 关键说明 • 数据源层:产生原始行为日志(点击、曝光、时长)和物品属性变更。 • 特征计算层:将原始数据加工成模型可用的数值/向量特征。 • 特征存储:缓存计算好的特征,供召回和排序阶段高速读取。 • 召回层:利用特征进行候选集筛选,是推荐链路的第一道漏斗。

你想想看,用户点了一个商品,这个行为从产生到影响下一次推荐结果,中间经历了什么?

  1. 数据源层:行为日志被采集,发送到消息队列(比如 Kafka)。
  2. 特征计算层:消费消息,计算用户实时兴趣标签、物品实时热度等。
  3. 特征存储层:把计算结果写入高速缓存,覆盖旧值。
  4. 召回层:当用户发起请求时,直接从缓存读取最新特征,进行检索。

我在项目中遇到过好几次,团队花了大把精力优化召回模型,结果线上效果纹丝不动。最后排查下来,是特征计算延迟太高,模型拿到的都是几分钟前的「过期」特征。所以,特征计算是整个系统的「水龙头」——水龙头没拧开,后面管道再粗也没用。

1.2 特征计算在推荐链路中的位置

我们再把镜头拉近一点,看看特征计算具体卡在哪个环节。

一条完整的推荐链路,通常分为四个阶段:

阶段 核心任务 特征计算角色
数据接入 采集、清洗、格式化原始数据 定义特征来源和原始字段
特征计算 聚合、变换、拼接、存储特征 核心执行者
召回 从海量物品中筛选候选集 提供用户侧和物品侧特征
排序 对候选集精排打分 提供更丰富的交叉特征

你会发现,特征计算是唯一一个同时服务召回和排序的模块。而且,召回阶段对特征实时性的要求比排序更高。为什么?

排序阶段通常有几百个候选物品,可以容忍几百毫秒的延迟。但召回阶段面对的是千万级物品库,如果特征延迟导致召回结果「冷启动」或「兴趣漂移」,用户刷到的内容就会变得莫名其妙。

我的经验: 在搭建特征计算服务时,我建议把召回特征和排序特征分开存储。召回特征追求极致的读取速度(通常用 Redis 的 Hash 结构),排序特征可以容忍稍慢的读取,但需要更丰富的维度。混在一起存储,容易互相拖累。

1.3 实时 vs 离线特征对比

好了,到了这一节最核心的对比。很多同学会问:「离线跑批算特征不香吗?为什么非要实时计算?」

我们直接看对比表:

对比维度 离线特征 实时特征
计算时机 T+1 或小时级定时调度 事件触发,秒级/毫秒级响应
数据源 Hive 表、离线数仓 Kafka 流、实时日志
典型特征 用户长期偏好、物品基础属性 用户最近点击序列、实时热度
存储介质 HDFS、HBase Redis、内存网格
一致性要求 强一致(最终一致即可) 最终一致(允许短暂不一致)
计算复杂度 高(可跑复杂模型) 低(必须轻量快速)
典型延迟 分钟级 ~ 小时级 毫秒级 ~ 秒级

看到这里,你可能会想:「那是不是所有特征都应该实时化?」

千万别这么干。我曾经在一个项目里,试图把用户的「性别」「年龄」这类静态属性也做成实时特征。结果呢?计算逻辑没变,只是把数据源从 Hive 换成了 Kafka,白白增加了维护成本和延迟。这类特征,离线算好存起来,线上直接读,完全够用。

避坑指南: 我曾经犯过一个错误——把离线特征和实时特征放在同一个特征服务里,用同一个 key 覆盖存储。结果离线任务因为数据倾斜延迟了 30 分钟,导致实时特征被离线特征「回刷」成了旧值。线上推荐效果直接跳水。后来我学乖了:离线特征和实时特征必须用不同的 key 前缀,或者干脆分服务部署。

那么,什么样的特征适合实时计算?我总结了三类:

  • 用户短期行为序列:最近 5 分钟点击、最近 1 小时搜索词。这类特征时效性极强,离线算出来已经「凉了」。
  • 物品实时统计量:实时点击率、实时曝光量。用于捕捉突发热点。
  • 上下文特征:当前时间、用户网络环境、设备状态。这些特征只能在请求时实时获取。

而像「用户会员等级」「物品类目」「历史 CTR 均值」这类变化缓慢的特征,老老实实用离线计算就好。

1.4 本章小结

这一章我们主要理清了三个问题:

  1. 实时特征计算在架构中的位置:它是数据源和召回/排序之间的桥梁,决定了推荐系统能否「跟上」用户的变化。
  2. 特征计算服务于召回和排序,但召回对实时性的要求更苛刻。
  3. 实时特征和离线特征各有适用场景,不能一刀切。核心原则是:变化快的特征实时算,变化慢的特征离线算,两者隔离存储。