1. 平台架构总览:实时推荐系统整体架构、数据流转链路、核心组件介绍
大家好,我是这次课程的主讲。做实时推荐系统运维有些年头了,踩过的坑不少,积累的经验也还算扎实。今天咱们先聊聊整个平台的骨架——架构、数据怎么流、以及那几个核心组件到底在干什么。
你可能会问:为什么第一节课就要讲架构?我个人的习惯是,不管接手什么系统,第一件事就是把架构图画出来。没有全局视角,后面排查问题就像盲人摸象。说白了,你得知道数据从哪来、经过谁、最后去哪,才能知道故障出在哪一环。
一句话总结:实时推荐平台 = 实时采集 + 实时计算 + 实时存储 + 实时服务。四个环节缺一不可,任何一个环节出问题,推荐效果都会打折扣。
1.1 整体架构分层
我习惯把实时推荐平台分成四层来看。这样分层,故障定位会清晰很多。
- 数据接入层:负责收集用户行为日志、业务事件。主力是 Kafka。
- 实时计算层:负责特征计算、模型推理、规则引擎。主力是 Flink。
- 存储层:负责特征存储、模型参数、实时结果。主力是 Redis 和 HBase。
- 服务层:负责对外提供推荐 API,组装结果返回给客户端。
嗯,这里要注意:分层不是的。比如 Redis 既做缓存也做实时特征存储,HBase 既存画像也存中间结果。但脑子里有这个分层模型,遇到问题就能快速缩小范围。
下面这张图是我自己画的架构总览,你可以对照着看。
1.2 数据流转链路详解
数据是怎么一步步走的?我拿一个典型的「用户点击商品」事件来举例。
- 用户点击商品,前端 SDK 生成一条日志,包含 userId、itemId、timestamp、行为类型。
- 日志发送到 Kafka,写入名为
user_behavior的 Topic。这里一般会做分区,按 userId 哈希,保证同一个用户的行为落到同一个分区。 - Flink 消费 Kafka,做几件事:
- 解析 JSON,做数据清洗(过滤爬虫、异常数据)。
- 计算实时特征,比如「用户最近 5 分钟点击次数」「商品实时热度」。
- 调用模型服务,获取推荐候选集。
- 将特征和结果写入 Redis 和 HBase。
- 推荐服务收到请求,从 Redis 读取用户实时特征,从 HBase 读取用户长期画像,组装成最终推荐列表返回。
整个过程,从用户点击到推荐结果返回,延迟要求通常在 200ms 以内。嗯,这个 SLA 其实挺苛刻的。我在项目中遇到过因为 Kafka 消费积压导致推荐延迟飙升到 5 秒的情况,最后排查发现是 Flink 的 Checkpoint 超时了。
我的经验:数据链路中,最容易出问题的三个点是:Kafka 消费偏移量提交失败、Flink Checkpoint 超时、Redis 热 key 导致阻塞。后面我们会专门讲这些场景的排查方法。
1.3 核心组件介绍
四个组件,每个都有它的脾气。我挑重点说。
1.3.1 Kafka —— 数据高速公路
Kafka 是整个系统的数据总线。所有行为数据、业务事件都经过它。说白了,没有 Kafka,实时计算就是无源之水。
| 角色 | 说明 | 运维关注点 |
|---|---|---|
| Producer | 写入数据,如日志 Agent、业务服务 | 写入吞吐、ACK 策略、重试机制 |
| Broker | 存储数据,集群节点 | 磁盘空间、ISR 同步、Leader 选举 |
| Consumer | 消费数据,如 Flink、推荐服务 | 消费延迟、Rebalance 频率、偏移量提交 |
| Topic | 数据分类,如 user_behavior、item_update | 分区数、副本数、数据保留策略 |
我个人习惯把 Kafka 的监控放在第一位。消费延迟超过 1 分钟就要报警,超过 5 分钟就要介入。我曾经因为没及时处理消费积压,导致 Flink 任务 OOM,整个推荐链路挂了半小时。
1.3.2 Flink —— 实时计算引擎
Flink 是实时推荐的大脑。它负责消费 Kafka 数据,做各种计算。你想想看,如果没有 Flink,这些计算就得靠批处理,延迟至少几分钟,实时推荐就变成「准实时」了。
Flink 在实时推荐中的典型用法:
- CEP(复杂事件处理):识别用户行为序列,比如「用户连续点击 3 次同品类商品」,触发推荐策略调整。
- 实时特征计算:用 Flink SQL 做窗口聚合,比如
SELECT userId, COUNT(*) FROM clicks GROUP BY TUMBLE(ts, INTERVAL '5' MINUTE)。 - 模型推理:加载训练好的模型,对每条事件做实时打分。
注意:Flink 的 Checkpoint 是保证 Exactly-Once 语义的关键。但 Checkpoint 超时或失败,会导致数据重复或丢失。我建议 Checkpoint 间隔不要超过 5 分钟,超时时间设为 10 分钟。如果频繁超时,优先检查反压和 GC。
1.3.3 Redis —— 实时特征缓存
Redis 在实时推荐里主要干两件事:
- 缓存实时特征:比如用户最近 5 分钟的点击列表、商品实时热度。这些数据更新快,用 Redis 的 Hash 或 Sorted Set 存。
- 缓存模型参数:一些轻量级的模型参数,比如 LR 的权重,直接放 Redis,推理时毫秒级读取。
Redis 的坑主要在热 key 和大 key。我记得有一次,某个爆款商品的实时热度 key 被疯狂读取,导致 Redis 实例 CPU 打满,所有请求都卡住了。后来我们做了本地缓存 + 热 key 拆分才解决。
1.3.4 HBase —— 用户画像存储
HBase 存的是用户长期画像和物品属性。比如用户过去 30 天的购买记录、商品类目偏好。这些数据量大,但不需要毫秒级更新,HBase 的 LSM-Tree 结构很适合。
HBase 的 RowKey 设计很关键。我一般用 userId 反转 + 时间戳 作为 RowKey,这样能避免热点,同时支持按时间范围扫描。
组件选型总结:
- 需要高吞吐、持久化、顺序读写 → Kafka
- 需要状态计算、事件时间、Exactly-Once → Flink
- 需要毫秒级读写、高并发、数据结构丰富 → Redis
- 需要海量存储、稀疏列、范围扫描 → HBase
1.4 架构设计的几个原则
最后,分享几个我做架构设计时坚持的原则。这些原则帮我避免了不少线上事故。
- 解耦:每一层之间通过 Kafka 或 API 解耦。这样某一层挂了,不会直接拖垮其他层。
- 降级兜底:推荐服务必须有降级策略。比如 Redis 挂了,就从 HBase 读离线特征;HBase 也挂了,就返回热门推荐。
- 可观测性:每一层都要有完善的监控和日志。没有监控的架构,出了故障就是盲人摸象。
- 容量规划:Kafka 的分区数、Flink 的并行度、Redis 的内存、HBase 的 Region 数,都要提前规划好。我见过太多因为分区数不够导致消费倾斜的案例。
好了,这一章的内容就到这里。架构是骨架,数据是血液,组件是器官。理解了它们的关系,后面的故障排查才能有的放矢。