从最早的Twitter、Facebook,到后来的微信朋友圈、信息流咨询,这些产品其实都是常见的FEED流系统。
那么今天思考一下,如何实现一个中小型FEED流系统。
在系统刚开始创建的时候,可以先考虑下面这两种方式:推模式和拉模式。
推模式
推模式,是发生在用户触发行为(发布新的动态,关注某个人,点赞)的时候。在触发时,用户的自身行为会记录到对应的行为表中,其次用户的行为也会记录到自己的粉丝对应动态表中。
上面的流程大概是:
1 2 3 |
|
使用推方式,对需求变更是易适应的。
因为用户每一次的行为,我们都有存储相应的数据。即使变更,只需更改逻辑层代码。另外性能较好,后台数据已经准备好了,无需复杂的SQL查询。当然这样做,也存在很多弊端。
1 2 |
|
拉模式
拉方式,是发生在粉丝拉取FEED时。粉丝拉取自己的动态,首先会检索自己的关注用户(UID分表)。得到关注的UID之后,再根据UID去查询关注用户发布的帖子。
拉的模式相对是比较简单易实现的,另外对用户关系变更(新增,删除用户)是敏感的。其次也不存在数据存储压力。但在查询的时候,对帖子表本身压力是很大的。尤其是用户本身关注的人很多的话,会有很严重的性能问题。
下面可以使用另外一种方式来优化拉模式。
拉方式优化-伪实时拉取
用户在登录APP时,会发送用户活跃态到服务端。活跃信号塞到队列中,消费者依次读取活跃态UID,得到用户的关注者列表。得到关注者列表后,会去帖子表,查询关注人的发布的帖子。写到用户自己的FEED中。
这种方式和对拉方式而言,能有效避免接口性能问题,相当于通过定时任务提前把用户的动态FEED跑出来。
和推方式比较,推是比较盲目的,这种方式只需针对活跃用户即可,能避免存储浪费。缺点在于实时性不好,用户登录APP后马上进入自己的FEED页,此时如果后台用户动态还没跑完,接口读取的就是历史数据了。当然这种方式不适合知乎,微博这种类型的APP的。
拉方式优化-分区拉取
分区拉取,是为了避免频繁查询单一帖子表所采用的一种优化手段。通过对帖子按照时间片分表,每次查询都能均摊到不同的表中,以此减轻主表的压力。
推方式优化-定时推
定时推,是以常驻进程的方式读取用户的发帖行为,再批量写入到粉丝的动态表中。这种方式和推方式差不多,只不过可以对多个发帖行为做聚合。
推方式优化-特定用户推
特定用户推,是推方式的一种优化方法。用户发送帖子时,只对活跃的粉丝用户写入。当然活跃用户的判定策略,是需要商定的。
总结
以上几种方案,都有自己的利弊和适用场景。选择最适合自己的就是最好的。
以上的方案还需要不断扩充完善。