难点:
push model的异步执行的画图
需要Clarify什么?
多少用户,直接用Facebook体量的用户吗。
好像也想不起来要clarify什么了,就在列应用场景的时候直接用吧。
场景
用户登录后,系统会给用户显示最有什么什么新鲜事,最近的up to 20条新鲜事
怎么知道一条feed用户有没有读过
用户发帖子
API
public List<Feed> GetFeed(userId, numberToReturn)
public boolean postFeed(userId, sessionKey, content
Working solution
用户通过load balancer登录到一台服务器上。 服务器查询用户follow的好友的列表, 服务器去查找这些好友最近都发了什么新的post. 服务器把这些帖子归并一下,发送前20个给用户。
Data Model / Storage
User Table
UserID, userName, password, createdAt, lastLogin
Friendship Table
FromUserId, ToUserId, Since
Post Table
PostId, authorId, createdAt, content
Detailed Working Solution
服务器去friendship table找用户所有的朋友。(friendship table要按FromUserId 建clustering index). 服务器去post Table, 找这些朋友的post。(PostTable 可以用columnar table, authorId做为row key, createdAt作为column key, 进行range query, 然后这样就不好找一个postId的内容了如果不知道它的作者是谁, 可以按postId建index也行, 再讨论, 也可以把postId用timestamp + userId组成, 这样从postId就知道谁是作者了)找到了所有朋友的新post之后,排序。然后返还。
bottleneck
每次可能要花一段时间查,太慢了。
Scale
把user Table按user Id sharding, friendship table也按userId sharding, postTable按authorId做为row key
Index
PostTable 如果用SQL的话,就要对authorId + createdAt 建2ndary index。
FriendShip Table, 用FromUserId做为ordering filed, 就不用再建index
难点
如何知道一个post是否读过
有几种解决办法: 如果有new feed table, 直接加一栏read or not看一下就好了
如果有没有news feedtable, 只接用user上次pull的时候 + 本地客户端的数据库就好了。
加速
push model
这种每次上线再查询的做法有点慢。可以在每个用户发帖之后把它发的帖子推送给它的朋友,执行一个异步任务。 具体做法是用户发帖后,写到数据库里就确认完成,同时发一个消息给messageQueue,当messageQueue读到这条消息的时候,他会去找这个朋户的朋友,同时把这个消息的id写到用户的newfeed table里面。这样用户登录之后就直接从自已的news feed table里面把前 20条取出来就好了。
然后push model的问题是对于明星用户,要fanout的用户太多,太慢。
这时可以把pull model 和push model结合在一起用。
推送服务
对于普通用户,当它发了帖子,就直接推送给它的朋友,(需要记一下每个人的在线状态)
对于明星用户,它的follower登录之后就会subscribe明星的channel, 明星每次发帖子,明星的服务器就会看一下谁follow了并且在线, 只把消息发给在线在follower.
网友评论