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

news2024/11/24 16:33:10

目录

一、点赞

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中哪些数据结构带有排序的特性呢

ListSetSortedSet
排序按照添加的顺序进行排序无法排序根据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,然后去查询数据库中对应得用户信息进行返回

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/549277.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Midjourney|文心一格 Prompt:完整参数列表、风格汇总、文生图词典合集

Midjourney|文心一格 Prompt:完整参数列表、风格汇总、文生图词典合集 1.Midjourney 完整参数列表 参数名称 调用方法使用案例注意事项V5V4V3niji版本在关键词后加空格,然后带上版本参数: --v 或者 —v –version 或者 —versionvibrant cali…

【密码学复习】第八讲 数字签名

数字签名(Digital Signature),也称电子签名,是指附加在某一电子文档中的一组特定的符号或代码,它是利用数学方法对该电子文档进行关键信息提取并与用户私有信息进行混合运算而形成的,用于标识签发者的身份以…

SpringBoot学习之集成Swagger3(二十七)

一、Maven配置 注意swagger的版本号是3.0.0版本以上才可以,这里我们就选择3.0.0版本 完整的Maven配置如下(仅供参考): <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaL…

vulnhub渗透测试靶场练习1

靶场介绍 靶场名&#xff1a;Medium_socialnetwork 下载地址&#xff1a;https://www.vulnhub.com/entry/boredhackerblog-social-network,454/ 环境搭建 靶机建议选择VM VirtualBox,我一开始尝试使用VMware时会报错&#xff0c;所以改用VM VirtualBox&#xff0c;攻击机使用…

魔改车钥匙实现远程控车:(前传)在macOS上安装使用Arduino

前言 因为最近有个需求需要硬件支持&#xff0c;原本打算使用 Arduino Nano&#xff0c;后来在 Boot 大佬的建议下&#xff0c;买了某宇宙家的 ESP32C3 核心板&#xff0c;对比 Arduino Nano 价格便宜了一大半&#xff0c;而且自身就集成了 WIFI 和 BLE 模块&#xff0c;还不用…

(一)before initialization of D3D(初始化D3D之前你需要了解的D3D基础知识)

什么是D3D? D3D全称Direct X 3D,即一组API可以用来针对GPU编程,不过他最主要的作用是用来渲染(不过现在也有很多其他应用比如d3d11va[Direct X 3D 11 Video API]用来进行硬件加速解码) Tips:Direct X 3D主要用来渲染,既然我们说到可以针对GPU编程了,当然不只是渲染的工作可以…

国考省考行测:数量关系,牛吃草问题,比例问题

国考省考行测&#xff1a;数量关系&#xff0c;牛吃草问题 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能&#xff0c;附带行测和申论&#xff0c;而常规国考省考最重要的还是申论和行测&#xff0c;所以大家认真准备吧&#xff0c;我讲一起屡屡申论…

〖Python网络爬虫实战㉘〗- Selenium案例实战(二)

订阅&#xff1a;新手可以订阅我的其他专栏。免费阶段订阅量1000 python项目实战 Python编程基础教程系列&#xff08;零基础小白搬砖逆袭) 说明&#xff1a;本专栏持续更新中&#xff0c;目前专栏免费订阅&#xff0c;在转为付费专栏前订阅本专栏的&#xff0c;可以免费订阅付…

图神经网络(处理点云)PPFNet的实现

文章说明&#xff1a; 1)参考资料&#xff1a;PYG官方文档。超链。 2)博主水平不高&#xff0c;如有错误还望批评指正。 3)我在百度网盘上传了这篇文章的jupyter notebook和有关文献。超链。提取码8848。 文章目录 前言文献阅读代码实操历史遗留问题 前言 本篇文章接上一篇文章…

今年的面试难度,我给跪了……

大家好&#xff0c;最近有不少小伙伴在后台留言&#xff0c;又得准备面试了&#xff0c;不知道从何下手&#xff01; 不论是跳槽涨薪&#xff0c;还是学习提升&#xff01;先给自己定一个小目标&#xff0c;然后再朝着目标去努力就完事儿了&#xff01; 为了帮大家节约时间&a…

