基于redis的分布式锁实现
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.types.Expiration;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
/**
-
@Description: redis工具类(含 redis分布式锁)
-
@Author: LiG
-
@Date: 2019/6/18 9:22
-
@Version: 1.0
*/
@Component
public class DistributedLockUtil {
@Autowired
private StringRedisTemplate stringRedisTemplate;@Autowired
private DefaultRedisScript defaultRedisScript;private static final Long UNLOCK_SUCCESS = 1L;
/**
- 分布式锁前缀
*/
public static final String LOCK_PREFIX = “distributed:locker:”;
/**
- 获取分布式锁,失败直接返回
- @param key 分布式锁的key(后缀)
- @param value 随机value
- @param lockTime 锁定失效时间(毫秒)
- @return
*/
public boolean lock(@NonNull String key, @NonNull String value, @NonNull Long lockTime) {
return lock(key, value, lockTime, 0L, 0L);
}
/**
- 获取分布式锁,设置获取超时时间,超时返回false
- @param key 分布式锁的key (后缀)
- @param value 随机value
- @param lockTime 锁定失效时间(毫秒)
- @param waitTime 最长等待时间(毫秒)
- @param sleepTime 重试休眠时间(毫秒)
- @return
*/
public boolean lock(@NonNull String key, @NonNull String value, @NonNull Long lockTime, Long waitTime, Long sleepTime) {
String lock = LOCK_PREFIX + key;
Long end = System.currentTimeMillis() + waitTime;
return stringRedisTemplate.execute((RedisConnection connection) -> {
while (true) {
boolean acquire = connection.set(lock.getBytes(StandardCharsets.UTF_8), value.getBytes(StandardCharsets.UTF_8),
Expiration.milliseconds(lockTime), RedisStringCommands.SetOption.SET_IF_ABSENT);
if (acquire) {
return true;
} else if(System.currentTimeMillis() > end) {
return false;
}
try {
//休眠
TimeUnit.MILLISECONDS.sleep(sleepTime);
} catch (InterruptedException e) {
return false;
}
}
});
}
/**
- 删除分布式锁
- @param key 分布式锁的key (后缀)
- @param value 加锁时传入的随机值
- @return
*/
public boolean unLock(@NonNull String key, @NonNull String value) {
String lock = LOCK_PREFIX + key;
long result = stringRedisTemplate.execute(defaultRedisScript, Arrays.asList(lock, value));
return UNLOCK_SUCCESS.equals(result);
}
@Bean
public DefaultRedisScript defaultRedisScript() {
DefaultRedisScript defaultRedisScript = new DefaultRedisScript<>();
defaultRedisScript.setResultType(Long.class);
defaultRedisScript.setScriptText(“if redis.call(‘get’, KEYS[1]) == KEYS[2] then return redis.call(‘del’, KEYS[1]) else return 0 end”);
return defaultRedisScript;
}
} - 分布式锁前缀