1、实时推荐系统概述
大家好,我是这门课的主讲。今天咱们聊聊实时推荐系统——说白了,就是用户刚点了个赞,下一秒推荐列表就得跟着变。我做了几年推荐系统,从离线批处理一路做到实时流处理,踩过的坑不少,今天把这些经验掰开揉碎了讲给你听。
什么是实时推荐
实时推荐,核心就一个字——快。
用户的行为数据从产生到影响推荐结果,延迟控制在秒级甚至毫秒级。你想想看,用户在双十一凌晨刷商品,每多等一秒,流失的订单可能就是几百万。我当年在电商平台做推荐,第一次上线实时模块时,看着用户点击后立刻刷出新内容,那种感觉,嗯,确实挺爽的。
实时推荐和传统离线推荐最大的区别在哪?我列个表你就明白了:
| 维度 | 离线推荐 | 实时推荐 |
|---|---|---|
| 数据处理延迟 | 小时级 / 天级 | 秒级 / 毫秒级 |
| 计算引擎 | Hive / Spark Batch | Flink / Spark Streaming |
| 存储选型 | HDFS / HBase | Redis / ClickHouse |
| 模型更新 | 定时全量重训 | 增量更新 + 近线融合 |
| 典型场景 | 每日热门榜单 | 「看了又看」实时推荐 |
核心要点:实时推荐不是要替代离线推荐,而是两者互补。离线做粗排和候选池生成,实时做精排和个性化兜底。我在项目里经常把离线产出的「用户长期兴趣」和实时计算的「短期行为」做加权融合,效果比单用任何一种都好。
业务场景分析
哪些业务场景必须上实时推荐?我挑三个最常见的说说:
1. 电商场景——「猜你喜欢」实时刷新
用户刚搜了「机械键盘」,又点进「青轴」商品详情页。这时候推荐系统应该立刻把「茶轴」「红轴」的对比款推上来,而不是等明天再更新。我曾经遇到过一个case:用户连续看了三款键盘都没下单,实时推荐立刻切到「键盘手托」和「鼠标垫」这类配件,转化率直接翻了一倍。
2. 内容资讯——「刷不完」的个性化 Feed
抖音、头条这类产品,用户每刷一下,推荐列表就得重新排。用户如果对某条视频点了「不感兴趣」,这条内容以及同类内容必须立刻从 feed 流消失。我记得有一次线上事故,实时屏蔽逻辑出了 bug,用户点了十几次「不感兴趣」还是能看到同类视频,那天的留存数据直接掉了两个点。
3. 社交推荐——「你可能认识的人」
用户刚关注了一个新好友,推荐列表里「共同好友」的权重就得立刻调整。这个场景对延迟要求极高,因为社交关系是实时变化的。我建议这类场景用 Flink 的 CEP(复杂事件处理)来做,比纯规则引擎灵活得多。
避坑指南:不是所有场景都需要实时。我曾经为了追求「实时」硬把用户画像的日更新改成秒更新,结果 Redis 集群被打爆,得不偿失。判断标准很简单——用户行为发生后,推荐结果在 10 秒内不更新会不会影响体验?如果不会,用近线(分钟级)就够了。
技术栈选型:Flink + Kafka + Redis + ClickHouse
这套组合拳,是我个人在多个项目中验证过的「黄金搭档」。为什么选它们?咱们一个一个说。
Flink——实时计算引擎
Flink 是目前流处理的事实标准。它支持 exactly-once 语义、事件时间处理、状态后端管理,这些特性在推荐场景里太重要了。我最早用 Spark Streaming 做实时推荐,遇到乱序数据时窗口计算经常不准,换成 Flink 后问题迎刃而解。
// Flink 实时推荐核心代码片段
DataStream<UserEvent> eventStream = env
.addSource(new KafkaSource<>())
.assignTimestampsAndWatermarks(
WatermarkStrategy.<UserEvent>forBoundedOutOfOrderness(Duration.ofSeconds(5))
);
// 实时计算用户短期兴趣向量
DataStream<UserVector> userVectorStream = eventStream
.keyBy(UserEvent::getUserId)
.process(new UserInterestProcessFunction());
Kafka——消息队列与数据管道
Kafka 负责承接所有用户行为日志,解耦数据生产端和消费端。我习惯把 Kafka 的 topic 按行为类型拆分:click_topic、purchase_topic、favorite_topic 等,方便 Flink 按需订阅。分区数建议设置为 Flink 并行度的 2-3 倍,这样能充分利用并行度。
Redis——实时特征存储
Redis 用来存用户最近 N 条行为、物品的实时热度、以及模型需要的特征缓存。我推荐用 Redis Cluster 模式,避免单点瓶颈。有个小技巧:把用户 ID 做哈希分片,让同一个用户的所有特征落在同一个 Redis 节点上,减少跨节点访问。
ClickHouse——实时 OLAP 分析
ClickHouse 用来做推荐结果的实时分析和监控。比如「过去 5 分钟推荐曝光了多少商品」「点击率是多少」,这些指标需要秒级响应。ClickHouse 的列式存储和向量化执行引擎,跑这类聚合查询比 MySQL 快两个数量级。
| 组件 | 核心职责 | 我推荐的版本 | 关键配置 |
|---|---|---|---|
| Flink | 实时流计算 + 状态管理 | 1.17+ | Checkpoint 间隔 30s,状态后端用 RocksDB |
| Kafka | 消息队列 + 数据缓冲 | 3.4+ | 分区数 = Flink 并行度 × 2,副本数 2 |
| Redis | 实时特征缓存 | 7.0+ | Cluster 模式,maxmemory-policy allkeys-lru |
| ClickHouse | 实时指标分析 | 23.3+ | MergeTree 引擎,分区按天 |
注意:技术栈选型不是一成不变的。如果你的业务量级不大(日均百万级事件),用 Flink + Kafka 可能太重了,换成 Redis + 简单的规则引擎也能跑。我见过不少团队一上来就上全套大数据组件,结果运维成本比开发成本还高。选型要匹配业务阶段。
系统架构总览
下面这张图是我画的一个简化版实时推荐架构。你看完就能明白数据是怎么从用户点击流到最终推荐结果的。
整个流程其实不复杂:
- 数据采集层:用户的行为(点击、购买、收藏)通过埋点上报到 Kafka。
- 实时计算层:Flink 从 Kafka 消费数据,做窗口聚合、特征提取,生成用户短期兴趣向量。
- 特征存储层:实时特征写入 Redis,供推荐服务低延迟读取;同时写入 ClickHouse 做监控分析。
- 推荐服务层:从 Redis 取实时特征,结合离线产出的候选池,做召回和排序,最终返回推荐列表给用户。
架构要点:这套架构里最容易被忽视的是「数据闭环」。推荐服务产出的结果(曝光、点击)要回流到 Kafka,形成新的行为数据,这样才能让模型持续自学习。我见过不少团队只做了正向流程,忽略了回流,结果模型越跑越偏。