Redis分布式锁
参考 http://www.redis.cn/topics/distlock.html
单 Redis 实现分布式锁
获取锁命令
SET resource_name my_random_value NX PX 30000
仅当 key
不存在时才能执行成功(NX),并且设置了30秒的过期时间(PX).
key
的值是一个随机值,这个值在每个客户端必须是唯一的
随机数的作用是为了安全的释放锁,仅当随机数等于本客户端村塾的值才能删除成功
Spring Boot 版本
@Slf4j
@SpringBootApplication
public class RedisApplication implements CommandLineRunner {
String key = "k";
ThreadLocal<String> stringThreadLocal = new ThreadLocal<>();
@Autowired
private RedisTemplate redisTemplate;
public static void main(String[] args) {
SpringApplication.run(RedisApplication.class, args);
}
@Override
@SneakyThrows
public void run(String... args) {
boolean res = false;
while (!res) {
String v = UUID.randomUUID().toString();
stringThreadLocal.set(v);
log.info("uuid: {}", v);
res = lock(stringThreadLocal.get());
if (res) {
log.info("设置锁成功");
log.info("dosomething...");
Thread.sleep(10000);
relase(stringThreadLocal.get());
} else {
log.info("设置锁失败");
Thread.sleep(1000);
}
}
}
public boolean lock(String value) {
boolean res = redisTemplate.opsForValue().setIfAbsent(key, value, 60, TimeUnit.SECONDS);
return res;
}
public void relase(String value) {
Object o = redisTemplate.opsForValue().get(key);
if (o != null && o instanceof String) {
String v = String.class.cast(value);
if (v.equals(stringThreadLocal.get())) {
redisTemplate.delete(key);
log.info("relase {}", v);
}else{
log.warn("失败 relase {}", v);
}
}
}
}
使用 redisson
https://github.com/redisson/redisson/tree/master/redisson-spring-boot-starter
RLock lock = redisson.getLock("myLock");
// or wait for lock aquisition up to 100 seconds
// and automatically unlock it after 10 seconds
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {
try {
...
} finally {
lock.unlock();
}
}
配置
https://github.com/redisson/redisson/wiki/2.-Configuration#26-single-instance-mode
参考配置
application.yml
spring:
redis:
#path to config - redisson.yaml
redisson:
file: classpath:redisson.yaml
redisson.yaml
singleServerConfig:
idleConnectionTimeout: 10000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
password: null
subscriptionsPerConnection: 5
clientName: null
address: "redis://himcs.io:6379"
subscriptionConnectionMinimumIdleSize: 1
subscriptionConnectionPoolSize: 50
connectionMinimumIdleSize: 24
connectionPoolSize: 64
database: 0
dnsMonitoringInterval: 5000
threads: 16
nettyThreads: 32
codec: !<org.redisson.codec.JsonJacksonCodec> {}
transportMode: "NIO"