redistemplate 加锁
时间: 2025-04-17 21:43:47 浏览: 26
### 如何使用 RedisTemplate 实现分布式锁
#### 设计原则
为了确保分布式系统的多个实例在同一时刻只有一个能够执行特定操作,分布式锁成为必要工具。在设计基于 `RedisTemplate` 的分布式锁时,需遵循几个重要原则:
- **唯一性**:每次加锁应赋予唯一的标识符,通常是一个随机字符串,用于区分不同客户端的请求[^3]。
- **自动过期机制**:为了避免死锁的发生,在创建键的同时设定合理的超时期限,一旦超过该期限未续期,则认为持有者已失效并允许其他竞争者获得资源访问权[^1]。
- **原子化操作**:无论是获取还是释放锁的操作都应当具备不可分割特性,即要么全部成功完成,要么完全不发生任何改变;这可以通过 Lua 脚本来达成目的。
#### Java代码实现
下面展示了一个简单的例子来说明如何利用 Spring Data Redis 中提供的 `RedisTemplate` 来构建一个可靠的分布式互斥锁。
```java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class DistributedLockService {
private static final String LOCK_SUCCESS = "OK";
private static final Long RELEASE_SUCCESS = 1L;
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* 尝试获取分布式锁.
*/
public boolean tryGetDistributedLock(String lockKey, String requestId, int expireTime){
Boolean result = this.stringRedisTemplate.opsForValue()
.setIfAbsent(lockKey, requestId, Duration.ofSeconds(expireTime));
return Objects.nonNull(result) && result.booleanValue();
}
/**
* 释放分布式锁.
*/
public void releaseDistributedLock(final String lockKey,final String requestId){
List<String> keys = Collections.singletonList(lockKey);
List<String> args = Collections.singletonList(requestId);
// 使用lua脚本保证判断和删除动作的原子性
String script =
"if redis.call('GET', KEYS[1]) == ARGV[1]" +
"then" +
"return redis.call('DEL', KEYS[1])"+
"else" +
"return 0" +
"end";
Object result = this.stringRedisTemplate.execute(
new DefaultRedisScript<>(script,Long.class),keys,args.toArray());
if(!RELEASE_SUCCESS.equals(result)){
throw new RuntimeException("Unlock failed");
}
}
}
```
上述代码片段展示了两种核心方法——尝试获取锁 (`tryGetDistributedLock`) 和安全地解除锁定状态(`releaseDistributedLock`) 。前者通过调用 `opsForValue().setIfAbsent()` 方法以非阻塞方式试图占有指定名称下的共享资源,并指定了最大等待时限;后者则借助 Lua 脚本实现了条件性的移除逻辑,从而有效防止误删他人所持之锁的情况出现[^2]。
阅读全文
相关推荐


















