目录
前言
类似于社交软件 or 网站 往往需要向用户 推荐一些 帖子 或者 文章 等。
本篇文章将介绍,如何基于 Redis 的 ZSet 和 Spring的定时任务 实现一个 内容推荐 的功能。
ZSet 存储结构
在介绍项目方案之前,我们先来了解下 ZSet 的 相关存储结构。
结构图
我们知道 ZSet 是一个 有序的集合。在 Redis 中,ZSet 的 Value 分为多个 entry。
每一个 entry 又分为一个 member (值), 和 score (分),排序规则就是按照 score 顺序排序。
我们可以在 member 中存入对应内容的标识,如 帖子 id 等
并且 Redis 提供了 score 的原子递增接口,一定程度上保证了 线程安全
ZINCRBY key increment member
JavaAPI
redisTemplate.opsForZSet().incrementScore(key, postId, score);
执行上述命令后,"member1"的分值将进行递增指定分值。如果"member1"不存在,Redis会自动将其添加到有序集合中,并将初始分值设为递增值。
此方案主要在扫出帖子后直接对数据(浏览量、点赞量、评论量)进行运算,如想将推荐功能变为 实时计算 的,可以使用该 API 进行热度变更
ZSet 相关的底层存储结构涉及 跳表、压缩列表、packlist ,在存储的 entry 数量 超过 128 个时,将由 压缩列表 变为 跳表 存储。
功能设计
假设我们以 热门帖子推荐 为例
流程图展示
流程介绍
- 首先,我们在每天凌晨先对 前一周 的帖子进行扫描,主要扫出在这一周之内 发布的帖子。
- 在扫出指定内容后,对帖子的数据做处理计算。如浏览量、点赞量、评论量等
- 根据自己规定的算法,对帖子计算出指定权重,并按照 帖子 id 为 member, score 为计算的权重 存入Redis 中。
- 在 ZSet 中,我们的内容已经自动完成排序,接下来只需要取出目标条数。在根据 id 把 相关内容查询出来即可。
这样下来,一个简易的 内容推荐功能就完成了。
很多内容其实也是可以进行修改很拓展的。比如:
- 扫描的时间可以不限于这一周
- 使用其他的算法来计算权重
等等