什么是分布式锁?
分布式锁是一种跨进程、跨机器的互斥机制,它允许多个服务实例竞争一个共享资源的独占权。只有持有锁的服务实例才能操作该资源,其他实例必须等待锁释放后才能继续尝试获取锁。
分布式锁的核心要求包括:
- 互斥性:同一时间只有一个客户端能够持有锁。
- 高可用性:即使部分节点宕机,锁服务仍然可用。
- 安全性:锁不会被错误地分配给多个客户端。
- 容错性:如果客户端崩溃或网络中断,锁应能自动释放。
使用 Redis 实现分布式锁的基本原理
Redis 提供了原子操作(如 SETNX
和 Lua 脚本),可以用来实现分布式锁。以下是实现的基本步骤:
-
加锁:
- 使用 Redis 的
SETNX
命令尝试设置一个键值对,表示锁的持有状态。 - 如果键不存在,则设置成功,表示获取锁;否则失败。
- 设置一个过期时间,防止死锁。
- 使用 Redis 的
-
解锁:
- 使用 Lua 脚本确保删除操作的原子性。
- 只有持有锁的客户端才能解锁。
-
续期:
- 如果任务执行时间较长,可以通过定时刷新锁的过期时间来防止锁提前释放。
代码实现
以下是一个基于 Java 和 Redis 的分布式锁实现,使用 Jedis 客户端库。
1. 加锁逻辑
java
import redis.clients.jedis.Jedis;
import java.util.UUID;
public class RedisDistributedLock {
private Jedis jedis;
private String lockKey;
private int expireTime; // 锁的过期时间(秒)
private String lockValue; // 锁的唯一标识
public RedisDistributedLock(Jedis jedis, String lockKey, int expireTime) {
this.jedis = jedis;
this.lockKey = lockKey;
this.expireTime = expireTime;
this.lockValue = UUID.randomUUID().toString(); // 唯一标识当前客户端
}
/**
* 尝试获取锁
*
* @return 是否成功获取锁
*/
public boolean acquireLock() {
String result = jedis.set(lockKey, lockValue, "NX", "EX", expireTime);
return "OK".equals(result);
}
/**
* 释放锁
*/
public void releaseLock() {
String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
"return redis.call('del', KEYS[1]) " +
"else return 0 end";
jedis.eval(luaScript, 1, lockKey, lockValue);
}
/**
* 续期锁
*/
public void renewLock() {
String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
"return redis.call('expire', KEYS[1], ARGV[2]) " +
"else return 0 end";
jedis.eval(luaScript, 1, lockKey, lockValue, String.valueOf(expireTime));
}
}
2. 使用示例
java
public class DistributedLockExample {
public static void main(String[] args) {
// 初始化 Redis 客户端
Jedis jedis = new Jedis("localhost", 6379);
// 创建分布式锁对象
RedisDistributedLock lock = new RedisDistributedLock(jedis, "my_lock_key", 10);
try {
// 尝试获取锁
if (lock.acquireLock()) {
System.out.println("成功获取锁,执行业务逻辑...");
Thread.sleep(5000); // 模拟业务逻辑处理
// 续期锁
lock.renewLock();
System.out.println("锁已续期,继续执行业务逻辑...");
} else {
System.out.println("未能获取锁,等待...");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 释放锁
lock.releaseLock();
System.out.println("锁已释放");
}
// 关闭 Redis 连接
jedis.close();
}
}
UML 图
以下是分布式锁实现的 UML 类图和序列图。
1. 类图

2. 序列图

总结
通过 Redis 实现分布式锁是一种高效且可靠的方案,适用于分布式系统中的资源共享场景。我们通过 SETNX
和 Lua 脚本保证了锁的互斥性和安全性,同时通过设置过期时间和续期机制避免了死锁的发生。
希望本文对你有所帮助!如果你有任何问题,欢迎留言讨论。