Redis实现用户点赞、点赞top5用户排序

案例需求

 

方案分析

 

一个用户对于一个blog只能点赞一次,如果只使用数据库完成该功能,那么用户每点赞一次都要查询、修改数据库,这样无疑增加了数据库的压力,那么引入redis,就可以使用redis的Sorted_Set集合解决该问题(中间件的引入当然是越少越好的,这样有利于系统的稳定性,那此处为了场景演示就引入redis了,毕竟现在有点规模的项目基本都离不开redis)

redis的Sorted_Set集合集合中的元素具有唯一性、有序性,利用唯一性完成一个用户对于一个blog只能点赞一次,利用有序性完成点赞top5的用户排序,key是blog的id,value是用户id和用于排序的时间戳,如果该key的value中有当前登录用户的userId,那么说明该用户对该blog已点赞,那么可以利用该用户的时间戳进行排序,如果没有当前登陆用户的userId,则未点赞。

点赞功能代码实现

   @Override
    public Result   likeBlog(Long id) {
        //获取当前用户
        Long loginUserId = UserHolder.getUser().getId();
        //判断该用户是否点赞
        String key="blog:liked:"+id;

        Double score = stringRedisTemplate.opsForZSet().score(key, loginUserId.toString());
        //score为空说明该用户未点赞
        if (score==null){
            //如果未点赞则点赞成功,数据库点赞数+1,用户对该blog的点赞信息添加到redis的set
            boolean isUpdate = update().setSql("liked = liked + 1").eq("id", id).update();
            if (isUpdate){
                //opsForZSet使用的是scoreSet集合,该集合较于set集合,可以对元素进行排序,基于该特性可以对点赞用户的顺序进行排名
                stringRedisTemplate.opsForZSet().add(key,loginUserId.toString(),System.currentTimeMillis());
            }
        }else {
            //如果已点赞则取消点赞,数据库点赞数-1,用户对该blog的点赞信息从redis的set移除
            boolean isUpdate = update().setSql("liked = liked - 1").eq("id", id).update();
            if (isUpdate){
                stringRedisTemplate.opsForZSet().remove(key,loginUserId.toString());
            }
        }

        return Result.ok();
    }

 最早点赞top5功能代码实现

  @Override
    public Result queryBlogLikes(Long id) {
        //从redis查询top5的点赞用户
        Set<String> top5 = stringRedisTemplate.opsForZSet().range("blog:liked:" + id, 0, 4);
        if (top5==null||top5.isEmpty())
        {
            return Result.ok(Collections.emptyList());
        }
        //从查询的数据中得到top5的用户id
        List<Long> ids = top5.stream().map(Long::valueOf).collect(Collectors.toList());
        String idsStr = StrUtil.join(",", ids);
        //根据id查询top5的用户并返回
//        List<User> users = userService.listByIds(ids);
        //详见黑马点评 实战篇 P10
        List<User> users = userService.query().in("id", ids).last("ORDER BY FIELD (id," + idsStr + ")").list();
        List<UserDTO> userDTOS = users.stream()
                        .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
                .collect(Collectors.toList());

        return Result.ok(userDTOS);
    }

细节注意

在最初使用userService.listByIds(ids)查询数据库用户时,查询条件中的id顺序和查询结果的顺序是相反的,具体效果如下:

先查id=5,再查id=1,结果是id=1在前面,id=5在后面,这样导致最早点赞top5的用户顺序相反

为解决上述问题,使用order by对id排序

 注意这里演示的id是确定的数值,在实际代码中要把查询到的用户id列表转换成动态字符串,如下:

//从查询的数据中得到top5的用户id
        List<Long> ids = top5.stream().map(Long::valueOf).collect(Collectors.toList());
        String idsStr = StrUtil.join(",", ids);

 List<User> users = userService.query().in("id", ids).last("ORDER BY FIELD (id," + idsStr + ")").list();
        List<UserDTO> userDTOS = users.stream()
                        .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
                .collect(Collectors.toList());

Bug修正

redis报错

WRONGTYPE Operation against a key holding the wrong kind of value

 原因是由于之前点赞功能是使用set集合,使得redis中已经存在了一个名为"blog:liked:23"的key值,添加点赞top5功能后由于把set集合换成了sorted_set集合导致key冲突,解决方案是删掉之前的key值

相关推荐

  1. uniapp 实现双击出现特效

    2024-07-18 13:48:02       44 阅读
  2. 用c语言写一个抖音系统

    2024-07-18 13:48:02       45 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-18 13:48:02       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-18 13:48:02       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-18 13:48:02       57 阅读
  4. Python语言-面向对象

    2024-07-18 13:48:02       68 阅读

热门阅读

  1. live555 rtsp服务器实战之doGetNextFrame

    2024-07-18 13:48:02       22 阅读
  2. 依赖倒置原则

    2024-07-18 13:48:02       19 阅读
  3. Python使用队列在两个线程中传递数据

    2024-07-18 13:48:02       18 阅读
  4. STM32判断休眠

    2024-07-18 13:48:02       20 阅读
  5. Spring boot 2.0 升级到 3.3.1 的相关问题 (四)

    2024-07-18 13:48:02       16 阅读
  6. Miniforge 安装器

    2024-07-18 13:48:02       20 阅读
  7. 基于opencv的图片加水印实现方案

    2024-07-18 13:48:02       20 阅读
  8. redis知多少

    2024-07-18 13:48:02       21 阅读
  9. 【LeetCode 0069】【二分查找】求平方根

    2024-07-18 13:48:02       22 阅读
  10. 密码学原理精解【8】

    2024-07-18 13:48:02       19 阅读