Feed 流 —— Timeline

Timeline

本文介绍基于关注关系并按时间排列的 Feed 流

Feed 流有两种工作模式,推模式和拉模式

拉模式

在用户查询时应该首先查询用户关注的所有博主的 uid 查询他们发布的作品,最后按照发布时间降序排列

拉模式用户每打开一次 “关注页” 系统就需要读取 N 个人的文章(N 为用户关注的博主数)所以拉模式又被称为读扩散

拉模式不需要额外存储数据

  • 发布文章在 articles 表增加一条数据
  • 用户关注在 followings 表中增加一条数据

在粉丝数特别多的博主发布内容时,不需要进行特殊处理,等到用户进入关注页再计算就好

但是每次进入关注页都要进行大量读取和排序操作,如果用户关注的人比较多,一次拉取耗时会很大

推模式

博主在发布文章的时候就要把新文章写入粉丝的 Timeline 中,用户每次只需要到自己关注的 Timeline

推模式每次发布文章都要写入 M 条数据(M 是粉丝数)所以推模式也叫写扩散

在粉丝数比较多的博主,每次发布作品都要推送很多,体验不够友好

一般发布文章之后,前端返回成功,用 MQ 异步向粉丝 Timeline 推送

在线推,离线拉

Timeline 实际上就是一个缓存

Timeline 的存储设置过期时间,如果用户一段时间没有打开 APP,Timeline 会失效,在他回归之后通过拉模式重建缓存即可

判断用户是否在线,也就可以通过 Timeline 缓存是否存在作为判断依据

并且用户总是关心关注页中最新的内容,所以 Timeline 也没必要存完整的数据,存最近一段时间的即可,旧数据等用户翻阅时重建

存储

用 ZSet 存储,article_id 作为集合的 member,发布时间戳作为 score

推送的时候对目标 Timeline 的 ZSet 进行 ZAdd 操作,若缓存没有某个 Timeline 就用拉模式重建

存在的问题

  • 如果没有某个 Timeline 的缓存时,无法判断缓存是否失效了,还是这个用户的Timeline 本来就是空的,只能通过读取 MySQL 数据才能判断,会造成缓存穿透

  • 由于只存储一段时间的 Timeline 所以当读完了 Redis 中的数据之后,无法判断数据库中是否有更久的数据

解决办法:

  • 在 ZSet 中放一个 noMore 标志,表示数据库中没有更多的数据了,对于 Timeline 本来就为空的用户,他们 ZSet 中只有一个 noMor 标志

Feed 流 —— Timeline
http://showyoubug.cn/2024/07/06/Timeline/
作者
Dong Su
发布于
2024年7月6日
许可协议