以下是几种常见的 Redis 分布式锁的 Java 实现方式:
1. 基于 SETNX 命令的实现
SETNX
命令(对应 Java 中的 setIfAbsent
方法)是实现 Redis 分布式锁的基础。以下是实现代码:
import redis.clients.jedis.Jedis;
public class RedisLock {
private Jedis jedis;
public RedisLock(Jedis jedis) {
this.jedis = jedis;
}
// 尝试获取锁
public boolean tryLock(String lockKey, String requestId, int expireTime) {
String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime);
return "OK".equals(result);
}
// 释放锁
public void unlock(String lockKey, String requestId) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
}
}
2. 基于 Redisson 的实现
Redisson 是 Redis 官方提供的 Java 组件,封装了分布式锁的实现,使用起来非常方便。以下是 Redisson 的使用示例:
首先,添加 Redisson 依赖:
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>最新版本</version>
</dependency>
然后,使用 Redisson 实现分布式锁:
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
public class RedissonLock {
private RedissonClient redissonClient;
public RedissonLock() {
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
redissonClient = Redisson.create(config);
}
// 获取锁
public RLock getLock(String lockKey) {
return redissonClient.getLock(lockKey);
}
// 释放锁
public void unlock(RLock lock) {
lock.unlock();
}
}
3. 基于 Spring Data Redis 的实现
如果项目中使用了 Spring Boot,可以通过 StringRedisTemplate
来操作 Redis,实现分布式锁:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
@Component
public class DistributedLock {
@Autowired
private StringRedisTemplate redisTemplate;
// 尝试获取锁
public boolean getLock(String lockId, long millisecond) {
Boolean success = redisTemplate.opsForValue().setIfAbsent(lockId, "lock", millisecond, TimeUnit.MILLISECONDS);
return success != null && success;
}
// 释放锁
public void releaseLock(String lockId) {
redisTemplate.delete(lockId);
}
}
4. 基于 Redlock 算法的实现
Redlock 算法是 Redis 官方推荐的分布式锁算法,适用于集群环境。以下是 Redlock 算法的 Java 实现:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
public class Redlock {
private JedisPool[] jedisPools;
private int quorum; // 多数派数量
public Redlock(JedisPool[] jedisPools) {
this.jedisPools = jedisPools;
this.quorum = (jedisPools.length + 1) / 2;
}
// 获取锁
public boolean lock(String lockKey, String requestId, int expireTime) {
int count = 0;
long start = System.currentTimeMillis();
for (JedisPool pool : jedisPools) {
try (Jedis jedis = pool.getResource()) {
String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime);
if ("OK".equals(result)) {
count++;
}
} catch (Exception e) {
// 忽略异常
}
}
if (count >= quorum && System.currentTimeMillis() - start <= expireTime) {
return true;
}
// 释放所有节点上的锁
unlock(lockKey, requestId);
return false;
}
// 释放锁
public void unlock(String lockKey, String requestId) {
for (JedisPool pool : jedisPools) {
try (Jedis jedis = pool.getResource()) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
} catch (Exception e) {
// 忽略异常
}
}
}
}
总结
基于 SETNX 的实现:简单高效,适用于单机环境。
基于 Redisson 的实现:封装完善,易于使用,推荐在 Spring Boot 项目中使用。
基于 Spring Data Redis 的实现:与 Spring 生态系统集成良好,适合 Spring Boot 项目。
基于 Redlock 算法的实现:适用于集群环境,但实现相对复杂,性能开销较大。
在实际项目中,可以根据具体需求和项目环境选择合适的实现方式