系统设计- 怎么简单设计一个twitter?
那么我们nail down 三个最为重要的社交网络的features:
-
tweeting: 指的就是user可以发出自己的tweets并且follower可以看的到
-
timeline:
主要分为两种
usertime: take all your tweets then rank it
hometime: line tweets from users you follow take all then rank with cron expression -
following
user可以选择follow什么人
一个比较简单的 solution类似于我们在解决算法的问题时的brutal force solution:
使用一个relational database:
两个table来做query
user table : 3 columes ID name followers
tweets table: 3 columes ID content user
这就是一个最简单的one to many mapping for tweets
So when displaying home timeline it would cause scan through the whole big tweets table and cause the refreshing really slow.
很明显,这并不是一个很好的解法
那么我们继续思考,找出twitter这个系统中的最需要关注的内容:
Focus: make home timeline really fast. we are caring more about reliability than consistency in extremely small time space. which leads to eventual consistency is what we care about.
那么我们最关注的就是eventual consistency 还有就是系统总体的稳定性。
这个时候为了解决query的速度太慢的问题,我们自然地想到in memory database redis。
考虑到cost的问题
Redis only store active users for last few days or weeks
根据上面的考虑我们提出一个proposal:
image我们看一下整个tweets的流程:
- 阿曼达push了一条tweets
- 她的notification send到了load balancer
- load balancer将她的这条tweets通过一个database找到她的follower,并且update了相关follower的pre-calculated的in memory home timeline。
- 当bob refresh他的timeline的时候正好能够看到in memory的所有结果,非常的快
我们再从Bob的角度来看一下他refresh的过程:
image- Bob refresh home page
- 浏览器send http request to load balancer
- 直接从redis里面拿到之前pre-calculated好的bob following的状态,整个过程只需要一秒不到
可能遇到一个大问题:
如果这个时候有大V发文了怎么办,比如说特朗普。
一个简答的解决方法就是,我们不去提前更新所有粉丝的timeline,而是把一个特定数量级别的大v的状态在发布之后插入到他的follower的home timeline里面,这样的话不需要再redis里面备份三次,并且占用很多的in memory 内存。
最后我们回顾一下思考的过程和关注的重点:
tradeoffs:
fast reads : from redis
evental consistency
内存的花费大:sacrifice memory for fast response. Mainly consist of characters so its alright,文字信息存量不是很大,并且我们只存活跃用户的tweets
如何找到三个对应的redis cluster:Hash map look up for bob find the 3 redis machine.