软件编程
位置:首页>> 软件编程>> java编程>> SpringBoot集成redis实现分布式锁的示例代码

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

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com