day43 用户关注、共同关注与关注推送Feed流

1. 今天做了什么

  • 实现了关注与取消关注功能,逻辑简单,交给 AI 快速完成
  • 实现了共同关注功能,使用 Redis Set 集合 + SINTER 命令
  • 实现了关注推送(Feed 流)功能,采用推模式 + Redis ZSet + 滚动分页

2. 核心知识点

关注与取消关注

  • 关注表存储用户 id 与关注用户 id,建立用户与用户之间多对多的联系
  • 关注 / 取消关注接口就是实现关注表的新增与删除
  • 获取是否关注就是一次查询操作

共同关注

  • 实现方案:用 Redis 的 Set 集合维护每个用户的关注用户
  • 共同关注依靠 Redis Set 的 SINTER 命令完成

关注推送 — Feed 流模式

  • Feed 流模式分类:时间排序、智能推荐
  • 本次关注推送采用时间排序

时间排序的三种实现方案:

  1. 拉模式:博主发内容存入发件箱,粉丝收件箱默认不存,粉丝查看时,拉取所有关注的发件箱,并按时间排序
    • 优点:节省空间,博主发件只写一份
    • 缺点:粉丝拉取耗时较久
  2. 推模式:博主发文,写入所有粉丝收件箱,粉丝查看直接读取收件箱
    • 优点:粉丝读取速度快
    • 缺点:博主发文写入较多,占用空间
  3. 推拉结合:
    • 根据博主粉丝量、用户活跃度差异性选择
    • 小博主推模式
    • 大博主:活跃粉丝推,非活跃粉丝拉
    • 优点:根据不同情况优化,适应性强
    • 缺点:实现复杂

推模式实现细节

  • 收件箱使用 Redis 的 Sorted Set
  • 每次发文,查询粉丝,向粉丝收件箱添加文章 id

滚动分页

传统角标分页的问题:第一次查询后,有新内容插入到前面,下次分页会查到重复内容。

采用滚动分页方案:

  1. 前端需要携带 lastTime,首次查询是当前时间戳,下一次查询时是上次的最早消息的时间戳,以时间戳为依据确保不会查到之前查过的元素
  2. 前端还需要传一个 offset(上次查询与最小时间相同的博文数),因为查询时最大值是包含的,该最大值是上次查询的最小值,已经查询过了,确保查询时能跳过上次查过的几条内容,该值由上次查询时后端返回
  3. 使用 stringRedisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, 0, max, offset, 3); 查询,最小值最大值都是包含的
  4. 处理数据,查询文章
  5. 封装时要携带 minTime、offset、Bloglist,返回给前端

3. 深度思考

  • 共同关注功能实际上就是为了学习 Redis 而使用 Redis 的 SET 集合,该方案并非优选
  • 实际上:
    1. 该功能不是热点功能,不需要依靠 Redis
    2. 将所有用户关注表用 Redis 缓存也不实际

4. 踩过的坑

5. 遗留问题 / 想不通