设计一个类似Twitter的时间线或者Facebook的feed功能。原文链接
1.描述使用场景和约束
使用场景:
- 用户发送推文
- 用户浏览自己推文的列表
- 用户浏览自己的时间线
- 用户搜索关键词
约束和假设:
- 流量不平均
- 发推文操作应该尽量快
- 亿级别用户
- 5亿推文每天
- 每条推文平均被10个人关注
- 推文分发动作平均每天50亿次(10*5亿)
- 2500亿读请求每月
- 100亿搜索请求每月
- 时间线应该尽量加载快速
- 时间线读多写少
- 搜索应该尽量快速
- 搜索读多写少
容量估算:
单条推文大小:
-
twitter_id
8字节 -
user_id
32字节 -
text
140字节 -
media
10k字节
总计10kb - 每月150TB的推文
- 每秒10万次读请求
- 每秒发送6000条推文
- 每秒分发60000条推文
- 每秒4000次搜索
2.创建系统设计
系统设计图3.设计关键组件
使用场景:用户发送推文
我们可以存储用户推文,以填充用户自己的推文列表。
分发用户推文有60k的TPS。所以应该选择一个支持快速写入的NOSQL或者cache。
照片,视频等文件的存储还是放在文件服务器或者三方的文件服务。
- 客户端发送请求到反向代理
- 反向代理转发请求给服务器
- 存储用户推文信息到用户自己的推文列表中
- 推文到推文分发服务中:
- 查找用户的粉丝,这个关系适合采用图数据库存储
- 将推文中的图片、视频等存储到文件服务中
- 将推文存储到用户粉丝的时间线中
- 将推文发送到搜索引擎服务
- 使用通知服务来通知粉丝新的推文
如果选用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 |
使用场景:用户的推文列表
- 客户端发送请求到反向代理
- 反向代理转发请求到服务器
- 读请求到时间线服务
- 获取cache中的twitter_id和user_id
- 根据twitter_id获取相关文件
- 获取user_id相关信息
使用场景:用户搜索推文
- 客户端发送请求到反向代理
- 反向代理转发请求到服务器
- 搜索服务接受请求
- 获取搜索信息,确定应该搜索什么内容
- 清除标记
- 搜索内容分词并校正错别字
- 将搜索转换成标准语法
- 从搜索服务(比如Lucene)中各个服务器获取数据
- 将数据合并、排序,返回结果
- 获取搜索信息,确定应该搜索什么内容
4.完善设计
最终设计图推文分发服务是一个可能存储的瓶颈,一般可以将其优化为推、拉两种模式(https://blog.csdn.net/hhq163/article/details/40823273)。
其他的优化点还包括冷热数据的分割,活跃用户数据转移到cache等等。
网友评论