SpringBoot集成redis实现分布式锁的示例代码

网友投稿 387 2022-11-05


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版本是2lnFKAZZOI.3.0,Jedis使用的是3.3.0

redis.clients

jedis

3.3.0

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();

}

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:hs查询API(hs代码查询网)
下一篇:vscode 插件连接 mysql-Client does not support authentication protocol requested by server
相关文章

 发表评论

暂时没有评论,来抢沙发吧~