持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情
Solution A:拉模型(Pull Model)
主动型的模型。当你打开微博,查看自己的新鲜事订阅(其它你所关注的用户发的微博)时,系统会先去取出你所关注的的用户列表,再分别把这些你所关注的的用户的时间线上的微博取出来,最终按时间执行归并排序,返回给你所需要的新鲜事订阅。
当你需要获取新鲜事列表时,系统是去你所关注(Follow)用户的时间线列表,拉取你所需要的新鲜事。
- 用户打开新鲜事列表,获取所有关注的其他用户
- 获取这些用户时间轴中的前 100 条新鲜事
- 将【2】中取到的新鲜事,按时间排序,合并成为一个 100 条的新鲜事列表(K 路归并)
复杂度
假设该用户关注了 N 个用户:
100*N次DB读 + N路归并 = 100*N次DB访问 + 100log(N)内存处理
一般内存处理的时间<< DB 访问时间,因此可忽略不计。【拉模型】下,若用户发布了一条新鲜事,会发生啥?
该模型下,用户发表一条新鲜事,只需在用户自己的时间轴中插入一条数据,即执行一次DB写。
伪代码
// 获取新鲜事列表
public List<Feed> getNewsFeed(request) {
List<Feed> followings = db.readFollowings(request.user);
List<Feed> newsFeedList = [];
followings.forEach(f -> {
List<Feed> feeds = db.getTimeLine(f.to_user, 100);
newsFeedList.push(feeds);
});
return K_sort(newsFeedList);
}
// 发布新鲜事
public String postNews(request, content) {
db.insertNews(request.user, content);
return "success";
}
缺陷
当用户想拉取自己订阅的新鲜事list,需执行较多DB操作,用户需等待这一系列 DB 操作执行完成,系统才会将新鲜事list返给客户端显示,对于用户就得等待较长时间。
Solution B:推模型(Push Model)
系统为每一个用户都维护了一个新鲜事列表,当某用户发了一条新鲜事,所有关注该用户的新鲜事列表里都会被插入一条该新鲜事;当一个用户查看自己订阅的新鲜事列表时,仅需从自己的列表中取出前 K 条新鲜事即可。
算法描述
- 为每个用户建立一个存储他的新鲜事的列表,列表中只包含他所关注的用户发布的新鲜事
- 当某个用户发布新鲜事后,会将该新鲜事逐个推送至每个关注他的用户的新鲜事列表
- 当用户需要查看自己订阅的新鲜事列表时,只需按时间顺序,从该新鲜事列表中取出
复杂度分析
当用户在刷新自己订阅的新鲜事列表时,只需1次DB读取。
当用户发一条新鲜事,若该用户被 N 个用户关注,则需执行 N 次 DB 写入。
在用户请求到达服务端后,服务端可先返回给用户“已发送成功”消息,用户无需等待所有数据插入完成,该操作可在系统异步执行,即【Fanout】:
假设现有四个用户之间好友关系如下:
张东升在 2020 年 06 月 20日 8:30 发一条新鲜事:“一起去爬山啊!”,此时新鲜事数据库表数据如下:
老陈发了一条新鲜事“今天碰上一个臭小子!”
严良发了一条:“我爸爸在哪呢?”:
朱朝阳结束了疲惫的一天发了条“终于记完了今天的日记。”:
基本伪代码:
// 获取新鲜事列表
function getNewsFeed(request) {
return db.getNews(request.user);
}
// 发布新鲜事
function postNews(request, content) {
db.insertNews(request.user, content);
AsyncTask.asyncExec(request.user, content);
return "success";
}
AsyncTask.asyncExec = (user, content) => {
let followings = db.readFollowings(request.user);
followings.forEach(f => {
db.insertNews(f, content);
});
}
缺陷
- 浪费DB空间: 同一条新鲜事会在数据表中存储多条,尽管这问题可通过在 fanout 的表中,只记录新鲜事 id 来优化,但是相比较而言,这一方案是更浪费DB存储空间
- 新鲜事更新可能会不及时: 如一个明星有 1M 粉丝,整个 Fanout 的过程可能要持续相当一段时间,有些粉丝可能已经收到这个明星发布的新鲜事,但是有的粉丝可能半小时后才收到,影响用户吃瓜的体验!