SortedSet实现点赞功能附带排行榜

发布时间 2023-08-25 13:22:31作者: 自学Java笔记本

SortedSet的基本使用

Sorted set 也称Zset类型,是一种具有排序效果的set集合。它跟set集合一样也是 string 类型元素的集合,且不允许重复的成员。并且要求每个元素都会关联一个double 类型的分数。后续可以通过分数来为集合中的成员进行从小到大的排序。

Sorted set集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

数据缓存结构:
image

命令格式 功能 案例
zadd key score member 往key集合中添加member元素,分数为score zadd players 100 a
zincrby key increment member 将key集合中的member元素 分数 + increment zadd players 100 a
zrange key start stop [withscores] 将key集合中的元素按分数升序排列 [显式分数] zrange players 0 -1 withscores
zrevrange key start stop [withscores] 将key集合中的元素按分数降序排列 [显式分数] zrevrange players 0 -1 withscores
zrank key member 返回member元素在key结合中的正序排名 zrank players a
zrevrank key member 返回member元素在key结合中的倒序排名 zrevrank players a
zcard key 返回key集合元素个数 zcard players
zscore key member 获取指定key和member中的分数,返回score zscore players a

点赞需求

需求:

  • 同一个用户只能点赞一次,再次点击则取消点赞
  • 如果当前用户已经点赞,则点赞按钮高亮显示(前端已实现,判断字段Blog类的isLike属性)

实现步骤:

  • 给Blog类中添加一个isLike字段,标示是否被当前用户点赞1
  • 修改点赞功能,利用Redis的sortedset集合判断是否点赞过,未点赞过则点赞数+1,已点赞过则点赞数-12修改根据id查询Blog的业务,判断当前登录用户是否点赞过,赋值给isLike字段3修改分页查询Blog业务,判断当前登录用户是否点赞过,赋值给isLike字段

核心代码

 public Result likeBlog(Long id) {
        //1. 获取登录用户
        Long userId = UserHolder.getUser().getId();
        // 2.判断当前用户是否已经点赞,从redis中判断,采用sortedset中的score,返回的是一个时间戳,如果集合中不存在对应的元素,返回的是null
        Double score = stringRedisTemplate.opsForZSet().score(RedisConstants.BLOG_LIKED_KEY + id, userId.toString());
        //3.如果未点赞,可以点赞
        if (score ==null){
            //3.1数据库点赞数+1
            boolean isSuccess = update().setSql("liked=liked+1").eq("id", id).update();
            if (isSuccess){
                //3.2保存用户到redis的 sortedset中,zadd key value source
                stringRedisTemplate.opsForZSet().add(RedisConstants.BLOG_LIKED_KEY+id,userId.toString(),System.currentTimeMillis());
            }
        }else {
            //4.如果已点赞,取消点赞
            // 4.1数据库点赞数-1
            boolean isSuccess = update().setSql("liked=liked-1").eq("id", id).update();
            if (isSuccess){
                // 4.2 把用户从redis的set集合中移除
                stringRedisTemplate.opsForZSet().remove(RedisConstants.BLOG_LIKED_KEY+id,userId.toString());
            }
        }
        return Result.ok();
    }