@Harry_The_Nerd: https://x.com/Harry_The_Nerd/status/2069785739810705773
摘要
Netflix混合加权推荐系统设计的详细解析,涵盖规模估算、新用户冷启动策略、行为信号捕捉以及召回率与精确度的平衡。
查看缓存全文
缓存时间: 2026/06/25 11:17
Netflix推荐系统 - 机器学习系统设计
Netflix ML推荐系统:高层设计
问题陈述
Netflix服务着数亿用户,涵盖电影、剧集和纪录片。核心挑战(除了存储和流式传输内容)在于用户打开应用的瞬间,以每次都感觉个性化、相关且新鲜的方式,决定向每位用户展示什么。
一种朴素的方法是将用户严格分桶:电影观众只看电影,剧集观众只看剧集。但这样会造成内容孤岛,扼杀发现。更好的方法是采用“混合加权推荐模型“。如果某用户主要观看电影,其推荐组合大约为70%电影、15%剧集、15%纪录片。这既尊重了用户的兴趣倾向,又不会将其锁定在单一内容类别中。
支撑整个系统的两个ML指标是召回率(我们是否展示了用户可能会喜欢的内容?)和精确率(在我们展示的内容中,用户实际参与了多少?)。这两个目标驱动着每一层的架构设计。
规模与容量估算
在设计系统之前,我们先确定关键数字。
流量
- 日活跃用户:2亿
- 内容目录:10万部(电影+剧集+纪录片)
- 每个用户每天的交互事件:约50个
- 原始交互数据量:2亿 × 50 × 1KB = 每天10TB
- 每个用户每天的会话数:约2个,每个会话加载一次首页
- 推荐请求:2亿 × 2 = 每天4亿次请求 → 平均约4600 RPS,峰值约10000 RPS
存储
- 内容元数据:10万 × 1KB = 100MB(极小,可完全缓存在内存中)
- 视频:存储在S3中,通过CDN分发
- 条目嵌入向量:10万部×128维×4字节 = 约50MB(完全适合内存)
- 用户嵌入向量:2亿用户×128维×4字节 = 约100GB(存储在Redis或DynamoDB中,定期更新)
- 行为数据湖:Cassandra,每天摄入10TB原始信号
延迟预算
- Netflix首页必须在200ms内加载完毕。这意味着推荐流水线不能在每次请求时实时运行。推荐必须是预计算并缓存的,这样首页获取仅是一次缓存读取。
处理新用户:冷启动策略
全新用户没有观看历史、会话数据和行为信号。三种策略可优雅处理此问题。
1. 显式类型引导 注册时,向用户展示5到8种类型卡片(浪漫喜剧、惊悚片等),并请他们选择感兴趣的内容。这是一个轻量级的显式信号。引导过程必须控制在最多3到5次点击,因为如果感觉像填表,用户流失率会很高。
2. 全球及区域趋势内容 大多数新用户是为了热门、知名内容而来Netflix。展示全球趋势(全球Top10)和历史著名作品能为他们提供立即可用的体验。社会认同感可减少选择困难。
3. 地理位置和设备信号 即使用户尚未交互,其所在位置也是一个很强的隐式信号。区域内容偏好真实存在:印度偏向宝莱坞和地区语言内容,韩国偏向韩剧,以此类推。CDN以低延迟提供这些区域内容。注册时的设备类型(印度用户晚上10点使用手机)也是一个较弱但有用的信号。
过渡到个性化 一旦用户观看了2到3个内容,行为信号便开始积累。系统开始将协同过滤融入混合推荐中。随着个人数据的增长,冷启动模型逐渐退居次要地位。
行为信号
单纯点击是弱信号。系统必须捕获更丰富的用户行为以构建准确的偏好画像。
- 会话观看时长:观看的小时数,而不仅仅是打开了什么
- 完成率:90%完成是强正面信号;在20分钟时放弃是负面信号
- 重看:重看一部作品是系统中最强的兴趣信号之一
- 显式评分:点赞/点踩,稀疏但质量高
- 搜索查询:直接意图信号。搜索“犯罪惊悚片“明确透露了类型偏好
- 添加到观看列表但未播放:存在兴趣但有摩擦
- 时间段和设备:早晨使用手机建议短篇或休闲内容;晚上使用电视建议长篇沉浸式内容
- 跳过片头/跳过前情回顾行为:体现参与深度和熟悉度
所有这些信号都由数据聚合器服务摄入并写入Cassandra,以user_id + timestamp为键。这是一种写密集型、时间序列类似的工作负载,正是Cassandra在此规模下的设计目标。
什么是嵌入向量?
在描述ML流水线之前,理解嵌入向量很重要,因为它们是整个推荐系统的基础。
机器无法理解片名《绝命毒师》或《生活大爆炸》。它需要一种数值表示来捕获该作品的含义和特征。嵌入向量是高维空间中的密集数值向量,通常为128或256维,编码了实体的语义属性。
例如:
《绝命毒师》 = [0.82, 0.11, 0.94, 0.03, …] (128个数字) 《毒枭》 = [0.79, 0.13, 0.91, 0.06, …] (128个数字)
这两个向量在嵌入空间中距离很近,因为两者都是高紧张度的犯罪剧,涉及毒品主题,受众画像相似。**相似的内容聚集在一起。相似的用户聚集在一起。**推荐问题就变成了该向量空间中的最近邻搜索问题。
两种嵌入向量支撑本系统:
- 条目嵌入向量:每个作品一个向量。10万部×128维×4字节 = 约50MB。完全适合内存。
- 用户嵌入向量:每个用户一个向量,由其行为历史构建。2亿用户×128维×4字节 = 约100GB。存储在Redis中,按固定节奏更新。
系统架构:三个核心服务
通过API网关和负载均衡器后,推荐系统建立在三个服务之上。
1. 用户服务
处理用户档案管理。当用户打开应用时,用户服务触发推荐服务来填充该用户的首页。Kafka位于用户服务与推荐服务之间,用于将档案更新事件与推荐刷新周期解耦。这确保登录高峰不会压垮推荐流水线。
2. 推荐服务
这是系统的核心。它运行一个两阶段ML流水线:候选选取器后跟随排序器。
3. 数据聚合器服务
消费用户会话中的所有行为信号(点击、会话时长、观看时长、重看、添加到观看列表等),并将其写入Cassandra。ML模型基于这些数据训练。这里也使用Kafka缓冲高吞吐事件流,然后落地到存储。
两阶段ML流水线
这是推荐系统的核心。直接从10万部作品到排序后的20部列表,在单模型中以10000 RPS、200ms预算下进行,计算上不可行。两阶段方法干净地解决了这个问题。
第一阶段:候选选取器(召回模型)
目标:将10万部作品缩减到针对给定用户的最佳100个候选。
此阶段优先考虑召回率。它不能遗漏用户可能会喜欢的内容。这里速度比完美排序更重要。
机制是近似最近邻(ANN)搜索。将用户嵌入向量与所有条目嵌入向量在向量空间中进行比较,检索最近的100个作品。使用FAISS(Facebook AI相似性搜索)或Pinecone等工具,即使对10万个向量也能在毫秒内完成搜索。
协同过滤也会输入此阶段:观看了内容X的用户也观看了Y。这使召回范围超出单个用户的直接历史。
流程:用户嵌入向量 -> ANN搜索条目嵌入向量 -> 最佳100候选
第二阶段:排序器(精确率模型)
目标:对100个候选进行评分和排序,选出要展示的20部作品。
此阶段优先考虑精确率。它使用更丰富、更昂贵的特征,并通过一个更重的神经网络模型运行。特征包括:
- 用户观看历史和兴趣得分
- 内容新鲜度和发布日期
- 时间段和设备类型
- 相似用户的缩略图点击率
- 协同同伴中类似内容的完成率
每个候选获得一个分数。选择前20名,并写入Redis,键为user_id。
流程:100候选 + 丰富特征 -> 神经网络排序器 -> 前20得分 -> Redis
首页填充
当用户服务需要填充首页时,它调用Redis执行MGET获取该用户预计算的前20。这是一个亚毫秒操作。200ms首页预算轻松满足,因为请求时无需任何ML推断。
数据存储与模型新鲜度:Lambda架构
Cassandra大规模存储所有行为数据。但有两个问题:深层模型重训练需要数小时,无法持续运行;实时行为(10分钟前看了惊悚片)应立即影响下一次推荐。
Lambda架构解决了这两个问题。
批处理层 每24小时在完整Cassandra数据集上进行完整模型重训练。这是深层处理:完整重新计算用户嵌入向量和条目嵌入向量,捕获长期模式和季节性变化。这作为定时任务在夜间运行。
速度层 轻量级模型在实时Kafka流上运行。它捕获近期信号(上一会话的观看行为)并对用户嵌入向量进行增量更新,无需等待下一次完整重训练。如果你连续看了三部惊悚片,你的推荐会在几分钟内转向惊悚片,而不是第二天。
综上:
- 批处理层 -> 深度与准确性
- 速度层 -> 新鲜度与响应性
多样性注入:避免信息茧房
纯粹优化精确率的排序器最终会向用户展示20部犯罪惊悚片,因为那是其主要兴趣。这会造成信息茧房,扼杀内容发现,并长期增加流失率。
一个排序后多样性层位于排序器输出与Redis写入之间。它通过多种策略重新洗牌并限制最终20部作品。
类别上限:无论兴趣得分如何,单一类型占据20个位置中的不超过5到6个。
新颖性注入:刻意预留2到3个位置给用户从未接触过的作品,即使它们的排序器得分略低。这长期推动对利基内容的发现。
探索与利用(乐队机方法):85%的位置利用已知偏好。15%探索新领域。模型从探索位置的参与度中学习,并逐步将新偏好纳入用户嵌入向量。
基于栏架的多样性:Netflix首页并非单独的20部列表。它组织为水平栏架:“因为你看了X”、“印度趋势”、“新片上线”、“今天Top10”。每个栏架有自己的多样性和类别规则。这既是UX解决方案,也是针对信息茧房问题的算法方案。
端到端请求流程
用户打开Netflix应用 | v API网关 -> 负载均衡器 | v 用户服务(档案查找) | [Kafka事件] | v 推荐服务 | v Redis查找(MGET user_id的前20)<– 预计算,亚毫秒 | v 首页渲染,含个性化栏架内容 | (后台) | v 数据聚合器服务摄入会话信号 -> Kafka -> Cassandra | v 批处理重训练(每24小时)+ 速度层(实时流) | v 更新用户嵌入向量 -> 候选选取器 -> 排序器 -> 多样性层 -> Redis
技术总结
- API网关 + 负载均衡器:入口点,流量分发
- Kafka:服务间解耦,缓冲高吞吐事件流
- Cassandra:行为数据湖,写密集型时间序列事件(user_id + timestamp为键)
- FAISS / Pinecone:向量空间中的ANN搜索,用于候选生成
- Redis:预计算每个用户的前20推荐,亚毫秒MGET读取
- S3 + CDN:视频存储与分发,同时提供缩略图和预告片区域缓存
- Lambda架构:批处理层(24小时重训练)+ 速度层(实时Kafka流更新)
以上。祝好!
相似文章
PEARL:基于对比学习的无偏分位数估计在工业级直播推荐中的应用
PEARL引入了一种对比分位数近似框架,用以缓解推荐系统中的行为强度不平衡问题,在服务数十亿用户的生产级直播平台上实现了参与度指标的显著提升。
@amanaryan23: 这是我在研究Google、Microsoft、Meta、Amazon和Netflix的工程师如何构建真实系统后整理的完整路线图…
一份整理好的路线图,展示了Google、Microsoft、Meta、Amazon和Netflix的工程师如何构建真实系统。
@tonysimons_: 一位Netflix工程师构建了一个开源代理,可将AI token使用量减少60-95%。零代码更改。基准测试显示±0…
一位Netflix工程师构建了Headroom,这是一个开源代理,可在无需代码更改且精度损失可忽略的情况下,将LLM上下文压缩60-95%。它支持主要AI代理,并在GitHub上以Apache 2.0许可提供。
τ-Rec:面向智能推荐系统的可验证基准
τ-Rec是一个用于智能推荐系统的可验证基准,它用可验证奖励和控制对话约束取代了主观的LLM-as-a-judge评估,揭示了主流模型存在陡峭的可靠性悬崖——即便是表现最佳的模型,其pass@1也仅有约57%。
如何在没有行为数据的情况下解决个性化冷启动问题?
一位软件工程师询问如何为没有行为数据的新用户引导个性化推荐,讨论内容推荐中的冷启动问题。