案例 05 · FeedStream:社交 Feed 与视频内容分发系统
一句话点题:本案例练的是「内容分发的放大效应」——Feed 系统的难点不是存一条内容,而是让千万人各自刷到不同的一屏,并在大 V、爆款视频、搜索、推荐和 CDN 成本之间做取舍。
🧪 案例篇第 5 篇 · 本案例只练一件事
练社交 Feed + 内容搜索 + 视频分发下的架构判断:什么时候用推模型,什么时候用拉模型,大 V 和爆款内容怎么兜住,视频为什么必须转码和 CDN,搜索 / 推荐 / 审核如何不拖垮主链路。
读完你应该能 本案例靠什么练 说清 Feed 为什么不是简单查帖子列表 用读写不对称和个性化首页解释时间线收件箱 判断推 / 拉 / 混合 Feed 怎么选 用普通人推、大 V 拉解决扇出爆炸 看懂图片 / 视频为什么不能走业务源站 用转码、分片、CDN、预热和回源解释带宽成本 把搜索、推荐、审核放进内容分发架构 用召回 / 排序 / 审核召回和降级兜住体验与安全 重要提醒:下面是教学化案例,不是某个社交平台的内部图纸。 数字用于数量级推理,目的是练判断,不是给出唯一答案。
开场:为什么 Feed 不是「查我关注的人发了什么」
因为一个内容产品真正卖的不是发帖按钮,而是用户每次打开时那一屏内容。
FeedStream 是一个图文 + 短视频内容社区。用户可以关注创作者、发布图文或视频、点赞评论、搜索内容,也会看到系统推荐的内容。普通创作者只有几百粉丝,头部创作者有几百万粉丝。热门视频上线后,几十万人会在几分钟内同时点开。
第一眼看,它像是普通内容系统:
- 用户发帖;
- 粉丝看首页;
- 点赞评论;
- 搜索关键词;
- 上传视频;
- 推荐一些内容。
但真正上线后,最危险的不是「帖子存不下」,而是:
首页刷新太慢、大 V 一发文打爆扇出队列、爆款视频回源压垮源站、违规内容已经扩散到几百万人的时间线里。
所以这一章不写「怎么做一个帖子表」。它问一个更具体的问题:
如何把海量内容分发给不同的人,同时控制热点、排序、媒体带宽和内容安全?
这章和前几章的压力源不同:
- StarArena 怕的是库存和支付状态。
- PatchDesk 怕的是多租户边界。
- DocuMind 怕的是答案可信。
- SyncRoom 怕的是实时状态收敛。
- FeedStream 怕的是一次写入被放大成海量读取、海量分发和海量带宽。
读前小词典
这篇会反复出现几个词,先用人话对齐一下:
| 词 | 人话解释 |
|---|---|
| Feed | 信息流。用户打开首页看到的一串内容。 |
| Timeline | 时间线。按某种顺序排列的一组内容 ID,可以是个人主页流,也可以是首页流。 |
| Fan-out | 扇出。一条内容要分发给很多接收者。 |
| 推模型 / 写扩散 | 发文时就把内容 ID 写进粉丝的收件箱,读的时候很快。 |
| 拉模型 / 读扩散 | 发文时只存一份,用户刷新时再去拉取关注对象的内容。 |
| 混合模型 | 普通人走推,大 V 走拉。避免大 V 发文时一次写爆。 |
| 大 V | 粉丝很多的头部创作者。它的发文会造成极端扇出。 |
| 收件箱 | 每个用户自己的 Feed 候选列表,通常只存内容 ID,不存正文。 |
| 召回 | 先从海量内容里粗略找一批候选。 |
| 排序 / 精排 | 对候选内容打分,决定先给用户看哪条。 |
| CDN | Content Delivery Network,内容分发网络。把图片、视频等静态内容缓存到离用户更近的边缘节点。 |
| 回源 | CDN 没命中缓存,只能回到源站 / 对象存储拿内容。回源通常更慢也更贵。 |
| 转码 | 把一个源视频加工成多种清晰度 / 码率,让不同网络都能播放。 |
| ABR | Adaptive Bitrate,自适应码率。播放器根据网络情况动态切换清晰度。 |
| 审核召回 | 内容被判违规后,不仅要下架原文,还要从搜索、推荐、时间线、缓存里撤掉。 |
一、起始状态:先验证内容供给和消费,别先造推荐帝国
FeedStream 的第一版目标很朴素:让用户能关注创作者,看到关注内容,发布图文和短视频。
起始阶段的约束大概是这样:
| 维度 | 起始阶段 |
|---|---|
| 日活用户 | 1 万以内 |
| 创作者 | 1,000~5,000 |
| 日发内容 | 5,000~20,000 条 |
| 视频占比 | 10%~20% |
| 峰值 Feed 读取 | 200~500 QPS |
| 团队规模 | 5~8 名工程师 |
| 核心目标 | 验证有没有人发、有没有人刷、有没有互动 |
| 最不能错 | 首页不能长期刷不出;违规内容不能无控制扩散 |
这时最合理的架构不是全量推荐平台,而是内容服务 + 关注关系 + 简单 Feed 读取 + 对象存储 / CDN:
用户发内容
│
▼
┌────────────────────────────────────────────┐
│ 内容服务 │
│ 写帖子正文、媒体地址、作者、可见性、审核状态 │
└──────────────┬─────────────────────────────┘
▼
┌──────────────┐
│ 内容存储 │
│ post / media │
└──────────────┘
用户刷首页
│
▼
┌────────────────────────────────────────────┐
│ Feed 读取服务 │
│ 查关注列表 → 拉取最近内容 → 简单排序 → 返回 │
└────────────────────────────────────────────┘
图片 / 视频 → 对象存储 → CDN这不是「架构简陋」。在没有大 V、没有海量读之前,拉模型简单、灵活,足够验证产品。
二、量化假设:它不是被写入压垮,而是被读取和热点压垮
先算一笔账。假设 FeedStream 推广半年后:
日活用户:2,000,000
月活用户:10,000,000
创作者:500,000
每日新内容:1,000,000 条
视频内容:200,000 条/天
峰值发文:2,000~5,000 条/秒
峰值 Feed 刷新:50,000~150,000 QPS
普通用户粉丝:100~2,000
中腰部创作者粉丝:10,000~200,000
头部创作者粉丝:1,000,000~20,000,000
爆款视频:10 分钟内 500,000 次播放
目标:首页刷新 P95 < 500ms,发文到可见通常 < 10s
视频目标:首帧 < 2s,卡顿率尽量接近 0,CDN 命中率 > 95%
审核目标:高风险内容先审后扩散;违规内容 5 分钟内从主要分发面撤回这个数量级里,写内容不是最大问题。真正危险的是:
- 读远多于写:一次发文后,可能被读几千、几万、几百万次。
- 粉丝分布极端倾斜:普通人几百粉,大 V 几百万粉,不能同一种扇出策略。
- 视频带宽是真成本:每多播放一分钟,都在烧 CDN 和带宽钱。
- 违规内容会被系统放大:Feed 和推荐越强,扩散越快,召回也越难。
所以 FeedStream 的架构重心不是「帖子怎么落库」,而是:
把个性化读取变快,把热点扩散变可控,把媒体分发从源站挪到边缘,把审核召回做成系统能力。
三、触发信号:什么时候说明第一版开始不够用
第一版跑起来后,不要凭感觉升级。看这些信号:
| 信号 | 表现 | 为什么这是架构问题 |
|---|---|---|
| 首页刷新越来越慢 | 用户关注 1,000 人后,每次刷新都要聚合很多人的内容 | 纯拉模型读放大,读路径开始扛不住 |
| 大 V 发文导致队列堆积 | 一条内容要写入几百万粉丝收件箱 | 纯推模型遇到头部账号扇出爆炸 |
| 热门内容正文查询打满 | 爆款内容被反复回填正文 | 内容正文和媒体缺少热点缓存 |
| 视频播放回源飙升 | 新热视频上线后 CDN 未命中,源站带宽打满 | 热点内容没有预热 / 回源合并 |
| 搜索结果搜不到新内容 | 新内容发布几分钟后还搜不到 | 索引新鲜度跟不上 |
| 推荐结果质量波动 | 用户刷到大量重复、低质、过期内容 | 召回 / 排序 / 去重链路不稳定 |
| 违规内容扩散后难撤 | 内容删了,但 Feed、搜索、缓存里还能看到 | 审核状态没有贯穿分发链路 |
| 点赞数忽高忽低 | 计数缓存和真实互动日志长期不一致 | 派生计数没有可重算来源 |
这些信号不是在说「数据库不够大」。它们在说:内容分发开始放大一切,包括热点、成本和错误。
四、核心矛盾:每个人都要一条自己的首页
FeedStream 的核心对象有四组:
- 内容 / 媒体 / 作者:发了什么,媒体在哪里,审核状态如何。
- 关注关系 / 可见性:谁关注谁,谁能看到这条内容,拉黑和隐私规则是什么。
- 时间线 / 推荐候选 / 排序结果:用户首页那一屏从哪里来,为什么这样排。
- 搜索 / 审核 / 互动信号:内容能不能搜到,能不能继续分发,用户如何反馈。
如果只看最简单路径,它像这样:
用户刷新首页 → 查我关注的人 → 查他们最近发的内容 → 排序返回但真实系统必须在每一步都回答:
- 我关注的人很多,每次都现查能不能撑住?
- 大 V 发文时,要不要写进每个粉丝的收件箱?
- 时间线里存正文还是只存内容 ID?
- 推荐排序能不能在 500ms 内完成?
- 视频播放从哪里取?CDN 没命中怎么办?
- 内容后来被判违规,怎么从时间线、搜索、推荐、CDN 里撤掉?
所以新的架构命题变成:
Feed 是一台个性化内容分发引擎,不是一张 posts 表。
关键分层是:
内容权威层:帖子正文、媒体、审核状态、可见性
分发层:时间线收件箱、推 / 拉 / 混合扇出
排序层:候选召回、粗排、精排、去重、多样性
媒体层:转码、对象存储、CDN、预热、回源保护
安全层:审核、下架、召回、风控、可见性过滤五、方案推演:Feed 到底推还是拉
这是本案例最重要的决策。Feed 系统的核心问题是:首页到底提前算好,还是刷新时现算?
方案 A:纯拉模型,刷新时现查
用户刷新
└─▶ 查我关注的所有人
└─▶ 查他们最近发的内容
└─▶ 合并排序返回| 优点 | 代价 |
|---|---|
| 发文很轻,只写一份 | 用户关注多了之后,每次刷新读放大严重 |
| 关注 / 取消关注立即生效 | Feed QPS 高时,读取路径很难撑住 |
| MVP 简单 | 难以做到 P95 < 500ms |
方案 B:纯推模型,发文时写进粉丝收件箱
用户发文
└─▶ 查粉丝列表
└─▶ 把内容 ID 写进每个粉丝的 Feed 收件箱| 优点 | 代价 |
|---|---|
| 首页读取极快,直接读自己的收件箱 | 大 V 一发文就是百万 / 千万级写入 |
| 适合读远多于写 | 扇出队列、时间线存储压力大 |
| 可以把排序结果预先准备好一部分 | 关注关系变化后的修正更复杂 |
方案 C:推拉混合,普通人推,大 V 拉
普通创作者发文 → 推进粉丝收件箱
大 V 发文 → 只写自己的作者流
用户刷新首页 → 读收件箱 + 拉取关注大 V 的新内容 + 排序合并| 优点 | 代价 |
|---|---|
| 普通内容读取快 | Feed 读取服务要合并两路候选 |
| 避免大 V 扇出爆炸 | 大 V 内容会成为读时热点,需要缓存 |
| 能按粉丝数阈值分治 | 阈值、灰度和中腰部账号策略要持续调 |
FeedStream 成长期选择:推拉混合。普通人内容写扩散,大 V 内容读时拉取,两路在 Feed 读取服务里合并。
关键不在「推还是拉谁更高级」,而在于:
粉丝分布极端倾斜,所以必须分而治之。对 99% 便宜情况优化,把 1% 会爆炸的情况单独处理。
六、关键架构决策:用 ADR 把为什么留下来
ADR 是 Architecture Decision Record,可以理解成「架构决策记录」。Feed 系统最容易在后面被人问:「为什么时间线只存 ID?为什么大 V 不推?为什么视频要异步转码?为什么审核要影响分发?」这些都应该提前写下来。
ADR-01:Feed 采用推拉混合,而不是纯推或纯拉
- 背景:读远多于写,首页刷新必须快;但粉丝数极端倾斜,大 V 写扩散会爆炸。
- 选择:粉丝数低于阈值的创作者走写扩散,发文时写进粉丝收件箱;头部创作者只写作者流,由粉丝刷新时拉取并合并。
- 放弃:放弃所有账号同一种分发策略。
- 换来:普通用户首页读取快,大 V 发文不会打爆扇出队列。
- 风险:Feed 读取链路更复杂,需要合并、去重、排序和缓存大 V 内容。
- 复审条件:当中腰部账号频繁触发阈值边界,需要按活跃粉丝、内容热度和账号等级动态调整策略。
ADR-02:时间线收件箱只存内容 ID,正文和媒体读时批量回填
- 背景:一条热门内容可能进入百万用户收件箱,如果每份都存正文和媒体信息,空间会爆炸。
- 选择:时间线收件箱存
post_id、作者、时间、轻量排序分等引用信息;读取时批量回填正文、计数和媒体地址。 - 放弃:放弃在每个收件箱里复制完整内容。
- 换来:空间可控,热门内容只存一份权威正文,修改审核状态时也更容易统一生效。
- 风险:读取时多一次批量回填,热门内容正文存储会成为热点。
- 复审条件:当回填成为瓶颈时,给热门正文、互动计数和整屏 Feed 增加短缓存。
ADR-03:视频上传后异步转码,通过对象存储 + CDN 分发
- 背景:源视频巨大,用户网络差异大,源站直发会导致卡顿和带宽成本失控。
- 选择:上传源视频后立即返回处理中;后台转码为多档分片和 manifest;播放时走 CDN,播放器用 ABR 按网络选择分片清晰度。
- 放弃:放弃上传请求里同步转码,也放弃源站直接分发视频。
- 换来:上传体验不卡,播放更流畅,带宽成本由 CDN 命中率控制。
- 风险:上传后到可播放有延迟;转码队列和 CDN 回源都需要监控。
- 复审条件:当爆款内容经常回源打满,需要热点预热、回源合并和多 CDN 策略。
ADR-04:审核状态必须贯穿 Feed、搜索、推荐和 CDN
- 背景:内容平台会出现违法、有害、侵权或垃圾内容;分发系统越强,错误扩散越快。
- 选择:内容有统一审核状态;高风险内容先审后扩散;下架事件异步通知 Feed 收件箱、搜索索引、推荐候选、缓存和 CDN;读取时也要二次检查可见性。
- 放弃:放弃只在内容详情页隐藏违规内容的做法。
- 换来:违规内容能从主要分发面撤回,可见性规则在写入和读取两侧都生效。
- 风险:召回链路复杂,可能出现某个分发面漏撤。
- 复审条件:当平台开始承载 UGC 大规模内容时,审核召回要作为一级能力,并建立下架回归测试。
七、演进后的结构与数据流
下面只画 FeedStream 的核心结构。它不是一个帖子 CRUD,而是一套内容分发、排序、媒体分发和审核召回系统。
起始路径
用户发文 → posts 表
用户刷新 → 查关注列表 → 查 posts → 返回
视频播放 → 源站文件地址问题是:读放大、大 V 扇出、视频带宽、审核召回都没有结构化。
演进后的结构
用户发内容
│
▼
┌──────────────────────────────────────────────┐
│ 内容服务 │
│ 写正文 / 可见性 / 审核状态 / 媒体元数据 │
└──────┬───────────────────────┬───────────────┘
│ │
▼ ▼
┌──────────────┐ ┌──────────────────────┐
│ 内容存储 │ │ 媒体管线 │
│ post 权威副本 │ │ 上传 → 转码 → 对象存储 → CDN│
└──────┬───────┘ └──────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Feed 分发服务 │
│ 普通人写扩散 → 粉丝收件箱 │
│ 大 V 只写作者流 → 读时拉取 │
└──────┬───────────────────────┬───────────────┘
▼ ▼
┌──────────────┐ ┌──────────────────────┐
│ 时间线收件箱 │ │ 搜索 / 推荐索引 │
│ user -> post_id│ │ 候选召回 / 排序特征 │
└──────┬───────┘ └──────────┬───────────┘
▼ ▼
┌──────────────────────────────────────────────┐
│ Feed 读取服务 │
│ 读收件箱 → 拉大 V → 回填正文 → 过滤可见性 │
│ → 排序 / 去重 / 多样性 → 返回一屏 │
└──────────────────────────────────────────────┘这张图的核心变化不是「多了推荐」,而是结构变清楚了:
- 内容服务保存权威正文、媒体引用、审核状态和可见性。
- Feed 分发服务决定推还是拉,并异步写入时间线收件箱。
- 时间线收件箱只存内容 ID,服务于低延迟读取。
- Feed 读取服务合并普通内容、大 V 内容、推荐候选,再做回填、过滤、排序。
- 媒体管线把图片 / 视频从业务源站移到对象存储和 CDN。
- 审核召回贯穿内容、Feed、搜索、推荐、缓存和 CDN。
跟一次「普通创作者发文」走到底
1. 创作者发一条图文。
2. 内容服务写入 post 权威副本,状态为待分发或已审核。
3. Feed 分发服务查粉丝列表,发现粉丝数 800。
4. 这属于普通账号,异步把 post_id 写入 800 个粉丝的时间线收件箱。
5. 粉丝刷新首页时,直接从自己的收件箱取最新 post_id。
6. Feed 读取服务批量回填正文、互动计数和媒体 URL。
7. 排序服务打分,再做去重和多样性控制。
8. 用户看到这一屏内容。跟一次「大 V 发爆款视频」走到底
1. 大 V 上传一个短视频。
2. 上传服务把源视频存入对象存储,投递转码任务,立即返回处理中。
3. 转码服务异步生成 1080p / 720p / 480p 等分片和 manifest。
4. 内容审核通过后,内容服务标记视频可分发。
5. 因为这是大 V,Feed 分发服务不把 post_id 写入几百万粉丝收件箱,只写作者流。
6. 粉丝刷新 Feed 时,读取服务发现用户关注了该大 V,拉取作者流里的新视频。
7. 排序服务把它并入候选,如果分数足够高,进入用户首页。
8. 播放器请求 manifest 和视频分片,优先命中 CDN。
9. 如果预测会爆,系统提前预热头部分片到 CDN;未命中回源时做请求合并,避免源站惊群。这里的关键点:
- 大 V 内容不写扩散,避免发文时扇出爆炸。
- 读时拉取大 V 内容必须配热点缓存,否则会把读压力转移到作者流。
- 视频播放不走业务服务,而走对象存储 + CDN。
- 审核没过的内容不能进入 Feed、搜索和推荐候选。
八、坏了怎么办:故障场景与兜底
| 故障 | 直接后果 | 检测方式 | 架构兜底 |
|---|---|---|---|
| 纯拉模型读放大 | 首页刷新慢,数据库被关注聚合打满 | Feed P95、关注数分布、查询扇出数 | 普通用户改写扩散,预计算时间线收件箱 |
| 纯推模型遇到大 V | 一条内容触发百万级写入,队列堆积 | fanout queue lag、单 post 扇出数 | 大 V 走读时拉取,粉丝数阈值动态调整 |
| 时间线存完整正文 | 爆款内容被复制百万份,空间失控 | 时间线存储膨胀 | 收件箱只存 post_id,读时批量回填 |
| 大 V 作者流无缓存 | 粉丝刷新时把作者流读爆 | 作者流 QPS、热点 post 回填量 | 热点作者流和热门正文短缓存 |
| 扇出同步阻塞发文 | 用户发文卡住甚至失败 | 发文延迟、扇出耗时 | 发文只落权威副本,扇出异步队列 |
| CDN 未命中率飙升 | 视频首帧慢,源站带宽打满 | CDN hit ratio、origin egress | 热点预热、分层缓存、回源请求合并 |
| 转码队列堆积 | 视频上传后长时间不可播 | 转码队列长度、任务耗时 | 转码 worker 弹性扩容,冷内容少转码档 |
| 搜索索引滞后 | 新内容搜不到或旧违规内容还能搜到 | 索引新鲜度、旧状态命中 | 近实时增量索引,下架事件优先处理 |
| 推荐候选重复 / 低质 | 用户刷到重复内容或垃圾内容 | 重复率、负反馈率、停留时长 | 去重、多样性规则、质量过滤、反馈闭环 |
| 违规内容已扩散 | Feed、搜索、缓存里仍可见 | 下架回归、内容状态扫描 | 审核状态贯穿全链路,下架事件召回各索引和缓存 |
| 可见性只在前端判断 | 私密内容进入不该看的人的 Feed | 权限穿透测试、投诉 | 扇出和读取两侧都强制可见性过滤 |
| 互动计数长期错误 | 点赞数、评论数和真实日志不一致 | 计数对账、异常波动 | 计数可缓存,但以互动日志可重算 |
内容分发的成熟度,不是看首页能不能刷出内容,而是看热点、违规、回源、推荐退化这些放大效应有没有被结构兜住。
📌 拿模板验证这次推演
本案例不是重写社交 Feed 或视频流模板,而是把「内容社区」里最容易互相影响的几条链路放在一起推演。
| 可复用模板 / 章节 | 本案例复用什么 | 本案例重点补什么 |
|---|---|---|
| 社交信息流 | 推 / 拉 / 混合、时间线收件箱、大 V 扇出 | 用具体内容社区解释为什么普通人推、大 V 拉 |
| 视频流媒体 | 转码、多码率、对象存储、CDN、预热 | 把视频分发放进 Feed 热点内容场景 |
| 搜索引擎 | 倒排索引、召回 + 精排、索引新鲜度 | 说明站内搜索和推荐候选都需要索引与过滤 |
| 通知 / 推送系统 | 异步通知、去重、限频 | 互动提醒不能阻塞发文和 Feed 读取 |
| 规模化的力学 | 热点、扇出、缓存、读写放大 | 把大 V、爆款视频、CDN 回源都看成放大问题 |
| 安全与多租户架构 | 可见性、权限、隔离 | 把私密内容、拉黑、审核状态落到分发链路 |
读法建议:先读本章,再回看 社交信息流模板 和 视频流媒体模板。你会更容易看懂:Feed 和视频看似两个系统,但热点和分发成本会把它们绑在一起。
🎯 随堂检验
- A因为推模型读性能一定差
- B因为头部创作者粉丝太多,一条内容会触发百万级写扩散,需要大 V 走读时拉取
- C因为时间线不能预计算
- A因为正文不能存数据库
- B因为热门内容会被很多收件箱引用,复制完整正文会让空间和更新成本爆炸
- C因为 Feed 不需要正文
- A帖子表字段太少
- BCDN 命中、热点预热或回源保护没做好
- C用户关注关系太复杂
- A够,因为详情页没了就没人能看
- B不够,还要从时间线、搜索索引、推荐候选、缓存和 CDN 里召回
- C不用管,等缓存过期
本案例小结
- Feed 不是查 posts 表,而是个性化分发引擎。 每个人的首页都不同,读远多于写,所以读取路径是主战场。
- 推拉混合是大规模 Feed 的核心取舍。 普通人走写扩散换读取速度;大 V 走读时拉取避免扇出爆炸。
- 时间线存引用,正文读时回填。 这是空间、热点缓存和审核一致性的关键。
- 视频内容必须离开业务源站。 转码、多码率、对象存储、CDN、预热和回源保护决定播放体验和带宽成本。
- 推荐和搜索是召回 + 排序漏斗。 不要试图每次刷新实时重算全网,而是先召回候选,再对小集合打分。
- 审核召回是分发系统的一部分。 内容被系统扩散到哪里,下架就必须能撤到哪里。
承上启下:这一章把内容 Feed、搜索、推荐和视频 CDN 放进同一个内容社区。下一章如果继续写 AI Agent / 编码 Agent,压力会再次变化:重点会从内容分发,转向工具调用、权限、沙箱、记忆、上下文和人工审批。
相关链接
- 模板对照:社交信息流 · 视频流媒体 · 搜索引擎 · 通知 / 推送系统
- 方法论:02 · 架构师的思考框架 · 07 · 从 0 到 1 设计一个系统 · 08 · 架构决策记录与演进
- 硬骨头:13 · 规模化的力学 · 16 · 安全与多租户架构
💬 评论