找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1657

积分

0

好友

215

主题
发表于 3 天前 | 查看: 16| 回复: 0
本帖最后由 云栈后端架构 于 2026-1-21 23:21 编辑

你刷推特时有没有好奇过,为什么总能刷到感兴趣的内容?

2023 年,马斯克把 Twitter(现在叫 X)的推荐算法代码开源了。这套服务 2 亿日活用户的系统,能在 800 毫秒内从海量推文里挑出 50 条推给你。今天我们就来拆解一下这套 71.2k Star 的架构,看看大厂的推荐系统到底是怎么玩的。


一、整体架构:四层搞定推荐

64060.png

Twitter 的推荐系统分了四层,每层干的事儿很明确:

数据层  

  • Tweetypie:管推文的增删改查,用的是 Twitter 自己搞的 KV 存储 Manhattan  
  • Unified User Actions:用 Kafka 收集用户的各种操作,点赞、转发、点击这些都在里面  
  • GraphJet:内存图数据库,记录用户和推文之间的关系

召回层(多路一起跑)  

  • Earlybird:基于 Lucene 改的搜索引擎,主要召回你关注的人发的推文  
  • UTEG:图遍历,找"你关注的人喜欢的内容"  
  • SimClusters:社区聚类,挖掘你的长期兴趣

排序层  

  • Heavy Ranker:深度神经网络,用 1 万多个特征预测你会不会点赞  
  • Navi:Rust 写的推理引擎,速度很快

混合层  

  • home-mixer:把前面召回的结果混在一起,去重、过滤、插广告

二、几个关键技术点

1. GraphJet:百亿条边的图怎么查得这么快?

推荐的核心逻辑是"找相似用户喜欢的东西"。Twitter 自己写了个 GraphJet,用分段存储加无锁写入:

// 核心数据结构
class SegmentedBipartiteGraph {
  // 用户到推文的边,按时间分段
  ConcurrentHashMap<UserId, TimeSegmentedEdgeList> userToTweets;

  // 插入边的时候只往后追加,不加锁
  void addEdge(UserId user, TweetId tweet, long timestamp) {
    edgeList.append(tweet, timestamp);  // CAS 操作
  }
}

单机能扛 100 万 QPS 写入,查询 P99 延迟 5 毫秒以内,1TB 内存能存 100 亿条边。


2. 多路召回:三条路一起找候选

Twitter 同时跑 3 种召回方式:

召回方式 延迟 覆盖面 适合什么场景
Earlybird(搜索) 10ms 广 关注的人发的新推文
UTEG(图遍历) 20ms 中等 社交关系扩散
SimClusters(聚类) 50ms 长期兴趣挖掘

三路并行跑,最后合并出 1500 条候选推文,再送去排序。


3. Heavy Ranker:1 万多个特征怎么用?

排序模型是整个系统的核心,Twitter 用的特征分三类:

用户特征  

  • 最近 7 天的点赞数、转发率  
  • 兴趣标签(145k 维的社区向量)  
  • 设备信息(网络质量、用的什么客户端)

推文特征  

  • 作者的声誉分(用 PageRank 算的)  
  • 内容质量(传播系数、评论深度)  
  • 安全分数(NSFW 检测、仇恨言论过滤)

交叉特征  

  • 用户和作者的亲密度(预测会不会互动)  
  • 话题匹配度

模型推理用的是 Navi 引擎,支持批量处理(一次 64 条)和 GPU 加速。


4. 实时性:发推到被看见只要 5 秒

推文发出去之后的流程:

用户发推 → Tweetypie 写库 
        → Kafka 广播 
        → Earlybird 更新索引(5 秒内)
        → GraphJet 更新图(1 秒内)
        → 别人刷新就能看到

核心思路:增量索引 + 内存图 + 异步更新,牺牲一点一致性换速度。


三、架构上的几点思考

1. 微服务拆分:按功能拆,不按技术拆

召回、排序、过滤都是独立服务。想加个新的召回源?直接加,不用动排序逻辑。

2. 流批结合:实时和离线各干各的

  • 实时流:Kafka Streams 处理用户行为,更新 GraphJet  
  • 离线批:Spark 每天跑一次 SimClusters 聚类  
  • 结果合并:线上服务同时查实时图和离线索引

3. 可观测性:每个请求都能追踪

// 分布式追踪
Trace.record("fetch_candidates_start")
val candidates = parallelFetch(
  earlybird, uteg, simclusters
)
Trace.record("fetch_candidates_end")
// 自动上报到 Zipkin

云栈社区的小伙伴们在做分布式系统时也发现,链路追踪真的很重要。Twitter 每个 RPC 都带 TraceId,出问题了马上能定位。


四、一些关键数据

指标 数值
每天请求量 300 亿+
P99 延迟 800 毫秒以内
候选召回数 1500 条
最终返回 50 条
模型特征数 1 万+
模型更新 每天一次

最后说两句

Twitter 把推荐算法开源,让我们能看到工业级推荐系统长什么样:分层架构、多路召回、流批结合、性能优化。

这套系统厉害的地方不是某个算法有多牛,而是工程化做得扎实:海量数据下怎么保证低延迟、怎么快速迭代新策略、怎么平衡精准和多样性。

后端架构师来说,这份代码值得好好研究。想看更多分布式系统的实战案例,可以去云栈社区逛逛,那里有不少开发者分享的经验,系统设计、分布式、高并发都有。

配套资源

项目地址github.com/twitter/the-algorithm
学习后端架构https://yunpan.plus/f/14
LeetCode 算法https://yunpan.plus/t/63


关注《云栈后端架构》,下期聊聊更多开源后端精选!

标签:#theAlgorithm #Github #推荐系统 #分布式架构 #微服务 #实时计算 #机器学习

来自圈子: 云栈后端架构



上一篇:小肩膀逆向JavaScript逆向高端1期 网易腾讯苏宁等主流网站验证码逆向实战解析
下一篇:高并发场景下,数据库与缓存双写:先操作谁才能保证数据一致性?
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-24 00:28 , Processed in 1.272653 second(s), 48 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表