SpringBoot集成redis实现分布式锁的示例代码
作者:菜小菜吃菜 发布时间:2022-08-24 19:21:56
标签:SpringBoot,redis,分布式锁
1、准备
使用redis实现分布式锁,需要用的setnx(),所以需要集成Jedis
需要引入jar,jar最好和redis的jar版本对应上,不然会出现版本冲突,使用的时候会报异常redis.clients.jedis.Jedis.set(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/String;
我使用的redis版本是2.3.0,Jedis使用的是3.3.0
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.3.0</version>
</dependency>
2、配置参数
spring:
redis:
host: localhost
port: 6379
password: root
timeout: 5000
# Redis数据库索引(默认为0)
database: 0
# 连接池最大连接数(使用负值表示没有限制)
jedis:
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: 8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
# 连接池中的最大空闲连接
max-idle: 8
# 连接池中的最小空闲连接
min-idle: 0
# 获取连接时检测是否可用
testOnBorrow: true
3、配置JedisPool
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* Jedis配置项
* @autho ConnorSong
* @date 2021/1/21 9:55 上午
*/
@Configuration
@Slf4j
public class JedisPoolCinfigration {
@Bean
public JedisPoolConfig jedisPoolConfig(@Value("${spring.redis.jedis.pool.max-active}") int maxActive,
@Value("${spring.redis.jedis.pool.max-idle}") int maxIdle,
@Value("${spring.redis.jedis.pool.min-idle}") int minIdle,
@Value("${spring.redis.jedis.pool.max-wait}") long maxWaitMillis,
@Value("${spring.redis.jedis.pool.testOnBorrow}") boolean testOnBorrow) {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(maxActive);
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMinIdle(minIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
jedisPoolConfig.setTestOnBorrow(testOnBorrow);
return jedisPoolConfig;
}
@Bean
public JedisPool jedisPool(@Value("${spring.redis.host}") String host,
@Value("${spring.redis.password}") String password,
@Value("${spring.redis.port}") int port,
@Value("${spring.redis.timeout}") int timeout, JedisPoolConfig jedisPoolConfig) {
log.info("=====创建JedisPool连接池=====");
if (StringUtils.isNotEmpty(password)) {
return new JedisPool(jedisPoolConfig, host, port, timeout, password);
}
return new JedisPool(jedisPoolConfig, host, port, timeout);
}
}
4、分布式锁工具类
import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;
import java.util.Collections;
/**
* jedis分布式锁工具类
* @autho ConnorSong
* @date 2021/1/20 6:26 下午
*/
@Slf4j
public class JedisLockUtils {
private static final String LOCK_SUCCESS = "OK";
private static final Long RELEASE_SUCCESS = 1L;
/**
* 尝试获取分布式锁
* @param jedis Redis客户端
* @param lockKey 锁
* @param lockValue value
* @param expireTime 超期时间(秒)
* @return 是否获取成功
*/
public static boolean tryGetLock(Jedis jedis, String lockKey, String lockValue, int expireTime) {
log.info("----获取Jedis分布式锁----lockKey:{}", lockKey);
try {
//方案一,具有原子性,并且可以设置过期时间,避免拿到锁后,业务代码出现异常,无法释放锁
String result = jedis.set(lockKey, lockValue, new SetParams().nx().ex(expireTime));
if (LOCK_SUCCESS.equals(result)) {
return true;
}
return false;
//方案二,setnx()具有原子性,但是有后续判断,整体不具有原子性,不能设置过期时间
// //setnx(lockkey, 当前时间+过期超时时间),如果返回 1,则获取锁成功;如果返回 0 则没有获取到锁
// String value = new Date().getTime() + expireTime + "";
// if(1 == jedis.setnx(lockKey, value)){
// return true;
// }else{
// String oldExpireTime = jedis.get(lockKey);
// if(Long.valueOf(oldExpireTime)< new Date().getTime()){
// //锁超时,可以获取锁重新设置锁
// //计算 newExpireTime = 当前时间+过期超时时间,然后 getset(lockkey, newExpireTime) 会返回当前 lockkey的值currentExpireTime
// long newExpireTime = new Date().getTime() + expireTime;
// String currentExpireTime = jedis.getSet(lockKey, newExpireTime + "");
// if(currentExpireTime.equals(oldExpireTime)){
// return true;
// }
// }
// return false;
// }
}finally {
returnResource(jedis);
}
}
/**
* 释放分布式锁
* @param jedis Redis客户端
* @param lockKey 锁
* @return 是否释放成功
*/
public static boolean closeLock(Jedis jedis, String lockKey, String lockValue) {
log.info("----释放Jedis分布式锁----lockKey:{}, lockValue:{}", lockKey, lockValue);
try {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(lockValue));
if (RELEASE_SUCCESS.equals(result)) {
return true;
}
return false;
}finally {
returnResource(jedis);
}
}
/**
* 关闭资源
* @param jedis
*/
public static void returnResource(final Jedis jedis){
if(null != jedis){
jedis.close();
}
}
}
来源:https://blog.csdn.net/qq_37252429/article/details/112950797


猜你喜欢
- 今天写程序的时候用到了附加属性,我是用VS内置的propa的代码段来实现的,代码如下:class Attach {
- 本文实例为大家分享了unity利用图片来生成字体的具体代码,供大家参考,具体内容如下开发中,可能会用到需要将图片转换成字体的需求。BMFON
- 局限性只支持MP4文件经过尝试对于一些MP4文件分割不了依赖<!-- mp4文件操作jar --><!-- https:/
- 本文实例讲述了Android开发之DatePicker和TimePicker实现选择日期时间功能。分享给大家供大家参考,具体如下:DateP
- 条码的应用已深入生活和工作的方方面面。在处理条码时,常需要和各种文档格式相结合。当需要在文档中插入、编辑或者删除条码时,可借助于一些专业的类
- 使用zxing批量在做好的立牌背景图的指定位置上,把指定的文本内容(链接地址、文本等)生成二维码并放在该位置,最后加上立牌编号。步骤:1).
- engine的实现结构elasticsearch对于索引中的数据操作如读写get等接口都封装在engine中,同时engine还封装了索引的
- 之前的一篇文章中的代码中有一个using的用法,刚开始查看了一些资料说是强制关闭对象的一个命令。今天又查了一些资料,才明白,原来using指
- 前言本次示例代码的文件结构如下图所示。1. 导入依赖坐标在 order-service 的 pom.xml 文件中导入 Feign 的依赖坐
- 本文实例讲述了C#创建、读取和修改Excel的方法。分享给大家供大家参考。具体如下:windows下我们可以通过 Jet OLE DB访问E
- java中的JsonSerializer用法背景今天在写项目的时候遇到一个问题,项目中有个类中有创建时间和更新时间两个属性,但是单位在后端用
- 本文实例为大家分享了Android自定义控件实现时间轴的具体代码,供大家参考,具体内容如下由于项目中有需求,就简单的封装一个,先记录一下,有
- Collections工具类Java里关于聚合的工具类,包含有各种有关集合操作的静态多态方法,不能实例化(把构造函数私有化)public c
- AndroidStudio kotlin配置安装插件File -> Settings -> Plugins -> Brow
- 主要介绍Android中如何使用rotate实现图片不停旋转的效果。Android 平台提供了两类动画,一类是 Tween 动画,即通过对场
- 前言这几天正在看Android官方的开发文档,里面有很多很值得思考的开发建议,有时间的朋友可以去看一下(官方是英文文档,如果看不懂可以通过浏
- Android ScrollView无法填充满屏幕的解决办法ScrollView滚动视图是指当拥有很多内容、屏幕显示不完时、需要通过滚动跳来
-   利用 springboot + redis 实现过滤重复提交的请求,业务流程如下所示,首先定义一个拦
- 将int数组转化为Integer数组这里使用java8的stream来进行转化,详细步骤如下所示://初始化int数组int[] nums
- 视图绑定通过视图绑定功能,您可以更轻松地编写可与视图交互的代码。在模块中启用视图绑定之后,系统会为该模块中的每个 XML 布局文件生成一个绑