经常使用Feed流架构实现

业务中不少需求都会用到相似feed流的架构。
例如数据库

  • 微信朋友圈
  • 微博
  • 动态
  • 1对N消息。

通常feed流的架构实现有下面几种。
假如如今的业务场景是微博,而后当前的数据状况是:后端

用户A关注了用户B和C,用户D关注了用户B
用户B发了微博A,B,用户C发了微博C,D微信

1. 拉

数据表架构

  • 微博表(字段有:微博ID,微博内容,发布人)

代码逻辑:性能

  1. 用户 B发布微博接口,插入记录到微博表,只有一行记录
  2. 用户A获取我关注的用户的微博接口:
    1. 获取当前登陆用户关注的用户,例如A关注的用户B和C
    2. 获取B和C发布的全部微博,
    3. 按时间倒序排列,分页,返回

优缺点:优化

  • 实现简单
  • 空间占用较少,一条微博只用一条数据库记录
  • 数据量大的状况下, 第2个接口查询较慢(须要用临时表,并且查询数据较多)

2.推

数据表code

  • 微博表(字段有:微博ID,微博内容,发布人)
  • feed流表(字段有:微博ID,发布时间,接收人)

代码逻辑:索引

  1. 发布微博接口
    1. 插入记录到微博表
    2. 获取当前用户粉丝用户列表,假如当前用户是B,那就是获取A和D
    3. 插入2行记录到feed流表
      1. 接收人=A,微博ID=刚才的微博表ID
      2. 接收人=B,微博ID=刚才的微博表ID
  2. 用户A获取我关注的用户的微博接口:
    1. 查询feed流表,找到接收人=A的记录,按发布时间倒序排,分页,返回

优缺点:接口

  • 实现较复杂
  • 空间占用较多,一条微博须要插入1+N条记录(N是粉丝用户数)。若是N是几十w或者几百w,对数据库压力很是大,包括空间占用,插入或删除耗时,索引创建等。
  • 第2个接口能够用索引,因此查询很快,。

3.推+拉

上面两种方案都有优缺点,当对读的要求很高,同时用户粉丝数很大,就要想办法优化,推+拉是其中一种方案。
具体方法是区分用户:产品

  • 对于常常读取的用户,采用推方案,保证读取的性能
  • 对于不常读取的用户,采用拉方案,下降存储压力

从产品的角度看,有不少种方法能够区分用户是否属于常常读,这里提供其中一个可行的方案:

4. 区分活跃用户的推+拉

数据表

  • 微博表(字段有:微博ID,微博内容,发布人)
  • feed流表(字段有:微博ID,发布时间,接收人)
  • 活跃用户表(字段有:用户ID,是否活跃,最新登陆时间)

代码逻辑:

  1. 发布微博接口
    1. 插入记录到微博表
    2. 获取当前用户活跃粉丝用户列表,假如当前用户是B,那就是获取A和D,其中A是活跃用户,D是非活跃,那就只获取A。SQL能够用exists,例如:select * from fans where exists (select * from 活跃表 where 是否活跃=1)
    3. 插入1行记录到feed流表(D不是活跃用户,就不插入了)
      1. 接收人=A,微博ID=刚才的微博表ID
  2. 用户A获取我关注的用户的微博接口:
    1. 查询feed流表,找到接收人=A的记录,按发布时间倒序排,分页,返回
  3. APP启动接口(每次APP启动,发送一个请求到后端)
    1. 若是用户是活跃用户,更新用户最新登陆时间
    2. 若是不是,经过拉方式为用户补发feed流:
      1. 获取用户全部关注的用户
      2. 获取这些用户发的微博
      3. 把这些微博ID插入到用户的feed流表(要避免重复插入)
  4. 定时任务
    1. 天天把最新登陆时间小于1天前的用户,设置为非活跃

优缺点:

  • 第2个接口能够用索引,因此查询很快。
  • 数据库压力下降。由于通常粉丝中活跃用户只有小部分,同时补发的时候,能够只补发最新的N条微博,进一步节省空间,固然这些要和产品经理制定好规则。
  • 逻辑较复杂
  • 由于补发feed流须要必定时间,因此这期间用户只能拉到旧的微博

5.总结

  • 若是想简单作,并且对读取要求不高,用拉方式就能够了
  • 若是对读取要求高,同时粉丝数很少,例如朋友圈,最多就几千个朋友,建议用推方式
  • 若是粉丝数不少,例如微博,动辄几十万到几千万粉丝的,建议用推+拉方式

未经容许,请不要转载

相关文章
相关标签/搜索