Redis分布式锁的使用案例

一、引入依赖

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.5.0</version>
</dependency>

二、工具类 

package com.hl.redisdemo.util;import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;import java.util.Collections;public class RedissonLockUtil {private static final Jedis jedis = new Jedis("localhost", 6379);/*** 可重入锁加锁* @param lockKey 锁的key* @param requestId 请求标识* @param expireTime 超时时间* @return 是否成功获取锁*/public static boolean lock(String lockKey, String requestId, int expireTime) {SetParams params = new SetParams();params.nx().px(expireTime); // 设置nx和px参数,保证只在不存在该key时设置值,并设置过期时间String result = jedis.set(lockKey, requestId, params);return "OK".equalsIgnoreCase(result);}/*** 可重入锁解锁* @param lockKey 锁的key* @param requestId 请求标识* @return 是否成功释放锁*/public static boolean unlock(String lockKey, String requestId) {String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";Object result = jedis.eval(luaScript, Collections.singletonList(lockKey), Collections.singletonList(requestId));Long RELEASE_SUCCESS = 1L;return RELEASE_SUCCESS.equals(result);}/*** 获取可重入锁* @param lockKey 锁的key* @param requestId 请求标识* @param expireTime 超时时间* @return 是否成功获取锁*/public static boolean tryLock(String lockKey, String requestId, int expireTime) {SetParams params = new SetParams();params.nx().px(expireTime); // 设置nx和px参数,保证只在不存在该key时设置值,并设置过期时间String result = jedis.set(lockKey, requestId, params);return "OK".equalsIgnoreCase(result);}
}

 三、测试代码

package com.hl.redisdemo.controller;import com.hl.redisdemo.util.RedissonLockUtil;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.UUID;/*** @author hulei* @date 2024/2/6 17:23*/@RestController
public class RedisDemoController {@RequestMapping("/redisTest")public String redisTest() throws InterruptedException {String str;String lockKey = "myLock";String requestId = UUID.randomUUID().toString(); // 生成唯一请求标识// 集群场景下,锁超时时间应该保证大于多数节点获取锁的时间//当发生在多数节点获取锁的时间大于锁超时时间时,获取到的锁在各节点早已超时失效,锁失效int expireTime = 5000; // 锁的过期时间为5秒,注意,// 尝试获取锁if (RedissonLockUtil.tryLock(lockKey, requestId, expireTime)) {System.out.println("获取到锁");// 执行业务逻辑Thread.sleep(1000);// 释放锁if (RedissonLockUtil.unlock(lockKey, requestId)) {System.out.println("释放锁成功");str = "释放锁成功";} else {System.out.println("释放锁失败");str = "释放锁失败";}} else {System.out.println("获取锁失败");str = "获取锁失败";}return str;}
}

测试结果分析:

1.正常测试结果

 

正常匀速点击请求,每次等之前的请求完成后释放锁,后面的请求则能够正常获取锁

2.异常测试结果 :

如果点击速度过快,之前的请求业务逻辑没有执行完,锁还未释放,后面的请求获取锁时,则提示锁获取失败,这样就保证了业务执行的顺序性,正确性。使用场景 如防止订单超卖,库存扣减等

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

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

相关文章

学习Android的第四天

目录 Android FrameLayout ( 帧布局 ) FrameLayout size 大小 FrameLayout 属性 Android GridLayout ( 网格布局 ) GridLayout 属性 计算器布局 Android AbsoluteLayout 绝对布局 AbsoluteLayout 四大控制属性 Android FrameLayout ( 帧布局 ) FrameLayout 是 Android…

K210开发板开箱介绍

一、正面有一个电容触摸屏 二、左上角是一个Type-C接口&#xff0c;可用来供电以及下载程序 三、右上角是一个三向的拨动开关&#xff0c;分别是向左、向右、向下三个通道 四、右侧这个是复位按键 五、这部分是wifi模块的一个串口以及按键 六、wifi模块在开发板的背面&#xff…

板块零 IDEA编译器基础:第三节 下载和在IDEA中集成 Tomcat服务器 来自【汤米尼克的JAVAEE全套教程专栏】

板块零 IDEA编译器基础&#xff1a;第三节 下载和在IDEA中集成 Tomcat服务器 一、为什么选择Tomcat&#xff08;1&#xff09;常见的JAVA WEB服务器&#xff08;2&#xff09;选择Tomcat的理由 二、Tomcat 8.5下载解压三、Tomcat 结构目录四、在IDEA中集成Tomcat 假设我们已经…

day06-Flex布局

01-标准流 标准流也叫文档流&#xff0c;指的是标签在页面中默认的排布规则&#xff0c;例如&#xff1a;块元素独占一行&#xff0c;行内元素可以一行显示多个。 02-浮动 基本使用 作用&#xff1a;让块元素水平排列。 属性名&#xff1a;float 属性值 left&#xff1a;左…

【element-ui】el-select下拉框el-date-picker弹出框定位问题解决方案

问题描述&#xff1a; 项目开发过程中发现el-select和el-date-picker弹出框显示时候&#xff0c;滚动屏幕&#xff0c;导致弹出框定位出现问题。 首先考虑到看一下element-ui官网提供的api&#xff0c;如下图 1、select提供了popper-append-to-body属性的配置 代码如下&#x…

【lesson44】进程间通信之匿名管道

文章目录 理解进程通信管道理解使用管道1.创建管道2.fork创建子进程3.构建单向通信信道子进程构建通信父进程构建通信 使用管道的完整版代码扩展Task.hppProcessPool.cc 理解进程通信 进程运行具有独立性—>进程想通信&#xff0c;难度其实是比较大的---->进程通信的本质…

DFS——剪枝

dfs在每个点&#xff08;状态&#xff09;的情况比较多&#xff0c;但是节点比较少的时候很常用&#xff0c;我们将每个状态的情况延伸出去&#xff0c;可以画出一棵搜索树。dfs会搜到每一种情况&#xff0c;所以我们实际上可以按照任意顺序来判否。为了优化搜索我们可以在搜索…

喵的一下午(分享今天的趣事)

2024/2/7 晚 喵喵我呀&#xff0c;起的很晚。又没有敲算法。于是&#xff0c;今天就没法发CSDN了。 每天&#xff0c;我还是特别喜欢看阅读量增加没&#xff0c;有没有人点赞&#xff0c;或者说添加收藏&#xff0c;当然&#xff0c;如果又多一个关注的朋友&#xff0c…

数据结构——单链表详解

目录 前言 一.什么是链表 1.概念 ​编辑 2.分类 二.单链表的实现(不带头单向不循环链表) 2.1初始化 2.2打印 2.3创建新节点 2.4头插、尾插 2.5头删、尾删 2.6查找 2.7在指定位置之前插入 2.8在指定位置之后插入 2.9删除pos位置 2.10删除pos之后的 2.11销毁链表…

《java 从入门到放弃》1.1 jdk 安装

1.jdk 是啥&#xff1f; jdk&#xff08;Java Development Kit&#xff09;&#xff0c;简单来说&#xff0c;就是java的开发工具。允许java 程序就是用它了。 jre &#xff0c;里面放的是java用的那些公用的包。 2.jdk下载 2.1 官网下载地址&#xff1a;Java Downloads | …

32USART串口

目录 一.通信接口 二.时序 三.USART简介 ​编辑四.数据帧 五.起始位侦测和采样位置对齐 &波特率计算 六.相关函数 七.编码格式设置 &#xff08;1&#xff09; UTF-8编码&#xff08;有的软件兼容性不好&#xff09;​编辑 &#xff08;2&#xff09;GB2312编码 八.…

【python数据分析基础】—dataframe中index的相关操作(添加、修改index的列名、修改index索引值等)

文章目录 前言一、添加、修改index的列名二、修改index索引值 前言 本文主要讲dataframe结构中index的相关操作&#xff0c;index相当于是数据表的行。 一、添加、修改index的列名 新建一个dataframe表&#xff0c;我们可以自定义index的值&#xff0c;如下&#xff1a; imp…

SSL协议是什么?关于SSL和TLS的常见问题解答

SSL&#xff08;安全套接字层&#xff09;及其后继者TLS&#xff08;传输层安全&#xff09;是用于在联网计算机之间建立经过身份验证和加密的链接的协议。尽管SSL协议在 1999年已经随着TLS 1.0的发布而被弃用&#xff0c;但我们仍将这些相关技术称为“SSL”或“SSL/TLS”。那么…

Instagram SEO如何优化?10个技巧

Instagram SEO 是优化 Instagram 内容以使其在平台搜索结果中被发现的做法。如果你希望你可以更快的让你的Ins获得流量&#xff0c;做好SEO就成功了一半。Instagram 搜索结果包括相关内容、帐户、音频、主题标签和地点&#xff0c;下面为你总结10个策略技巧&#xff01; 一、In…

解析spritf和sscanf与模拟常用字符串函数strchr,strtok(二)

今天又来继续我们的字符串函数的文章&#xff0c;这也是最后一篇了。希望这两篇文章能让各位理解透字符串函数。 目录 strchr strtok sprintf和sscanf strchr strchr 是一个用于在字符串中查找特定字符首次出现位置的函数。以下是解析和模拟实现 strchr 函数的示例&…

【Linux】信号-下

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;【LeetCode】winter vacation training 目录 &#x1f449;&#x1f3fb;信号递达&#xff0c;信号未决&#x…

vue3学习——自定义插件,注册组件(引入vue文件报红线)

在src/components文件夹目录下创建一个index.ts文件 import { App, Component } from Vue import SvgIcon from /components/SvgIcon/index.vue import Pagination from /components/Pagination/index.vue const globalComponents: { [name: string]: Component } { SvgIcon,…

第三模块 面向对象网络并发编程

第三模块 面向对象&网络&并发编程 面向对象基础1. 初识面向对象1.1 对象和self1.2 常见成员1.3 应用示例 2. 三大特性2.1 封装2.2 继承练习题2.3 多态 3. 扩展&#xff1a;再看数据类型总结作业 从今天开始&#xff0c;我们将进入系列课程第3个模块的的学习&#xff0c…

TCP和UDP相关问题(重点)(5)——5.TCP三次握手和四次挥手(非常重要)

5.1三次握手的过程 一次握手&#xff1a;客户端发送带有SYN(x)标志的数据包到服务端&#xff0c;然后客户端进入SYN_SEND状态&#xff0c;等待服务器端的确认。 二次握手&#xff1a;服务端发送带有SYN(y)ACK(x1)标志的数据包到客户端&#xff0c;然后服务端进入SYN_RECV状态。…

Java设计模式大全:23种常见的设计模式详解(三)

本系列文章简介&#xff1a; 设计模式是在软件开发过程中&#xff0c;经过实践和总结得到的一套解决特定问题的可复用的模板。它是一种在特定情境中经过验证的经验和技巧的集合&#xff0c;可以帮助开发人员设计出高效、可维护、可扩展和可复用的软件系统。设计模式提供了一种在…