1、依賴包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>1.5.2.RELEASE</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
2、redis 工具類
@Component
public class RedisStringUtil {
/**
* 注入Redis字符串模板
*/
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 設置值
*
* @param key 鍵
* @param value 值
*/
public void set(String key, String value) {
this.redisTemplate.opsForValue().set(key, value);
}
/**
* 當前的值 + 1
*
* @param key 鍵
* @return 返回操作之後的值
*/
public Long increment(String key) {
return this.redisTemplate.opsForValue().increment(key, 1);
}
/**
* 當前的值加 + value
*
* @param key 鍵
* @param value 值
* @return 返回操作之後的值
*/
public Long incrementBy(String key, long value) {
return this.redisTemplate.opsForValue().increment(key, value);
}
/**
* 當前的值 - 1
*
* @param key 鍵
* @return 返回操作之後的值
*/
public Long descend(String key) {
return this.redisTemplate.opsForValue().increment(key, -1);
}
/**
* 當前的值 - value
*
* @param key 鍵
* @return 返回操作之後的值
*/
public Long descendBy(String key, long value) {
return this.redisTemplate.opsForValue().increment(key, -Math.abs(value));
}
/**
* 設置值
*
* @param key 鍵
* @param value 值
* @param timeout 超時(秒)
*/
public void set(String key, String value, long timeout) {
this.redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
}
/**
* 設置值
*
* @param key 鍵
* @param value 值
* @param timeout 超時時間
* @param timeout 超時時間單位
*/
public void set(String key, String value, long timeout, TimeUnit timeUnit) {
this.redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
/**
* 獲取值
*
* @param key 鍵
* @return 獲取值
*/
public String get(String key) {
return this.redisTemplate.opsForValue().get(key);
}
/**
* 刪除
*
* @param key 健
*/
public void delete(String key) {
this.redisTemplate.delete(key);
}
/**
* 當不存在的時候設置值,
*
* @param key 鍵
* @param value 值
* @param expireSeconds 超時時間(單位 秒)
* @return 成功 返回 OK
*/
public boolean setIfNotExists(String key, String value, long expireSeconds) {
return this.setIfNotExists(key, value, expireSeconds, TimeUnit.SECONDS);
}
/**
* 當不存在的時候設置值,
*
* @param key 鍵
* @param value 值
* @param expire 超時時間
* @param timeUnit 超時單位
* @return 成功 返回 OK
*/
public boolean setIfNotExists(String key, String value, long expire, TimeUnit timeUnit) {
final long finalExpire = this.getExpireSeconds(expire, timeUnit);
String status = this.redisTemplate.execute((RedisCallback<String>) connection -> {
Object nativeConnection = connection.getNativeConnection();
if (nativeConnection instanceof JedisCluster) {
JedisCluster jedisCluster = (JedisCluster) nativeConnection;
// 只有可以不存在是才設置,並且設置超時時間
return jedisCluster.set(key, value, "nx", "ex", finalExpire);
} else {
Jedis jedis = (Jedis) nativeConnection;
// 只有可以不存在是才設置,並且設置超時時間
return jedis.set(key, value, "nx", "ex", finalExpire);
}
});
if (StringUtils.isEmpty(status)) {
return false;
} else {
return "OK".equals(status);
}
}
/**
* 時間轉換 轉爲 秒
*
* @param expire 時間
* @param timeUnit 單號
* @return 返回 秒
*/
private long getExpireSeconds(long expire, TimeUnit timeUnit) {
//1秒(s) =100釐秒(cs)= 1000 毫秒(ms) = 1,000,000 微秒(μs)
// = 1,000,000,000 納秒(ns) = 1,000,000,000,000 皮秒(ps)
//=1,000,000,000,000,000飛秒(fs)=1,000,000,000,000,000,000仄秒(zs)
// =1,000,000,000,000,,000,000,000幺秒(ys)=1,000,000,000,000,000,000,000,000渺秒(as)
switch (timeUnit) {
case DAYS:
expire = expire * 24 * 60 * 60;
break;
case HOURS:
expire = expire * 60 * 60;
break;
case MINUTES:
expire = expire * 60;
break;
case MILLISECONDS:
expire = expire / 10 ^ 3;
break;
case MICROSECONDS:
expire = expire / 10 ^ 6;
break;
case NANOSECONDS:
expire = expire / 10 ^ 9;
break;
default:
break;
}
return expire;
}
}
3、redis 分佈鎖實現類
@Component
public class RedisLock {
/**
* redis操作的類
*/
@Autowired
private RedisStringUtil redisStringUtil;
/**
* 加鎖的值
*/
private static final String LOCK_VALUE = "TRUE";
/**
* 默認超時時間 10s
*/
private static final int TIME = 10;
/**
* 鎖的前綴,命名空間
*/
private static final String PREFIX = "LOCKS:";
/**
* 加鎖
*
* @param key 鍵
*/
public boolean lock(String key) {
return this.redisStringUtil.setIfNotExists(PREFIX.concat(key), LOCK_VALUE, TIME);
}
/**
* 加鎖,有超時時間(建議)
* 避免解鎖失敗導致死鎖
*
* @param key 鍵
* @param time 超時時間(默認 秒)
*/
public boolean lock(String key, long time) {
return this.redisStringUtil.setIfNotExists(PREFIX.concat(key), LOCK_VALUE, time);
}
/**
* 加鎖,有超時時間(建議)
* 避免解鎖失敗導致死鎖
*
* @param key 鍵
* @param time 超時時間
* @param unit 超時單位
*/
public boolean lock(String key, long time, TimeUnit unit) {
return this.redisStringUtil.setIfNotExists(PREFIX.concat(key), LOCK_VALUE, time, unit);
}
/**
* 解鎖
*
* @param key 鍵
*/
public void unlock(String key) {
this.redisStringUtil.delete(PREFIX.concat(key));
}
4、使用方式
@Autowired
private RedisLock redisLock;
public void test() {
String key = "lock_";
if (this.redisLock.lock(key)) {
try {// 需要加鎖的代碼塊
} finally {
this.redisLock.unlock(key);
}
}
}