Redis分布式锁
分布式锁概述
分布式锁
是一种用于协调分布式系统中多个节点对共享资源访问的同步机制。在单机多线程环境下,我们可以使用Java中的ReentrantLock或synchronized
等本地锁来控制线程对共享资源的访问。但在分布式系统中,不同的服务/客户端通常运行在独立的JVM进程上,本地锁无法跨JVM实现互斥访问,这时就需要分布式锁
Redis分布式锁基础实现
SETNX命令实现
Redis实现分布式锁的核心在于利用其"互斥"能力,主要通过SETNX(SET if Not eXists)命令实现。这个命令表示如果key不存在才会设置其值,否则不做任何操作。
基本实现流程:
# 加锁
127.0.0.1:6379> SETNX lockKey uniqueValue
(integer) 1 # 加锁成功
# 释放锁
127.0.0.1:6379> DEL lockKey
(integer) 1
这种简单实现存在严重问题:如果获取锁的客户端崩溃或网络中断,无法释放锁,将导致死锁。
Redisson
是Redis官方推荐的Java客户端之一,提供了丰富的分布式对象和服务,其中分布式锁是其核心功能之一。下面我将详细解析Redisson分布式锁的实现机制。
使用示例
public void outer() {
lock.lock();
try {
System.out.println("Outer method acquired lock");
inner(); // 再次获取同一把锁
} finally {
lock.unlock();
System.out.println("Outer method released lock");
}
}
public void inner() {
lock.lock(); // 再次获取同一把锁(重入)
try {
System.out.println("Inner method acquired lock");
} finally {
lock.unlock();
System.out.println("Inner method released lock");
}
}
Redis分布式锁中lock_key
在分布式锁场景中,lock_key相同是设计上的必然要求,这是由分布式锁的基本原理决定的:
互斥性
要求:所有客户端必须使用相同的key来竞争同一把锁
如果每个客户端使用不同的key,就失去了互斥的意义
例如:秒杀系统中的商品ID seckill:product:123
Redisson主从一致性
在Redis主从复制架构中,当客户端在主节点获取锁后,如果主节点在将锁信息同步到从节点前宕机,此时:
- 从节点被提升为新主节点
- 新客户端可能从新主节点获取相同的锁
- 导致多个客户端同时持有同一把锁,破坏互斥性
Redisson的解决方案
1. Redlock算法实现
Redisson提供了RedLock(红锁)实现,基于Redis作者提出的Redlock算法:
- 向N个独立的Redis节点顺序获取锁
- 当且仅当获取到大多数节点(N/2+1)的锁时才算成功
- 总耗时必须小于锁过期时间
- 释放锁时需要向所有节点发送释放请求
RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");
RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
lock.lock();
try {
// 临界区代码
} finally {
lock.unlock();
}
方案 | 一致性保证 | 性能 | 实现复杂度 | 适用场景 |
---|---|---|---|---|
单Redis节点 | 弱 | 高 | 低 | 非关键业务 |
Redlock | 强 | 中 | 中 | 金融/交易 |
Zookeeper | 最强 | 低 | 高 | 强一致需求 |