Spring Boot整合Redis分布式锁
# pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-redis</artifactId>
</dependency>
# RedisLockConfig
@Configuration
public class RedisLockConfig {
@Bean(destroyMethod = "destroy")
public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) {
// 这里的lock是存储在redis中的key前缀“The key prefix for locks.”
return new RedisLockRegistry(redisConnectionFactory, "lock");
}
}
# 示例
@Autowired
private RedisLockRegistry lockRegistry;
Lock lock = lockRegistry.obtain(key);
boolean locked = false;
try {
locked = lock.tryLock();
if (!locked) {
// 没有获取到锁的逻辑
}
// 获取锁的逻辑
} finally {
// 一定要解锁
if (locked) {
lock.unlock();
}
}
# Redis 的分布式锁实现方式
# 单个 Redis 实例
setnx (key, 当前时间 + 过期时间) + Lua
# 加锁
set NX PX + 重试 + 重试间隔
向 Redis 发起如下命令: SET productId:lock 0xx9p03001 NX PX 30000
productId
:由自己定义,可以是与本次业务有关的 id,"0xx9p03001" 是一串随机值,必须保证全局唯一 (原因在后文中会提到)。NX
:指的是当且仅当 key (也就是案例中的 "productId:lock”) 在 Redis 中不存在时,返回执行成功,否则执行失败。PX 30000
:指的是在 30 秒后,key 将被自动删除。
执行命令后返回成功,表明服务成功的获得了锁。
# 解锁
采用 lua 脚本
在删除 key 时需传递 key 对应的 value 值,以保证删除的是所期望的,如果服务 A 只通过 key 来删除锁,则可能会误将服务 B 的锁释放掉。
if redis.call("get", KEYS[1])==ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
# Redis 集群模式
Redlock
# 参考
上次更新: 2022/12/31, 03:04:26