pom依賴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.2</version>
</dependency>
</dependencies>
application.properties配置
#redis 配置
# Redis數據庫索引(默認爲0)
spring.redis.database=0
# Redis服務器地址
spring.redis.host=192.168.252.128
# Redis服務器連接端口
spring.redis.port=6379
# Redis服務器連接密碼(默認爲空)
spring.redis.password=123456
# 連接池最大連接數(使用負值表示沒有限制)
spring.redis.jedis.pool.max-active=200
# 連接池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.jedis.pool.max-wait=-1
# 連接池中的最大空閒連接
spring.redis.jedis.pool.max-idle=8
# 連接池中的最小空閒連接
spring.redis.jedis.pool.min-idle=0
# 連接超時時間(毫秒)
spring.redis.timeout=0
#spring-session 使用
spring.session.store-type=none
配置類
package com.example.demoredis.conf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
@Configuration
public class RedisConfig {
private Logger logger = LoggerFactory.getLogger(RedisConfig.class);
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout;
@Value("${spring.redis.jedis.pool.max-active}")
private int maxActive;
@Value("${spring.redis.jedis.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.jedis.pool.min-idle}")
private int minIdle;
@Value("${spring.redis.jedis.pool.max-wait}")
private long maxWaitMillis;
@Bean
public JedisPool redisPoolFactory() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
jedisPoolConfig.setMaxTotal(maxActive);
jedisPoolConfig.setMinIdle(minIdle);
JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password);
logger.info("JedisPool注入成功!");
logger.info("redis地址:" + host + ":" + port);
return jedisPool;
}
}
測試代碼:
package com.example.demoredis;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.UUID;
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoRedisApplicationTests {
@Resource
private JedisPool jedisPool;
/**
* @description 分佈式鎖測試
* @date 14:57 2019/9/17
**/
@Test
public void contextLoads() {
Jedis jedis = jedisPool.getResource();
String ping = jedis.ping();
System.out.println("================================jedis連接:" + ping);
/*System.out.println(lock(jedis, "a", "1", 60L));
System.out.println(jedis.get("a"));
System.out.println(unLock(jedis, "a", "2"));*/
String key = "aaa";
String value = UUID.randomUUID().toString().replaceAll("-", "");
// 鎖定過期時間 s
Long lockTime = 60L;
// 嘗試次數
Integer tryCount = 20;
// 每次嘗試休閒時間 ms
Long trySleepTime = 1500L;
// 業務代碼執行時間 s
Integer serSecond = 30;
Boolean lock = false;
try {
lock = lockRetry(jedis, key, value, lockTime, tryCount, trySleepTime);
if (lock) {
System.out.println("鎖定成功-------------------------");
System.out.println("業務代碼執行.......................................");
for (int i = 0; i < serSecond; i++) {
System.out.println(" ... " + (i + 1));
Thread.sleep(1000L);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (lock) {
Boolean unLock = unLock(jedis, key, value);
if (unLock) {
System.out.println("解鎖成功-------------------------");
} else {
System.out.println("解鎖失敗-------------------------");
}
}
}
System.out.println("================= 關閉連接 ==================");
jedis.close();
}
/**
* @description 重試去獲取鎖(鎖定)
* 參數:jedis,k,v, 過期時間,重試次數,每次重試休眠時間
* @date 14:58 2019/9/17
**/
public Boolean lockRetry(Jedis jedis, String key, String value, Long timeOut, Integer retry, Long sleepTime) {
Boolean flag = false;
try {
for (int i = 0; i < retry; i++) {
flag = lock(jedis, key, value, timeOut);
System.out.println("重試" + (i + 1) + "次....... " + key + " -> " + value);
if (flag) {
System.out.println("成功獲取鎖--------");
break;
}
Thread.sleep(sleepTime);
}
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
/**
* @description 加鎖
* 參數:jedis,k,v,過期時間
* @date 15:05 2019/9/17
**/
public Boolean lock(Jedis jedis, String key, String value, Long timeOut) {
// 保證原子性,同一時間只能一個key,並且不能被覆蓋:NX:如果存在不操作(返回null), EX:超時時間單位秒
String result = jedis.set(key, value, "NX", "EX", timeOut);
// 操作成功時返回"OK"
return "OK".equals(result);
}
/**
* @description 解鎖
* 參數:jedis,k,v
* @date 15:06 2019/9/17
**/
public static Boolean unLock(Jedis jedis, String key, String value) {
// 如果k,v對存在 刪除,如果k,v不存在不刪除,(使用腳本可以保證操作的原子性)
String luaScript = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then return redis.call(\"del\",KEYS[1]) else return 0 end";
Long result = (Long) jedis.eval(luaScript, Collections.singletonList(key), Collections.singletonList(value));
return Long.valueOf(1).equals(result);
}
}