Feed 流系统怎么设计?推模式、拉模式和推拉结合怎么选?
以下对话为教学模拟,不是真实面经。
🧑💻 面试官:Feed 流用推模式还是拉模式?
🙋♂️ 我:推模式读得快,拉模式写得快。
🧑💻 面试官:一个账号有几千万粉丝,发布一次要写多少份?大部分粉丝并不活跃,也全部提前生成吗?
不只比较一次读写快慢,还要比较谁承担扩散,以及哪些结果值得提前准备。
面试速答(60 秒版)
Feed 推模式通常在发布时,把内容引用分发到粉丝的候选收件箱,让读取更直接,但发布扩散成本随着粉丝数量增长。
拉模式则在用户读取时,从关注对象的内容中收集候选。发布成本较低,但关注数量和排序工作会影响读取延迟。
推拉结合可以给普通、活跃关系提前生成候选,把大粉丝账号等高扩散内容留到读取时合并。不过,具体分界需要根据访问和成本评估。
Feed 还需要统一排序、分页、去重、删除与权限处理。候选收件箱不是最终可见答案,读的时候仍要验证内容状态,不能只解决扩散就认为系统完整。

知识点详解:发布时做工作,还是读取时做工作
先区分内容本身和用户的候选列表
咱们假设做一个按关注关系展示内容的 Feed。每条内容存一份主体,用户候选列表里主要保存内容 ID 和必要排序信息,而不是为每个粉丝复制整篇正文。
候选列表是一种读取加速结构。实际展示还需要查内容状态、权限和排序结果。
System Design Primer 的 Twitter 设计练习可作为问题拆解参考。它是公开的设计练习,不是当前 X 平台完整架构;下面同样是教学方案。
推模式,把扩散成本放在发布时
用户 A 发布一条内容,系统把它的引用写入相应粉丝候选列表。粉丝读取时,不必重新扫描所有关注者的历史内容。
优势是读路径相对集中。代价是一次发布可能产生很多写操作,还需要处理重复任务、部分失败和分发延迟。
如果一个账号有大量粉丝,却只有少部分近期活跃,提前为每个人生成候选可能浪费资源。推送完成之前,不同用户看到内容的时间也可能不同。
因此,推模式不是“发布一次写一条”,也不保证所有粉丝同时看到。

拉模式,把候选收集放在读取时
用户打开 Feed,系统根据关注列表,从相关作者的内容中收集候选,再合并排序。
发布不必为每个粉丝立即分发,但读取工作会受关注数、候选数量和查询成本影响。大关注列表可能带来大量并行查询与尾延迟。
可以通过缓存、预计算和限制候选窗口降低成本。但一旦引入这些机制,系统就不再是最纯粹的“每次从零拉取”。讨论时最好说明实际做了哪部分。
推拉结合,合并的是候选来源
一种教学方案是:普通作者内容进入用户候选收件箱;高粉丝作者内容在读取时额外获取;两边合并、去重后统一排序。
不能简单把两份已经分页的列表拼起来。它们的排序规则、时间范围和游标需要兼容,否则容易重复或漏掉内容。
分界也不必只看粉丝总数。发布频率、活跃粉丝、读取频率和资源预算,都影响扩散是否划算。阈值应从真实负载中确定,不编一个通用数字。
内容删除和权限变化,要回到真实状态
内容已经分发以后被删除,候选列表可能还保留它的 ID。作者从公开改为受限,也可能改变读者权限。
因此,在展示时仍然需要过滤不可见内容,并通过相应流程清理候选。只靠“发布时判断过权限”不足以覆盖后续变化。
如果产品支持复杂排序,还要区分候选召回与最终排名。收件箱里的先后顺序,不一定就是用户最终看到的顺序。
分页不能只拿一个时间戳当万能游标
相同时间可能有多条内容,排序结果也可能变化。游标应能够表达稳定的排序位置,例如结合时间与唯一 ID;算法推荐流又可能需要版本或快照等安排。
这里没有一种适合所有 Feed 的游标方案。关键是定义后续读取如何避免重复、漏项和排序跳动,并接受产品允许的变化范围。
验证时可以模拟发布积压、重复分发、大粉丝作者、关注变化、删除和翻页。记录写放大、读取尾延迟、候选覆盖和资源成本,再决定采用多少推、多少拉。

面试官继续追问
推模式是不是比拉模式一致性更强?
不一定。分发可能延迟或部分失败,拉模式也可能读到缓存。必须说明数据路径与一致性目标。
大粉丝作者一定只能拉吗?
不一定。可以按活跃关系推、分批推或采用其他预计算。判断依据是成本与读取目标,不是固定标签。
Feed 里面为什么还要去重?
分发重试、多个候选来源和翻页都可能带来重复。稳定内容 ID 与明确游标规则仍然需要。
面试速记卡
- 推模式:发布时分发候选,读取直接,写扩散增加。
- 拉模式:读取时收集候选,发布简单,读路径变重。
- 推拉结合:不同来源合并去重,再统一排序。
- 可见边界:候选 ID 不代表内容仍有效或有权限。
- 选型依据:访问分布、写放大、尾延迟与分页正确性。
公司面试真题
这道题暂未收录可核验的公司真题来源。你可以先阅读本文解析,或浏览已收录的公司面试真题。
浏览公司面试真题 →