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

2023-11-16

目录

一、点赞

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、代码实现

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,然后去查询数据库中对应得用户信息进行返回

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Redis】Redis实现点赞、点赞排行榜 的相关文章

  • 如果列名不同,则一对多休眠连接

    我有三个具有以下结构的表 合同 gt Contract id 主要 customer company id Vendor company id 公司 gt Company id 主要 创建日期 创建者 Company Timeline gt
  • Quarkus 不以编程方式选择 bean

    我试图以编程方式选择 bean 但 quarkus 不会注入 bean 并引发异常 不支持吗 public enum ReportType ONE TWO Qualifier Retention RUNTIME Target METHOD
  • Java:线程“主”中的异常 java.lang.StringIndexOutOfBoundsException:字符串索引超出范围:

    我是初学者 谁能帮我弄清楚我们在做什么 我正在尝试读取字符串并将字符串的每个字符存储在数组中 import java util Scanner public class CoreMainDigitExtractor static Scann
  • 检查 IPv4 地址是否在私有范围内

    在 Python 中 使用 IPy 模块您可以执行以下操作 gt gt gt ip iptype PRIVATE 有没有一个库或简单的方法可以在 Java 中执行相同的操作 似乎不完全是但是InetAddress有一些 isXX 方法 例如
  • 具有 CRUD 功能的基于 Spring Web 的管理工具

    在 PHP Symfony 世界里有一个工具叫 Sonata Adminhttps sonata project org https sonata project org 基于 AdminLTE 模板 这是一款一体化管理工具 具有登录 菜单
  • Kafka Java Consumer 已关闭

    我刚刚开始使用卡夫卡 我面临着消费者的一个小问题 我用Java写了一个消费者 我收到此异常 IllegalStateException 此消费者已关闭 我在以下行中遇到异常 ConsumerRecords
  • 使用 JAX-WS 的 WebLogic 中没有模式导入的单个 WSDL

    如何使用 JAX WS 配置由 WebLogic 10 3 6 生成的 Web 服务 以将对象架构包含在单个 WSDL 文件声明 而不是导入声明 中 示例代码 界面 import javax ejb Local Local public i
  • Web API 缓存 - 如何使用分布式缓存实现失效

    我有一个 API 目前不使用任何缓存 我确实有一个正在使用的中间件 它可以生成缓存标头 Cache Control Expires ETag Last Modified 使用https github com KevinDockx HttpC
  • 将现有 eclipse 项目导出到 war 文件时出现“模块名称无效”

    我正在尝试将现有 Eclipse 项目导出到 war 文件 但无论我在 WAR Export 对话框页面中输入什么 系统总是返回 模块名称无效 我不知道如何解决这个问题 谢谢您的帮助 我有同样的问题 我修复了它 请按照以下步骤操作 您可以创
  • 是否有最新的 Facebook Java SDK? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 好像没找到最近更新的 如果没有 是否有一个好的 Java 库来执行与 Facebook 的 API 交
  • Android 解析 JSON 卡在 get 任务上

    我正在尝试解析一些 JSON 数据 我的代码工作了一段时间 我不确定我改变了什么突然破坏了代码 当我运行代码时 我没有收到任何运行时错误或警告 我创建一个新的 AsyncTask 并执行它 当我打电话时 get 在这个新任务中 调试器在此行
  • 合并两个地图的最佳实践是什么

    如何将新地图添加到现有地图 地图具有相同的类型Map
  • 改变 Java 中凯撒移位的方向

    用户可以通过选择 1 向左或 2 向右移动字母来选择向左或向右移动 左边工作正常 右边不行 现在它显示了完全相同的循环 但我已经改变了所有 and 以不同的方式进行标记 最终我总是得到奇怪的字符 如何让程序将字符向相反方向移动 如果用户输入
  • Jetty Plugin 9启动不喜欢icu4j-2.6.1.jar

    我对 mortbay 的 Maven jetty 插件 6 有相同的配置
  • JAXB 编组器无参数默认构造函数

    我想从 java 库中编组一个 java 对象 当使用 JAXB marschaller 编组 java 对象时 我遇到了一个问题 A 类没有无参数默认构造函数 我使用Java Decompiler来检查类的实现 它是这样的 public
  • Java和手动执行finalize

    如果我打电话finalize 在我的程序代码中的一个对象上 JVM当垃圾收集器处理这个对象时仍然再次运行该方法吗 这是一个大概的例子 MyObject m new MyObject m finalize m null System gc 是
  • Java 中处理异步响应的设计模式

    我读过类似问答的答案 如何在 JAVA 中创建异步 HTTP 请求 https stackoverflow com questions 3142915 how do you create an asynchronous http reque
  • 在 Freemarker 模板中检查 Spring 安全角色和记录的用户名

    有谁知道 freemarker 标签来检查 freemarker 文件中的 spring 安全角色和用户名 我从网络上的几个资源中发现以下代码将打印登录的用户名 但它没有打印用户名 而是打印 登录为
  • 如何清理 Runtime.exec() 中使用的用户输入?

    我需要通过命令行调用自定义脚本 这些脚本需要很少的参数并在 Linux 机器上调用 当前版本容易出现各种shell注入 如何清理用户给出的参数 参数包括登录名和路径 Unix 或 Windows 路径 用户应该能够输入任何可能的路径 该路径
  • 使用 AmazonSNSClient 发送短信时的授权

    aws 官方文档如何发送短信 http docs aws amazon com sns latest dg sms publish to phone html使用 java 中的 aws SDK 非常简单 但是 当发送如底部示例所示的消息时

