SpringBoot集成redis實現(xiàn)分布式鎖的示例代碼
1、準備
使用redis實現(xiàn)分布式鎖,需要用的setnx(),所以需要集成Jedis
需要引入jar,jar最好和redis的jar版本對應(yīng)上,不然會出現(xiàn)版本沖突,使用的時候會報異常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、配置參數(shù)
spring: redis: host: localhost port: 6379 password: root timeout: 5000 # Redis數(shù)據(jù)庫索引(默認為0) database: 0 # 連接池最大連接數(shù)(使用負值表示沒有限制) jedis: pool: # 連接池最大連接數(shù)(使用負值表示沒有限制) 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("=====創(chuàng)建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 { //方案一,具有原子性,并且可以設(shè)置過期時間,避免拿到鎖后,業(yè)務(wù)代碼出現(xiàn)異常,無法釋放鎖 String result = jedis.set(lockKey, lockValue, new SetParams().nx().ex(expireTime)); if (LOCK_SUCCESS.equals(result)) { return true; } return false; //方案二,setnx()具有原子性,但是有后續(xù)判斷,整體不具有原子性,不能設(shè)置過期時間 // //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()){ // //鎖超時,可以獲取鎖重新設(shè)置鎖 // //計算 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); } } /** * 關(guān)閉資源 * @param jedis */ public static void returnResource(final Jedis jedis){ if(null != jedis){ jedis.close(); } } }
到此這篇關(guān)于SpringBoot集成redis實現(xiàn)分布式鎖的示例代碼的文章就介紹到這了,更多相關(guān)SpringBoot redis分布式鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解在springboot中使用Mybatis Generator的兩種方式
這篇文章主要介紹了詳解在springboot中使用Mybatis Generator的兩種方式,本文將介紹到在springboot的項目中如何去配置和使用MBG以及MBG生成代碼的兩種方式,非常具有實用價值,需要的朋友可以參考下2018-11-11jeefast和Mybatis實現(xiàn)三級聯(lián)動的示例代碼
這篇文章主要介紹了jeefast和Mybatis實現(xiàn)三級聯(lián)動的示例代碼,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-10-10Spring Security 和Apache Shiro你需要具備哪些條件
這篇文章主要介紹了Spring Security 和Apache Shiro你需要具備哪些條件,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07Spring Cloud Feign請求添加headers的實現(xiàn)方式
這篇文章主要介紹了Spring Cloud Feign請求添加headers的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04