1、依賴包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
2、分佈式鎖
import com.zto.ztrace.util.RedisStringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public class RedisLock {
/**
* redis操作的類
*/
@Autowired
private RedisStringUtil redisStringUtil;
/**
* 加鎖的值
*/
private static final String LOCK_VALUE = "TRUE";
/**
* 默認超時時間 3000ms
*/
private static final int TIME = 3000;
/**
* 鎖的前綴,命名空間
*/
private static final String PREFIX = "LOCKS:";
/**
* 加鎖
*
* @param key 鍵
* @return 返回是否允許執行
*/
public boolean lock(final String key) {
return this.redisStringUtil.setIfNotExists(RedisLock.PREFIX.concat(key), RedisLock.LOCK_VALUE, RedisLock.TIME);
}
/**
* 加鎖,有超時時間(建議) 避免解鎖失敗導致死鎖
*
* @param key 鍵
* @param expireMilliSeconds 超時時間(默認 耗秒)
* @return 返回是否允許執行
*/
public boolean lock(final String key, final long expireMilliSeconds) {
return this.redisStringUtil.setIfNotExists(RedisLock.PREFIX.concat(key), RedisLock.LOCK_VALUE, expireMilliSeconds);
}
/**
* 加鎖,有超時時間(建議) 避免解鎖失敗導致死鎖
*
* @param key 鍵
* @param time 超時時間
* @param unit 超時單位
* @return 返回是否允許執行
*/
public boolean lock(final String key, final long time, final TimeUnit unit) {
return this.redisStringUtil.setIfNotExists(RedisLock.PREFIX.concat(key), RedisLock.LOCK_VALUE, time, unit);
}
/**
* 解鎖 this.redisStringUtil.set(PREFIX.concat(key), LOCK_VALUE, 5, TimeUnit.MILLISECONDS);
*
* @param key 鍵
*/
public void unlock(final String key) {
this.redisStringUtil.delete(RedisLock.PREFIX.concat(key));
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public class RedisStringUtil {
/**
* 注入Redis字符串模板
*/
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 設置值
*
* @param key 鍵
* @param value 值
*/
public void set(final String key, final String value) {
this.redisTemplate.opsForValue().set(key, value);
}
/**
* 當前的值 + 1
*
* @param key 鍵
* @return 返回操作之後的值
*/
public Long increment(final String key) {
return this.redisTemplate.opsForValue().increment(key, 1);
}
/**
* 當前的值加 + value
*
* @param key 鍵
* @param value 值
* @return 返回操作之後的值
*/
public Long incrementBy(final String key, final long value) {
return this.redisTemplate.opsForValue().increment(key, value);
}
/**
* 當前的值 - 1
*
* @param key 鍵
* @return 返回操作之後的值
*/
public Long descend(final String key) {
return this.redisTemplate.opsForValue().increment(key, -1);
}
/**
* 當前的值 - value
*
* @param key 鍵
* @return 返回操作之後的值
*/
public Long descendBy(final String key, final long value) {
return this.redisTemplate.opsForValue().increment(key, -Math.abs(value));
}
/**
* 設置值
*
* @param key 鍵
* @param value 值
* @param timeout 超時(秒)
*/
public void set(final String key, final String value, final long timeout) {
this.redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
}
/**
* 設置值
*
* @param key 鍵
* @param value 值
* @param timeout 超時時間
* @param timeout 超時時間單位
*/
public void set(final String key, final String value, final long timeout, final TimeUnit timeUnit) {
this.redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
/**
* 獲取值
*
* @param key 鍵
* @return 獲取值
*/
public String get(final String key) {
return this.redisTemplate.opsForValue().get(key);
}
/**
* 刪除
*
* @param key 健
*/
public void delete(final String key) {
this.redisTemplate.delete(key);
}
/**
* 當不存在的時候設置值,
*
* @param key 鍵
* @param value 值
* @param expireMilliSeconds 超時時間(單位 毫秒)
* @return 成功 返回 OK
*/
public boolean setIfNotExists(final String key, final String value, final long expireMilliSeconds) {
return this.setIfNotExists(key, value, expireMilliSeconds, TimeUnit.MILLISECONDS);
}
/**
* 當不存在的時候設置值,
*
* @param key 鍵
* @param value 值
* @param expire 超時時間
* @param timeUnit 超時單位
* @return 成功 返回 OK
*/
public boolean setIfNotExists(final String key, final String value, final long expire, final TimeUnit timeUnit) {
return this.redisTemplate.opsForValue().setIfAbsent(key, value, expire, timeUnit);
}
}
3 、使用方式
import com.zto.ztrace.extend.RedisLock;
@Autowired
private RedisLock redisLock;
if (this.redisLock.lock(key)) {
try {
// 業務邏輯
} finally {
this.redisLock.unlock(key);
}
}else{
// 獲取鎖失敗
}