随机推荐

  • springboot校园二手物品交易平台 毕业设计源码03373

    目 录 摘要 1 绪论 1 1 研究背景 1 2国内外研究现状 1 3论文结构与章节安排 2平台分析 2 1 可行性分析 2 2 系统流程分析 2 2 1 数据流程 3 3 2 业务流程 2 3 系统功能分析 2 3 1 功能性分析 2 3
  • 大数据标准化白皮书(2020版) 附下载地址

    大数据是新时代最重要的 数字金矿 是全球数字经济发展的核心动能 数据资源如同农业时代的土地 劳动力 工业时代的技术 资本 已经成为信息 时代重要的基础性战略资源和关键生产要素 是推动经济发展质量变革 效率变 革 动力变革的新引擎 不断驱动人
  • python爬取推特图片_twitter图片视频批量下载

    import requests import re from urllib request import urlretrieve import os import ssl ssl create default https context s
  • 试看5分钟视频python_Python面试应急5分钟!

    不论你是初入江湖 还是江湖老手 只要你想给自己一个定位那就少不了面试 面试的重要性相信大家都知道把 这就是我们常说的 第一印象 给大家说一下我的面试心得把 面试前的紧张是要的 因为这能让你充分准备 面试时的紧张是绝对要避开的 因为这可能导致
  • open source 3d map_3D视觉技术在机器人抓取作业中的应用实例

    原标题 3D视觉技术在机器人抓取作业中的应用实例 关键词 3D视觉 工业机器人 抓取 1 引言 3D视觉技术作为新兴的技术领域还存在很多亟待解决的问题 但2D视觉已不能满足空间抓取的应用要求 与2D视觉相比 3D视觉技术的优点有 1 3D视
  • C++ 创建桌面快捷方式

    include
  • 白盒测试——基本路径测试

    基本路径测试是将程序流程图转化为控制流图 通过分析控制结构的环路复杂性 进而找出路径的基本独立集 最终导出测试用例 基本独立集 从基本独立集导出的测试用例保证对程序中的每一条语句至少执行一次 控制流图 定义 百度百科 是一个过程或程序的抽象
  • 若依开关使用

  • OpenLayers 6加载各种地图源的方法(天地图、百度、高德、ArcGIS、Bing、OSM、Google等)

    前言 OpenLayers是一个用于开发WebGIS客户端的JavaScript包 OpenLayers 支持多种常用的地图来源 包括天地图 百度地图 高德地图 ArcGIS地图 Bing地图 OSM地图 Google地图等 一 加载天地图
  • 3D游戏编程——空间与运动

    3D游戏编程 空间与运动 1 简答并用程序验证 游戏对象运动的本质是什么 答 游戏对象运动的本质就是使用矩阵变换 平移 旋转 缩放 改变游戏对象的空间属性 我们做的游戏关键就是游戏对象在每一帧图像上怎么变换 最直观的就是观察我们每个对象的T
  • CSS SASS 外部引入的scss文件中,不能用嵌套写法

    小记录 在vue文件中引入scss文件中 不能正常使用sass语法 发现是引入方式的问题
  • 【自我提升】Spring Data JPA之Specification动态查询详解

    写在前面 刷完Spring Data JPA的课后 发现Specification动态查询还挺有意思的 还应用到了规约设计模式 在此记录下学习过程和见解 目录 一 应用场景 二 源码解析 三 规约模式 四 实际应用 一 应用场景 1 简介
  • 云数据库知识学习——概述

    一 云计算是云数据库兴起的基础 云计算是分布式计算 并行计算 效用计算 网络存储 虚拟化 负载均衡等计算机和网络技术发展融合的产物 云计算是由一系列可以动态升级和被虚拟化的资源组成的 用户无需掌握云计算的技术 只要通过网络就可以访问这些资源
  • function XX declared implicitly

    stm32 keilMDK出现warning function XX declared implicitly 原创 2014年08月26日 14 50 47 26281 warning 223 D function CLR TX DATA
  • 枚举类,属性循环---(枚举类循环)通过名称取值

    代码示例 public enum DomeEnum AA 1 张三 BB 2 李四 CC 3 王五 DD 4 赵六 EE 5 李七 private Integer code private String name DomeEnum Inte
  • Qt 官方示例

    哈喽 我是老吴 最近又玩了一下 Qt 给大家分享一点 Qt 相关的基础知识吧 我个人非常喜欢 Qt 它简直就是我这个 C 手残党的利器 学习 Qt 的最佳途径应该是阅读官方的手册和示例 今天要分享的就是 Qt 官方提供的一个示例 http
  • 一种针对夏克哈特曼波前传感器质心数据求解波前斜率的处理方法

    一 导出质心数据 针对夏克哈特曼波前传感器 型号 索雷博 导出的质心数据 Save Centroid Date 本文提供一种基于质心数据的斜率矩阵获取及波前重构方法 图 1 哈特曼波前传感器导出质心数据 二 斜率矩阵求解 首先 通过Wave
  • 2023上半年京东运动鞋服市场数据分析(京东数据运营)

    大众线下运动生活恢复 掀起新一轮户外潮流 运动热潮迭起 由此产生的运动鞋服及专业装备需求 为运动品牌们带来了诸多增长机会 近日各大运动品牌陆续发布上半年财报 回答了品牌对复苏机遇 发展挑战的应对情况 接下来结合具体数据 我们一起来看一下运动
  • 【基础知识】一文看懂深度优先算法和广度优先算法

    概览 先上个图 现在我们要访问图中的每个节点 即图的遍历 图的遍历是指 从给定图中任意指定的顶点 称为初始点 出发 按照某种搜索方法沿着图的边访问图中的所有顶点 使每个顶点仅被访问一次 这个过程称为图的遍历 我们根据访问节点的顺序与方式 根
  • 【Redis】Redis实现点赞、点赞排行榜

    目录 一 点赞 1 思路 2 代码实现 二 点赞排行榜 1 思路 2 代码实现 一 点赞 1 思路 在我们的项目中我们有时候会碰到这样的需求 比如实现一个博客系统 当用户访问到这篇博客时可以进行点赞 那么这个功能如何去实现呢 我们可以在数据