Redis实现点赞功能

ZSET

问题:防重复点赞,通过 Redis 判断用户是否已点赞,避免重复操作。

数据库和 Redis 协同维护点赞状态,确保前端展示一致性。

利用 Redis 的原子操作(如 ZSET)快速处理点赞 / 取消点赞请求,减少数据库压力。

基于 Redis 有序集合按时间戳排序,高效获取点赞排行榜。

Redis数据结构:Redis 有序集合(ZSET),存储用户 ID 和点赞时间戳,保证唯一性(ZADD 天然去重);通过 ZSCORE 快速判断用户是否已点赞;使用 ZRANGE 获取点赞排行榜(如前 5 名);

Redis命令:ZADD key score member(存储用户点赞记录)、ZSCORE key member(检查用户是否已点赞)、ZREM key member(取消点赞时移除用户记录)

  • @Override
        public Result likeBlog(Long id) {
            // 判断当前用户是否点赞
            UserDTO user = UserHolder.getUser();
            if(user == null){
                return Result.fail("用户未登录");
            }
            Long userId = user.getId();
            String key = "blog:liked:" + id;
            Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
            if(score == null){
                //如果未点赞则点赞
                //更新点赞数量到数据库
                boolean issuccess = update().setSql("liked = liked + 1").eq("id", id).update();
                //保存点赞用户到redis集合, 按时间排序最先点赞的会排在前面
                if(issuccess){
                    stringRedisTemplate.opsForZSet().add(key,userId.toString(),System.currentTimeMillis());
                }
            }
            else {
                //如果已点赞则取消点赞
                //数据库减去
                boolean issuccess = update().setSql("liked = liked - 1").eq("id", id).update();
                //redis中删除
                if(issuccess){
                    stringRedisTemplate.opsForZSet().remove(key,userId.toString());
                }
            }
    ​
            return Result.ok();
        }
    ​
    // 点赞排行
    @Override
    public Result queryBlogLikes(Long id) {
        String key = BLOG_LIKED_KEY + id;
        // 1.查询top5的点赞用户 zrange key 0 4
        Set top5 = stringRedisTemplate.opsForZSet().range(key, 0, 4);
        if (top5 == null || top5.isEmpty()) {
            return Result.ok(Collections.emptyList());
        }
        // 2.解析出其中的用户id
        List ids = top5.stream().map(Long::valueOf).collect(Collectors.toList());
        String idStr = StrUtil.join(",", ids);
        // 3.根据用户id查询用户 WHERE id IN ( 5 , 1 ) ORDER BY FIELD(id, 5, 1)
        List userDTOS = userService.query()
                .in("id", ids).last("ORDER BY FIELD(id," + idStr + ")").list()
                .stream()
                .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
                .collect(Collectors.toList());
        // 4.返回
        return Result.ok(userDTOS);
    }

你可能感兴趣的:(Redis必知会,redis,spring,boot,java)