菜单

Twitter 时间线与搜索

相关源文件

目的与范围

本文档提供了 Twitter 时间线和搜索系统架构的技术概述。它解释了实现一个支持推文发布、时间线查看和搜索功能的类似 Twitter 服务所需的核心组件、数据流、存储机制和扩展考虑。有关社交图谱实现细节,请参阅社交图谱

系统概览

Twitter 时间线和搜索系统处理数百万用户发布推文、查看时间线和搜索内容。该系统旨在高效处理高读写量,同时保持用户交互的低延迟。

来源:solutions/system_design/twitter/README.md96-97

用例和限制

核心用例

  1. 推文发布:用户发布推文
  2. 时间线查看:
    • 用户查看其个人时间线(自己的动态)
    • 用户查看主时间线(来自关注用户的动态)
  3. 推文搜索:用户通过关键词搜索推文
  4. 通知:服务将推文推送给关注者

关键限制

指标
活跃用户1亿
每日推文数5亿
每月推文数150亿
平均扇出每条推文10次投递
每日扇出投递数50亿
每月读取请求数2500亿
每月搜索数100亿

性能要求

  • 推文发布快速
  • 时间线查看迅速
  • 搜索高效
  • 系统读密集(为读取优化)
  • 推文写入期间写密集

来源:solutions/system_design/twitter/README.md37-62

数据特性

推文大小估算

组件大小
tweet_id8 字节
user_id32字节
文本140字节
媒体~10 KB(平均)
总计~10 KB

流量估算

  • 每月150 TB的新推文内容
  • 每秒10万次读取请求
  • 每秒6,000条推文
  • 每秒6万条推文通过扇出投递
  • 每秒4,000次搜索请求

来源:solutions/system_design/twitter/README.md66-90

核心组件

推文发布工作流

当用户发布推文时,系统会

  1. 将推文存储到用户时间线的 SQL 数据库中
  2. 将推文扇出到关注者的内存缓存主时间线中
  3. 为搜索建立推文索引
  4. 将所有媒体存储到对象存储中
  5. 向关注者发送通知

来源:solutions/system_design/twitter/README.md102-121

主时间线查看工作流

主时间线检索过程

  1. 从内存缓存获取时间线数据(O(1) 操作)
  2. 使用 multiget 有效获取推文详情
  3. 使用 multiget 有效获取用户详情
  4. 组合并返回完整时间线

来源:solutions/system_design/twitter/README.md157-164

用户时间线查看

用户时间线(个人时间线)与主时间线不同,因为它

  1. 只包含用户自己的推文
  2. 直接从 SQL 数据库检索
  3. 不需要扇出机制

来源:solutions/system_design/twitter/README.md192-197

搜索工作流

搜索过程

  1. 解析并分词搜索查询
    • 移除标记
    • 将文本拆分为术语
    • 修正拼写错误
    • 规范化大小写
    • 转换为布尔操作
  2. 查询搜索集群(基于 Lucene)
  3. 使用 scatter-gather 在服务器间查找匹配项
  4. 合并、排名并排序结果

来源:solutions/system_design/twitter/README.md199-220

数据存储设计

时间线的内存缓存模式

系统使用类似 Redis 的内存缓存,具有原生列表结构

           tweet n+2                   tweet n+1                   tweet n
| 8 bytes   8 bytes  1 byte | 8 bytes   8 bytes  1 byte | 8 bytes   8 bytes  1 byte |
| tweet_id  user_id  meta   | tweet_id  user_id  meta   | tweet_id  user_id  meta   |

这种格式可以高效地存储和检索时间线数据。

来源:solutions/system_design/twitter/README.md126-132

API设计

推文发布 API

POST /api/v1/tweet

请求

响应

来源:solutions/system_design/twitter/README.md136-152

主时间线 API

GET /api/v1/home_timeline?user_id=123

响应

来源:solutions/system_design/twitter/README.md166-188

搜索 API

GET /api/v1/search?query=hello+world

返回与主时间线类似的响应,但包含与搜索查询匹配的推文。

来源:solutions/system_design/twitter/README.md216-220

扩展性考量

系统瓶颈与解决方案

来源:solutions/system_design/twitter/README.md226-227

主要瓶颈

  1. 扇出服务:拥有数百万关注者的用户可能造成扇出瓶颈

    • 解决方案:跳过对高关注用户的扇出
    • 替代方案:搜索高关注用户的推文,并在服务时与主时间线合并
  2. 内存缓存优化:

    • 在每个主时间线中只保留最近的推文(几百条)
    • 只在缓存中存储活跃用户的时间线
    • 按需重建非活跃用户的时间线
  3. 数据库扩展:

    • SQL 读取副本可能不足以处理缓存未命中
    • 高写入量将使单个主从设置不堪重负
    • 解决方案:联邦、分片、非规范化、SQL 调优
    • 考虑将部分数据迁移到 NoSQL 数据库

来源:solutions/system_design/twitter/README.md251-277

进一步优化策略

时间线数据管理

  • 在内存缓存中,每个用户只存储最新(几百条)的推文
  • 只在内存缓存中保留活跃用户的时间线
  • 需要时从数据库重建非活跃用户的时间线
  • 推文信息服务中只存储一个月的推文
  • 用户信息服务中只保留活跃用户

搜索优化

  • 搜索集群可能需要将推文保留在内存中以实现低延迟
  • 考虑使用 Elasticsearch 或 Lucene 等专业搜索技术

数据库优化

  • 使用联邦(Federation)按功能拆分数据库
  • 实施分片(Sharding)以在多个数据库之间分发数据
  • 在适当情况下应用反规范化
  • 优化 SQL 查询以提高性能
  • 考虑为特定组件使用 NoSQL 数据库

来源:solutions/system_design/twitter/README.md257-277

结论

Twitter 时间线和搜索系统展示了分布式系统设计的关键原则

  1. 读写路径分离
  2. 对高读取操作有效利用缓存
  3. 针对不同功能的专业服务
  4. 可处理数百万用户的可扩展架构
  5. 针对不同使用模式的优化策略

通过理解这些组件及其相互作用,工程师可以构建类似的高效可扩展的社交媒体平台。