原视频链接
https://www.youtube.com/watch?v=QmX2NPkJTKg
面试的时候最好问面试人他有什么对系统的功能有什么expectation。虽然你可能使用过这个APP,知道它的一些功能,但是时间限制可能不能允许你回答过多的功能,或者是在某个功能上耗时太久,而是应该询问面试人,回答他想知道的。
本视频中讨论的Instagram的一些功能如下:
1)Store/ Get Images 存储,获取图片
2)Like + Comment Image 点赞评论图片
3)Follow someone 关注某人
4)Publish a news feed 为用户提供信息流,比如用户打开会得到20个post的推荐
上面的这些功能,比如说1)Store/ Get Images在Tinder的视频 中已经提到过了,关于图片存储很重要的一点是要用成本相对底的file system来存储。
2)Like + Comment
针对的其实就是图片的post,对于comment是否允许revursive comment,即对comment再进行comment。Instagram允许的是单层的嵌套,也就是说可以用comment2对一个comment1进行评价,但对第二个comment2就不能再进行评价了。为了分析的时候更简单,可以直接不考虑recursive comment的情况。但你仍需要点赞一个comment。
视频中给出了如何根据不同的功能需求包括像某个post一共得到了多少个like,找到所有喜欢这个post的人,找到某个用户所有的post等等来调整E-R图,也就是数据表的结构,最终视频里得到的关于这些数据表的结构如下。
Likes table 的表头:
likesID, Active (post is deleted/active), ActivityID (likes to commentID/ postID), UserID, timestamp
Post table的表头:
UserID, PostID, text, ImgaeUrl, timestamp
Comment table 的表头:
CommentID, text, timestamp
Activity table 的表头 (专门为了能统计某个post有多少个likes设计的):
ActivityID, likes
3)Follow someone
这个功能主要包括两方面,一个是谁关注了User X,User X关注了谁,设计的数据表结构如下
Follow table 的表头:
FollowersID(关注着), FolloweesID (被关注的人), timestamp
4)Publish a news feed
用户的mobile app 连接到gateway server,在这个gateway server上装会有proxy和reverse proxy来使用户和gateway后面的service进行通信。在考虑信息流的功能时可以选择性地先忽略其他的功能,比如说profile service, image service等等。为了处理newsfeed,专门建立一个microservice叫做NewsFeed Service。这个service连接着和信息流相关的一些数据库,比如说上面提到的post数据库和follow的数据库。
一般组成newsfeed service 的会有多台机器,gate怎么知道要把请求转给那个机器呢?这个就要用到load balancer,consistent hashing之类的基本概念了。有的时候请求的数量很多,load balancer也忙不过来。一个办法是可以在gateway上每隔比如说10秒存一下loader balancer或者说是整个service哪个连着哪个,应该将什么样的请求送到哪个service上的snapshot。这样就不一定需要将所有的请求送给load balancer了,而是通过gateway就能知道将请求转给那个服务。
因为newsfeed一般来说是将你关注的和关注你的人最新的一定数量的post推送给你,所以每次如果用户刷新界面也就是发起请求,就需要向NewsFeed Service请求,如果每次NewsFeed Service都向post和follow的数据表做查询,那么一个问题就是万一用户请求很多,会对数据库以及service造成比较大的压力。一个解决的办法就是precompute用户的newsfeed。在每个用户关注了的人发了新的post之后,将这个新的post加到所有关注者的一个消息队列里面,一般来说这个队列长队有限,假设为20,当一个用户的队列长度达到20就不再往下加了,这样就可以缓解query执行的压力。那么这个属于每个用户队列的数据怎么存储呢?是用database还是用cache呢?还是更倾向于cache。一个原因是cache相对数据库实现的逻辑可能简单一些,cache是stateless的,就算server crash了,只需要重新计算一下就行。还有一个原因是cache的容量是有限的,如果我们是用LRU cache,那么只有经常使用的用户的newsfeed会在cache,而不常使用的用户也就不会在cache了。
还有一个问题是关于名人发post的。一般来说当一个用户的消息队列到了20,应该将这个newsfeed push也就是发送给用户,但是对于名人来说,他的/她的follower可能有上亿的人,将名人的post一下子推送给上亿的人是不现实的,服务器也肯定受不了。这时采取的措施时与其主动通知(push)newsfeed,而是等待用户主动来请求(pull)这个消息。更现实一些的做法是采用pull和push两种hybrid混合的方式,对于一些celeb,就用pull,对于普通用户就用push。