【Redis】Redis实现点赞、点赞排行榜

目录

一、点赞

1、思路

2、代码实现

二、点赞排行榜

1、思路

2、代码实现


一、点赞

1、思路

在我们的项目中我们有时候会碰到这样的需求,比如实现一个博客系统,当用户访问到这篇博客时可以进行点赞,那么这个功能如何去实现呢,我们可以在数据库中维护一张点赞表,当用户刚进入这个博客页面时拿着这个博客的id发起请求查询这张点赞表,看是否存在点赞记录,如果存在返回前端,前端获取到后将点赞按钮高亮色展示,当用户再次点击时则发起取消点赞请求将数据库中点赞数-1且删除点赞记录,如果没有点过赞则发起点赞请求操作数据库使得点赞数+1以及插入一条点赞记录,上述流程基本全是数据库操作,我们可以通过redis来对该功能进行优化,那么我们怎么优化呢,可以借鉴之前redis优化秒杀项目一人一单的思路,此处一人只能赞一次与一人一单极为相似,我们可以使用redis中的set数据结构,当用户点赞时可以将该博客的id作为set类型key的组成,将用户id作为value值存入set,然后让数据库中点赞量+1。用户进入页面后查询redis中的该set集合,发现该用户id在其中,则使点赞按钮高亮色再次点击时将数据库中的点赞数-1在将该用户id从set集合中移除,整体思路如上述,下面我们使用代码来实现一下

2、代码实现

此处为了代码全部展示,将部分操作全部放在controller层,其中reidskey的命名为了方便此处阅读使用硬编码而没有使用redis key工具类进行管理,在项目开发中推荐使用自定义redis key的工具类进行管理

@RestController
@RequestMapping("/api/follow")
public class FollowController {
     @Autowired
    private StringRedisTemplate stringRedisTemplate;
     @Autowired
    private FollowService followService;
     /**
     * 点赞和取消点赞接口(使用Redis缓存防止重复操作)
     * @param id 文章ID,不能为空且必须为正整数
     * @param request HTTP请求对象
     * @return 返回结果对象
     */
    @PostMapping("/like")
    public ReturnModel like(@NotNull @Positive Integer id, HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session == null || session.getAttribute(ApplicationVariable.USER_SESSION_KRY) == null) {
            // 判断用户是否已经登录
            return ReturnModel.fail(-1, "您尚未登录");
        }
         User user = (User) session.getAttribute(ApplicationVariable.USER_SESSION_KRY);
        Integer userId = user.getId();
         Boolean isLiked = stringRedisTemplate.opsForSet().isMember("like:user:" + id, userId.toString());
        if (Boolean.TRUE.equals(isLiked)) {
            // 如果已经点赞,将该用户id从set中移除,并将数据库点赞数-1
            boolean isSuccess = followService.update(id, -1);
            if (isSuccess) {
                stringRedisTemplate.opsForSet().remove("like:user:" + id, userId.toString());
            }
        } else {
            // 如果未点赞,将该用户id加入set中,并将数据库点赞数+1
            boolean isSuccess = followService.update(id, 1);
            if (isSuccess) {
                stringRedisTemplate.opsForSet().add("like:user:" + id, userId.toString());
            }
        }
         return ReturnModel.success(200);
    }
 }

二、点赞排行榜

1、思路

如果我们需要在点赞功能的基础上实现展示最先点赞的前10个人,获取亲密度比较高的前10个人,那么我们如何去修改上述的代码去实现呢?这里我们要实现的功能带有排序的特点,那么在redis中哪些数据结构带有排序的特性呢

List Set SortedSet
排序 按照添加的顺序进行排序 无法排序 根据score值排序
唯一 不保证唯一 保证唯一性 保证唯一性
查找 按索引查找获取按首尾查找 根据元素查找 根据元素查找

在上述三种结构中满足可排序且保证唯一性的只有SortedSet,我们可以通过它的zscore key命令来查找用户是否存在,如果存在就会返回他的score如果不存在则返回空,我们可以通过返回结果来判断用户是否点赞,可以通过zrange命令来获取最先点赞的前10个用户的id,然后通过数据库查找返回

2、代码实现

【Redis】Redis实现点赞、点赞排行榜_第1张图片

public ReturnModel followByRedis(@NotNull @Positive Integer id, HttpServletRequest request) {
        // 1.首先获取用户id
        HttpSession session = request.getSession(false);
        if (session == null || session.getAttribute(ApplicationVariable.USER_SESSION_KRY) == null) {
            return ReturnModel.fail(-1,"您尚未登录");
        }
        User user = (User) session.getAttribute(ApplicationVariable.USER_SESSION_KRY);
        Integer userId = user.getId();

        // 2.查询当前用户是否点赞
        Double score = stringRedisTemplate.opsForZSet().score(RedisUtil.FOLLOW_KEY + id,userId.toString());
        if (score != null) {
            // 2.1 已点赞,则数据库点赞数-1 将该用户id从set中移除
            boolean isSuccess = followService.update(id,-1);
            if (isSuccess) {
                // 数据库操作成功,set中移除id
                stringRedisTemplate.opsForZSet().remove(RedisUtil.FOLLOW_KEY + id,userId.toString());
            }
        } else {
            // 2.2 未点赞,则数据库点赞数+1 将该用户id加入set中
            boolean isSuccess = followService.update(id,1);
            if (isSuccess) {
                // 数据库操作成功,userId加入set
                stringRedisTemplate.opsForZSet().add(RedisUtil.FOLLOW_KEY + id,userId.toString(),System.currentTimeMillis());
            }
        }

        // 3.返回结果
        return ReturnModel.success(200);
    }

后续获取前10时可以通过

stringRedisTemplate.opsForZSet().range(RedisUtil.FOLLOW_KEY + id,0,9);

来获取存在redis中的前10个用户id,然后去查询数据库中对应得用户信息进行返回

你可能感兴趣的:(Redis,Java,redis,数据库,java)