实现Redis分布式锁的核心在于利用Redis的单线程特性,通过原子操作确保互斥性,并结合过期时间、唯一标识等机制解决死锁、误解锁等问题。以下是具体实现方案及关键代码示例:
一、核心实现步骤1. 加锁逻辑2. 解锁逻辑- 校验归属:通过Lua脚本原子性执行GET + DEL,确保只有锁的持有者能释放锁。if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end
- 原子性保证:Lua脚本在Redis中单线程执行,避免竞态条件。
二、Java代码实现(基于Jedis)1. 依赖引入<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version></dependency>2. 加锁代码public boolean tryGetDistributedLock(String lockKey, String requestId, int expireTime) { try (Jedis jedis = jedisPool.getResource()) { String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime); return "OK".equals(result); }}- 参数说明:
lockKey:锁的键名(需全局唯一)。
requestId:客户端唯一标识。
expireTime:锁的过期时间(毫秒)。
3. 解锁代码public boolean releaseDistributedLock(String lockKey, String requestId) { try (Jedis jedis = jedisPool.getResource()) { String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " + "return redis.call('del', KEYS[1]) else return 0 end"; Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId)); return result.equals(1L); }}三、关键问题处理死锁避免
通过PX设置过期时间,即使客户端崩溃,锁也会自动释放。
误解锁防护
解锁时校验value是否与requestId匹配,防止删除其他客户端的锁。
锁续期(可选)
对于耗时操作,可使用Redisson等库的看门狗机制自动续期。
Redis集群容错
单节点Redis可能因故障导致锁丢失,需使用Redlock算法(需多数节点同意)增强可靠性。
四、注意事项- 锁粒度:避免锁住过多资源,影响并发性能。
- 重试机制:加锁失败后应合理重试(如指数退避)。
- 性能考量:频繁加解锁可能增加Redis负载,需评估业务场景。
五、完整示例调用String lockKey = "order_lock";String requestId = UUID.randomUUID().toString();int expireTime = 30000; // 30秒// 尝试加锁if (tryGetDistributedLock(lockKey, requestId, expireTime)) { try { // 执行业务逻辑 } finally { // 确保解锁 releaseDistributedLock(lockKey, requestId); }} else { // 获取锁失败处理}通过以上方案,可实现一个满足互斥性、防死锁、防误删的Redis分布式锁。如需更高可靠性,建议结合Redisson库或Redlock算法。