当前位置:首页 > 每日看点

微博和知乎中的 feed 流是如何实现的?

卡卷网1年前 (2025-05-03)每日看点291

Twitter 架构演进

Twitter 的两个主要业务是:

  1. 发推文: 用户可以向其粉丝发布新消息(平均 4.6k 请求 / 秒,峰值超过 12k 请求 / 秒)。(2012年[2])
  2. 看推文: 用户可以查阅他们关注的人发布的推文(300k 请求 / 秒)。

1. 读扩散

读扩散处理每秒 12K 次发推文还是很简单的, Twitter 的挑战主要是 300K 查看推文请求.

看推文时,首先查找关注的所有人,查询这些被关注用户发布的推文, 并按时间顺序合并

SQL 伪代码:

SELECT * FROM posts WHERE user_id IN (SELECT user_id FROM follows WHERE follower_id = :user_id) ORDER BY created_at DESC

微博和知乎中的 feed 流是如何实现的?  第1张

[1]

2. 写扩散

  • 发推文时: 查找所有粉丝, 写入所有粉丝的 timeline 中
  • 看推文时: 读取 timeline

微博和知乎中的 feed 流是如何实现的?  第2张

3. 演进

  • 推特第一版使用读扩散, 系统很难承受 300K看推文的负载
  • 推特第二版使用写扩散, 一条推文平均推送 75 个粉丝, 所以 timeline 的写压力大约 345K, 读压力是 300K

写扩散看起来很美好, 但是隐患是一些用户有超过 3000 万的粉丝, 如果该用户发推文, 那么写入 3000 万用户的 timeline (而 Twitter 尝试在 5 秒内向粉丝发送推文)

最终: Twitter 已经稳健地实现了写扩散,逐步转向了读写混合模式

Twitter 在技术分享[2]中没有透露实现细节, 下面是我的架构设计

读写混合模式 架构设计

1. 名词解释

  • 粉丝收件箱/timeline: 关注页的信息流(微博、朋友圈).
  • 发件箱: 作者发布的内容
  • 写扩散: 作者发布消息后, 立即推送给粉丝的 "粉丝收件箱"
  • 读扩散: 作者发布消息后, 不推送给粉丝. 粉丝获取信息流时, 遍历关注列表中的作者, 拉取 "发件箱" 中的新内容.
  • 大V: 粉丝数超过 10 万的用户定义为大V, 大V 不可降级为小V.

2. 作者发布内容时

  • 小V : 采用写扩散模式, 写入 所有粉丝 的 "粉丝收件箱"
  • 大V : 仅写入 活跃粉丝 的 "粉丝收件箱", 离线粉丝通过读扩散获取

流程图:

微博和知乎中的 feed 流是如何实现的?  第3张

2.1. 什么是 "活跃粉丝"?

  • 粉丝登录时, 查询自己关注的所有大 V, 注册到当天的 "活跃粉丝" 中
  • 大 V 发内容时, 查今天的 "活跃粉丝" 和昨天的 "活跃粉丝",合并 2 个结果作为大 V 活跃粉丝 (1-2天 内登录的都是活跃粉丝)

<---- 昨日 ---->|<---- 今日 ----> [ 活跃粉丝 ][ 活跃粉丝 ] <-------------------------> 合并后的大V活跃粉丝 (1-2天内登录)

好处:

  • 大 V 查询对 关系表 的压力降低到 0 QPS
  • 减少大 V 写扩散对 "粉丝收件箱" 的压力

1-2 天登录的用户有点多, 如何减少活跃粉丝量?

缩短时间, 比如 10-20 分钟存在心跳的用户

3. 粉丝登录时

  • 查询用户关注的大V列表
  • 查询"发件箱"
  • 写入新内容到"粉丝收件箱"
  • 计算红点

流程图:

微博和知乎中的 feed 流是如何实现的?  第4张

4. 粉丝读取内容时

  • 查询 "粉丝收件箱"

"粉丝收件箱" 数据结构 (Redis ZSet):

# Score: 内容更新时间戳 # Value: 内容ID content_id_1 -> 1704240000 (对应 2024-01-03 00:00:00) content_id_2 -> 1704153600 (对应 2024-01-02 00:00:00) ...

5. 粉丝关注作者时

主线逻辑:

  • 查询作者最近发布内容(大V有缓存), 写入 "粉丝收件箱" (100ms)