【STM32G431RBTx】备战蓝桥杯嵌入式→决赛试题→第七届

文章目录 前言一、题目二、模块初始化三、代码实现interrupt.h:interrupt.h:main.h:main.h: 四、完成效果五、总结 前言 无 一、题目 二、模块初始化 1.LCD这里不用配置&#xff0c;直接使用提供的资源包就行 2.ADC:开启ADCsingle-ended 3.LED:开启PC8-15,PD2输出模式就行了…

手撕代码——同步FIFO

手撕代码——同步FIFO 一、FIFO原理与设计二、完整代码与仿真结果三、仿真结果 一、FIFO原理与设计 查看Xilinx官方FIFO IP核&#xff0c;其主要的信号有时钟信号、写端口信号、读端口信号&#xff0c;其中&#xff0c;写端口信号包括写满信号full、写使能信号wr_en、写数据输入…

[元带你学: eMMC完全解读 7] eMMC 设备与系统概述

依JEDEC eMMC 5.1及经验辛苦整理,付费内容,禁止转载。 所在专栏 《元带你学: eMMC完全解读》 前言 全文3600 字, 全文介绍eMMC 内部系统框架, Bus 总线宽度, 总线Speed Mode, 了解即可。对应Bus 总线重点看 8 Bit 即可, Speed Mode 重点看 HS400。几乎所有的系统都是跑在…

Java并发编程-synchronized

目录 1. synchronized在jdk 1.6中的优化 1.1 锁消除 1.2 锁粗化 1.2 锁升级/锁膨胀 1.2.1 锁升级原理 1.2.2 自适应自旋锁 2. synchronized实现原理 3. synchronized和Lock的对比 1. synchronized在jdk 1.6中的优化 在JDK1.5的时候,Doug Lee推出了ReentrantLock,lock的…

【密码学复习】第九讲 密钥管理(一)

密钥管理简介 • 柯克霍夫斯原则(Kerckhoffs Principle) 即使密码系统的任何细节已为人悉知&#xff0c;只要密钥未泄漏&#xff0c;它也应是安全的(19世纪). 密钥安全&#xff1a;三分技术&#xff0c;七分管理 密钥管理就是在授权各方之间实现密钥关系的建立和维护…

dom4j 读取xml配置文件,根据配置文件利用反射创建对象

pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 …

maven打包命令打出的可执行的jar包和可依赖的jar包的区别

目录 引出问题: 介绍打包插件 下面开始打包: 解压比较这两个jar包的区别: 引出问题: 当我建了一个maven的springboot项目A写了一个工具类,我把A项目打包成jar包去给B项目用,结果 B项目报错找不到这个jar包. 百度后发现原来jar包分为可执行jar包和可被依赖的jar包 介绍打包…

二、医院设置管理

文章目录 一、医院设置管理1、项目开发流程1.1 定义路由模块1.2 定义api模块1.3 定义页面组件脚本1.4 定义页面组件模板1.5 测试数据通信1.6 跨域处理 2、分页查询2.1 定义页面组件脚本2.2 定义页面组件模板2.3 表单查询 3、删除3.1 定义api模块3.2 定义页面组件模板3.3 定义页…

Midjourney|文心一格prompt教程[进阶篇]:Midjourney Prompt 高级参数、各版本差异、官方提供常见问题

Midjourney|文心一格prompt教程[进阶篇]&#xff1a;Midjourney Prompt 高级参数、各版本差异、官方提供常见问题 1.Midjourney Prompt 高级参数 Quality 图片质量是另一个我比较常用的属性&#xff0c;首先需要注意这个参数并不影响分辨率&#xff0c;并不改变分辨率&#x…

【C++】实现一个日期计算器

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;命运给你一个低的起点&#xff0c;是想看你精彩的翻盘&#xff0c;而不是让你自甘堕落&#xff0c;脚下的路虽然难走&#xff0c;但我还能走&#xff0c;比起向阳而生&#xff0c;我更想尝试逆风…