当前位置:首页 > 每日看点 > 正文内容

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

卡卷网4个月前 (05-03)每日看点101

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

分享给朋友:

相关文章

创业容易吗?

创业容易吗?创建企业不一定是困难或令人生畏的。它可以从一个简单但有力的想法开始,比如小强意识到,如果洗手液能杀死真菌,尤其是拳击台上的真菌,就会更加有用。创业确实需要奉献精神、努力工作和仔细规划——这是没有办法的。虽然这本身可能并不容易,但...

有了Istio,开发还需要微服务架构吗?

有了Istio,开发还需要微服务架构吗?

Istio 是一个开源的服务网格(Service Mesh),通过它可以实现对服务间通信的管理和监控。对于那些本身没有设计为具备安全功能的传统应用程序,Istio 可以提供一个“透明”的安全保护层,而不需要对应用本身进行任何代码修改。 I...

内存和硬盘的单位都是G,两者的功能是什么?谁能用简单通俗的方式来解读一下?

内存和硬盘的单位都是G,两者的功能是什么?谁能用简单通俗的方式来解读一下?

要弄清楚这个问题,首先要弄清楚什么是内存,什么是硬盘,在计算机的组成结构中有一个很重要的部分是存储器。它是用来存储程序和数据的部件。对于计算机来说,有了存储器,才有记忆功能,,才能保证正常工作。存储器的种类很多。按其用途可分为主存储器与辅助...

4499 元起的荣耀Magic7 系列实际使用体验怎么样,值得入手吗?

全是软文。。。。。。不过我买了,标准版。为什么买荣耀:屏幕看着舒服,玩游戏选择大屏,超声波指纹解锁。其它,系统、续航、充电、拍照,不是最强,但均衡下来短板都不是很短。其它米OV,IQ、一加,都看了,预算有限,米OV的小屏不感兴趣,OPPO硬...

为什么大家都说手机性能永远超不过PC?

最新的天玑9400牛逼吧,堪称PC级CPU,测试成绩16W功耗能跑9500分,1.8W能跑3000分,GPU也差不多是这个情况。手机电池一般是4000-5000毫安时,电压3.7V。也就是说,手机正常满载5W功耗下,这个电池能支持运行4个小...

中国芯片产量达1399亿颗,这意味着什么?

美国并不是没有明白人,只是特朗普不懂芯片产业的情况,冒冒失失在ZZ正确下,开启了对中国芯片的掐脖子,结果没掐死,反而让人练出了铁肺。芯片是所有科技产业的上游,美国原本在上游呆得很舒服,靠英伟达、AMD、德州仪器、高通等这些几十年霸主地位的公...

发表评论

访客

看不清,换一张

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