分支逻辑:

  • 判断作者是否大V: (1ms)
  • 如果是:
    • 修改粉丝 followBigV 表 (1ms)

  • 如果不是, 且粉丝数不超 10 万:
    • 结束
  • 如果不是, 且粉丝数超 10 万:
    • 该作者标记为大V (1ms)
    • 异步:
      • 查询作者所有粉丝 (10s)
      • 为每个粉丝 followBigV (关注的大V) 添加此新晋大V (100S)

微博和知乎中的 feed 流是如何实现的?  第5张

6. 粉丝取消关注时

主线逻辑:

  • 从粉丝收件箱删除作者内容 (大V 有缓存) (100ms)
  • 如果是大 V, 从粉丝关注的大V列表删除作者

微博和知乎中的 feed 流是如何实现的?  第6张

详细设计

1. 大V列表如何存储?

  • 每个用户关注的大V列表, 因为数量有限, 存储在单个 key 中
  • 预估: 用户关注 100 个大V, 该 key 约为 1KB

followBigV 数据结构:

{ // 用户关注的大 V ID 列表 "bigVIds": ["10001", "10002", "10003", "10004", "10005"], // 上次登录刷新时间 "lastRefreshTime": "2024-01-01 00:00:00" }

2. 如何降低"粉丝收件箱"的存储成本?

  • 采用冷热数据分离.

冷备:

  • 将 1 个月 未活跃用户的 "粉丝收件箱" 数据从 Redis 迁移到 DB, 标记冷备.
  • 存在冷备标记 cold:<UserID> -> '1' 表示用户数据被冷备

用户再次登录加载冷备:

  • 检查冷备标记.
  • 若标记存在 则从 DB 读取数据重新加载到 Redis

用户登录流程图:

微博和知乎中的 feed 流是如何实现的?  第7张

3. "粉丝收件箱"的写性能优化

  • 采用批量写入 (Pipeline) 能带来 1-2 个数量级的提升 (Redis 单机可达 200-300 万 QPS)

参考

[1] DDIA: ddia.vonng.com/#

[2] Twitter Timelines at Scale infoq.com/presentations

扫描二维码推送至手机访问。

版权声明:本文由卡卷网发布,如需转载请注明出处。

本文链接:https://www.kajuan.net/ttnews/2025/05/12838.html

分享给朋友:

相关文章

那些极速版软件其存在目的是什么?

那些极速版软件其存在目的是什么?

我看了很多回答,其实都没有回答道点子上。 你知道极速版APP为什么叫极速版吗? 是他看视频更快吗?显然不是。 只是它的安装包体积更小,下载安装速度更快而已,所以叫极速版app。当然啦,现在极速版APP和原声版APP,安装包已经没有区别了,这…

为什么微服务一定要有网关?

为什么微服务一定要有网关?

网关 一句话总结,网关的作用是上浮公共逻辑,下沉差异逻辑。公共逻辑就是所有接口都需要做的事,比如权限校验,限流算法等,这样业务就只需要关心业务逻辑即可。下面是一个对比图: 当然除了一些公共逻辑外, 路由也是网关的核心功能,它可以进行流量…

想要在双 11 换一台全面无短板的新手机,有没有「闭眼买」的机型推荐?

想要在双 11 换一台全面无短板的新手机,有没有「闭眼买」的机型推荐?

最近一个月各大手机厂商的旗舰机扎堆发布,不知道大家看爽了没? 这一代的性能续航大提升,最低 3599 元就能买到,同时老款也有不小的降幅,今年双 11 算是相当适合换手机的节点了! 这次,小黑就给大家推荐双 11 期间值得购买的手机...…

为什么说不懂电脑的不要碰AMD?

作为一个资深垃圾佬,说缺点前,先说优点吧AMD CPU(后续简称AU)的优点:处理器对比Intel,三级缓存更大,最明显的感知就是,网游帧数更高(5900X,7900X之类高端型号都是双CCX共享大缓存,反而不如次一点的CPU帧数更高);相…

MacOS真的比Windows流畅吗?

我现在公司配的机器,配置是绝对的大古董了 惠普z230sff薄塔 cpu只是个4770,没错不是4790k,4770全核睿频只有3.8g 显卡更是古董,k600,已经结束驱动更新支持了,显存仅1g,跑分跑不过13代uhd核显 内存是加到16…

在 Kubernetes 中,Service 的实现原理是什么,它是如何实现服务发现的?

行,问的这个问题挺有意思,Kubernetes 里 Service 是怎么实现的,服务发现是怎么回事,咱就直说了。这事儿看起来挺玄乎,但掰开揉碎了讲,也就那么回事。你得把这事儿想得简单点,别一上来就被啥术语吓住了——其实全是些搬砖的套路。…

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。