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<String> top5 = stringRedisTemplate.opsForZSet().range(key, 0, 4);
        if (top5 == null || top5.isEmpty()) {
            return Result.ok(Collections.emptyList());
        }
        // 2.解析出其中的用户id
        List<Long> 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<UserDTO> 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);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值