设计 facebook feed 和 设计 facebook search是相同的问题
定义问题的需求和范围,询问问题去声明用例和约束,讨论假设
ps: 没有一个面试官会展示详细的问题,我们需要定义一些用例和约束
用例:
我们定义问题的范围,只是去处理以下Use Cases
问题域外
约束和假设:
状态假设
每条推文的平均传播量为10次
50 亿个tweet被传播一天
1500亿tweet被传播每个月
计算使用量:
和面试官说明你是否需要进行粗略使用量估算
转换规则:
250 万秒每个月
1 request/s = 250 万 request/ 月
40 request/s = 1000 万 request/月
400 request/s = 10 亿 request/月
描绘所有重要组件的 high level design
我们可以存储用户自己的tweet来填充这个用户时间线,我们应该讨论这个用户Case的取舍在SQL和NoSQL之间
传播tweets和构建这个home timeline 是一个笑话,传播tweets给所有的follower(6w tweets delivered on fanout per second) 将 过载一个传统的关系型数据库。我们或许想选择一个数据存储(速度快的写,比如No SQL数据库和内存),从内存中序列化的读1MB数据需要250微秒,当从SSD需要4X,从硬盘中读需要 80X.
我们可以存储媒体文件比如图片和视频在 Object Store
使用一个 Queue 去异步发送 notifications
向你的面试官说明多少代码你期望去写
如果Cache是使用Redis,我们可以使用原生的Redis List伴随着如下结构:
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 |
新的 tweet 将会被放进 Memory Cache, 将填充这个User 的 home timeline
我们将使用一个 public REST API:
$ curl -X POST --data '{ "user_id": "123", "auth_token": "ABC123", \
"status": "hello world!", "media_ids": "ABC987" }' \
https://twitter.com/api/v1/tweet
Response:
{
"created_at": "Wed Sep 05 00:37:15 +0000 2012",
"status": "hello world!",
"tweet_id": "987",
"user_id": "123",
...
}
内部的服务通信,我们可以使用 Remote Procedure Calls
REST API:
curl https://twitter.com/api/v1/home_timeline?user_id=123
Response:
{
"user_id": "456",
"tweet_id": "123",
"status": "foo"
},
{
"user_id": "789",
"tweet_id": "456",
"status": "bar"
},
{
"user_id": "789",
"tweet_id": "579",
"status": "baz"
}
这个 Rest API应该是和 home timeline相同的,除了所有的 tweets应该才子与 User,而不是User 的 follower
Rest API:
$ curl https://twitter.com/api/v1/search?query=hello+world
开始思考这四件事:
讨论初始化的Design,定位瓶颈的过程是非常重要的。比如:添加 Load Balancer到多Web Server会产生什么问题? CDN 呢?数据库主从架构呢?什么是最优解?
我么将介绍一些组件来完成这个Design并且去定位扩展性问题,内部的load balancer不被展示去减少
杂乱。
分析设计发现,Fanout Service是潜在的瓶颈,Twitter 用户的数百万 follower会花费数分钟来完成广播流程。这可能导致推文 @replies 出现竞争状况,我们可以通过在服务时重新排序堆文件来缓解这种情况。
我们还可以避免将来自高关注度用户的推文散开,代替,我们可以搜索去找到高关注度用户的 tweet,合并搜索结果伴随着用户的 home timeline结果。然后重新排序 tweet 在服务器时间。
额外的优化包括:
我们也想要定位在数据库中的瓶颈。
尽管 Memory Cache 可以减少数据库的负载,仅仅SQL读取副本不足以处理缓存缺失。我们可能需要采用额外的SQL扩展模式。
大量的写入将压倒单个SQL写主从,这也表明需要额外的扩展技术。
We should also consider moving some data to a NoSQL Database.
Additional topics to dive into, depending on the problem scope and time remaining.
Refer to the security section.
See Latency numbers every programmer should know.