如何设计一个动态Feed流系统?


一、什么是Feed流?

Feed流就是能够实时/智能推送消息的数据流,如微博、朋友圈、动态等都属于Feed流。

Feed流有几个重要的概念:

  • Feed:每一条消息都是一个Feed,如微博中的每一条微博等
  • Feed流:多个Feed组成一个Feed流,如微博关注页、微信朋友圈等
  • Timeline:即按照发布时间排序的Feed流,如微信朋友圈等(不按照推荐逻辑)
  • Rank:即按照智能推荐排序的Feed流,如微博推荐页等

二、如何设计一个动态Feed流系统?

1、初始化

一开始用户还没有对应的Feed流的时候,我们就应该创建一个,如微博关注页,具体通过MySQL+Redis实现即可。

用关系型数据库MySQL就能完成了为什么还要用Redis呢?因为Feed流的场景是读多写少的,如果查询性能比较差,会很大程度影响用户体验的。

而Redis我们可以使用Zset数据结构来做,因为它是一个有序集合,可以按照我们的排序规则进行排序,如:

  • key值:存当前用户id
  • member值:存消息id
  • score值:存消息id和对应的发布时间/权重

2、推送时机

Feed流是会更新的,所以我们要考虑每一个推送时机,具体如下:

  • 用户关注
  • 用户取消关注
  • 关注的用户发动态
  • 关注的用户删动态

3、推送模式

Feed流的推送模式主要包括三种:

  • 推模式:即主动推,如用户发了一条动态,那么会给所有关注他的用户都退一条Feed,这样的缺点是数据量太大(如果有千万个粉丝,则需要推千万条Feed)
  • 拉模式:即被动拉,如用户发了一条动态,我们并不会做什么措施,而是等关注他的用户拉取关注页时再实时去查询,这样的缺点就是查询速度慢、聚合复杂(可以考虑使用es查询)
  • 推拉结合模式:主要针对大V场景(粉丝量大),我们需要先区分哪些用户是大V(比如粉丝量超过100w),然后当用户发动态时,先判断是否为大V,如果是的话则用拉模式,如果不是的话则用推模式

4、推送步骤

当用户发布一条动态

  1. 判断该用户是否大V,如果是则不做后续处理
  2. 如果是普通用户,则将该条Feed发送给该用户的粉丝的Feed流

当用户刷新关注页

  1. 拉取自己的Feed流
  2. 查询自己关注的大V列表,并发拉取他们的动态Timeline
  3. 合并步骤1和步骤2的结果返回

三、Q&A

1、如果用推拉结合模式的话,可能会导致大V的动态Timeline读压力过大,要怎么解决呢?

我们知道粉丝也分为活跃粉和非活跃粉,那么我们针对这个做处理可以吗?

比如当大V发了一条动态,我们只需要对活跃粉采用推模式,而对非活跃粉采用拉模式,这样就能避免所有的用户都过来拉而导致读压力过大。(缺点可能是我们要多加判断活跃粉)


文章作者: GaryLee
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 GaryLee !
  目录