分布式锁实现
1. 加锁
- Key:锁的唯一标识符。
- Value:锁的持有者的唯一标识符(例如客户端的唯一 ID)。
- 过期时间:防止死锁,设置一个合理的过期时间。
2. 释放锁
- 检查锁的持有者:只有锁的持有者才能释放锁。
- 原子性操作:使用 Lua 脚本确保释放锁的操作是原子的。
package com.example.demo;
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 DistributedLock {
@Autowired
private StringRedisTemplate stringRedisTemplate;
// 锁的过期时间(秒)
private static final long LOCK_EXPIRE_TIME = 10; // 锁10秒后自动释放
// 获取分布式锁
public boolean acquireLock(String lockKey, String requestId) {
// 使用 SETNX 命令尝试获取锁,结合过期时间确保锁的原子性
Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, requestId, LOCK_EXPIRE_TIME, TimeUnit.SECONDS);
return Boolean.TRUE.equals(success);
}
// 释放分布式锁
public boolean releaseLock(String lockKey, String requestId) {
// 使用 Lua 脚本确保释放锁的原子性,并校验锁是否是自身的。
String unlockLuaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
"return redis.call('del', KEYS[1]) " +
"else " +
"return 0 " +
"end";
Long result = stringRedisTemplate.execute(
new DefaultRedisScript<>(unlockLuaScript, Long.class),
Collections.singletonList(lockKey),
requestId
);
return result != null && result > 0;
}
}