1. 引言
在分布式系统中,多个服务实例可能同时操作共享资源,如果缺乏互斥机制,就会出现超卖、重复扣款、数据覆盖等问题。分布式锁正是为了解决这类跨进程、跨节点的并发竞争问题而设计的通用方案。本文围绕分布式锁的核心原理,给出基于 Redis 的完整代码实现,并讨论常见注意事项。
2. 核心原理
分布式锁的本质是让多个进程在共享存储上竞争一个「唯一标记」,谁拿到标记,谁就获得执行权。以 Redis 为例,最朴素的做法是利用 SETNX 命令:只有当 key 不存在时才能写入成功,写入成功的节点即获得锁。为了避免死锁,锁必须设置过期时间;为了避免误删他人锁,释放前要校验持有者标识。
3. 代码实现
下面给出一个基于 Redis 的分布式锁实现,使用 Java 语言和 Jedis 客户端,代码可直接复制运行。
import redis.clients.jedis.Jedis;
import java.util.UUID;
public class RedisLock {
private Jedis jedis;
private String lockKey;
private String requestId;
private int expireTime = 30000; // 锁自动过期时间,单位毫秒
public RedisLock(Jedis jedis, String lockKey) {
this.jedis = jedis;
this.lockKey = lockKey;
this.requestId = UUID.randomUUID().toString();
}
// 加锁:SETNX + 过期时间,保证原子性
public boolean tryLock() {
String result = jedis.set(lockKey, requestId,
"NX", "PX", expireTime);
return "OK".equals(result);
}
// 解锁:先校验持有者,再删除,防止误删他人锁
public void unlock() {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] " +
"then return redis.call('del', KEYS[1]) " +
"else return 0 end";
jedis.eval(script, 1, lockKey, requestId);
}
}
使用示例:
Jedis jedis = new Jedis("localhost", 6379);
RedisLock lock = new RedisLock(jedis, "order:12345");
if (lock.tryLock()) {
try {
// 执行临界区业务逻辑
System.out.println("获取锁成功,执行业务");
} finally {
lock.unlock();
}
} else {
System.out.println("获取锁失败,稍后重试");
}
4. 注意事项
第一,加锁和解锁必须保证原子性,避免「先 SETNX 再单独 EXPIRE」这种非原子写法。第二,释放锁前必须校验持有者标识,否则可能误删其他线程的锁。第三,业务执行时间不能超过锁的过期时间,否则锁提前失效会导致并发问题,必要时可引入看门狗续期机制。第四,在 Redis 主从架构下,主节点宕机可能导致锁丢失,对强一致性要求高的场景可考虑 Redlock 算法。
5. 总结
分布式锁是解决分布式并发竞争的基础组件。本文给出的 Redis 实现覆盖了加锁、解锁和防误删三个关键环节,代码简洁且可直接落地。实际生产环境中,建议优先使用 Redisson 等成熟客户端,它们内置了看门狗续期和 Redlock 支持,能进一步降低实现复杂度。
网硕互联帮助中心




评论前必须登录!
注册