【Redis 分布式锁血案】主节点挂了还没释放锁怎么办?这才是正确的解决姿势!
·
📌 一、问题引入:一场由 Redis 分布式锁引发的血案
在 Java 分布式系统中,Redis 作为高性能的缓存中间件被广泛用于实现分布式锁。
常见的做法是使用:
SET key value NX PX 30000
来加锁——这段命令的含义是:仅当 key 不存在时设置,并设置过期时间为 30 秒。
但如果你以为这样就安全了,那就大错特错!
❗ 场景还原
- 微服务 A 成功获取锁(Redis 主节点写入
lock:order)。 - 还未释放,Redis 主节点突然挂了。
- Redis 自动发生主从切换,从节点升级为新主。
- 新主上未同步
lock:order锁状态。 - 微服务 B 检查无锁,直接抢锁成功!
- 💥两个服务都认为自己拥有锁,导致业务并发冲突、数据错乱!
📉 二、为什么会发生这种灾难?
🔍 原因:Redis 主从复制是异步的
Redis 的复制默认是异步:
- 写入主节点的数据不一定能及时同步到从节点;
- 主节点宕机后,从节点变主节点;
- 从节点可能压根不知道锁存在,于是下一个客户端就能再次加锁!
✅ 三、正确姿势一:RedLock 分布式锁算法
📌 RedLock 原理
- 将锁请求同时发送到 多个独立的 Redis 节点(建议 5 个)。
- 只要在多数节点(如 ≥3)成功加锁,则认为加锁成功。
- 锁具有统一的 TTL(过期时间),且加锁过程必须在较短时间(如 500ms)内完成。
- 释放锁时必须向所有节点发起解锁请求。
✅ 优势:
- 不依赖主从复制,避免单节点故障导致锁状态丢失。
- 即使部分节点挂掉,仍能维持分布式锁正确性。
⚠️ 注意事项:
- 必须部署多个 独立 Redis 实例(非主从结构);
- 推荐使用 Redisson 框架封装 RedLock。
💻 四、实战演示:Redisson 实现 RedLock(Java)
1️⃣ 引入依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.27.2</version>
</dependency>
2️⃣ 配置多个独立 Redis 节点(非主从)
Config config = new Config();
config.useClusterServers()
.addNodeAddress("redis://127.0.0.1:7001")
.addNodeAddress("redis://127.0.0.1:7002")
.addNodeAddress("redis://127.0.0.1:7003");
RedissonClient redisson = Redisson.create(config);
3️⃣ 加锁代码(RedLock)
RLock lock1 = redisson.getLock("lock1");
RLock lock2 = redisson.getLock("lock2");
RLock lock3 = redisson.getLock("lock3");
RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);
try {
boolean isLocked = redLock.tryLock(500, 30000, TimeUnit.MILLISECONDS);
if (isLocked) {
System.out.println("加锁成功,执行业务...");
}
} finally {
redLock.unlock();
}
✅ 五、正确姿势二:使用 Zookeeper 实现强一致分布式锁
Zookeeper 采用 CP 模型(强一致性),可以使用 Apache Curator 实现分布式锁。
💡 Zookeeper 优势:
- 天然支持分布式一致性;
- 容错性高,适用于高可靠场景;
- 不依赖 Redis,避免缓存误删等问题。
✅ 六、正确姿势三:业务+锁双重保障机制
- 锁状态记录数据库、MQ 或本地;
- 锁续命机制避免业务执行过慢导致锁提前过期;
- 对并发操作增加幂等校验、状态回滚。
❌ 七、常见错误用法警示
| 错误用法 | 风险点说明 |
|---|---|
| 只使用 Redis 主节点加锁 | 主从切换后锁可能丢失 |
| 依赖 Redis 异步复制锁数据同步 | 无法保证锁存在 |
| 忽略锁过期时间 & 无续命机制 | 业务未完成,锁已被其他线程获得 |
| 不使用唯一值标识锁归属 | 锁被误删或误释放 |
📦 八、最佳实践总结
| 应用场景 | 推荐方案 |
|---|---|
| 高性能 & 高可用 | Redisson + RedLock |
| 强一致性要求 | Zookeeper + Curator 分布式锁 |
| 简单单机锁 | Redis 单实例 |
🔚 九、写在最后:锁不是万能,幂等才是底线
分布式系统中锁只是“安全带”,不能成为系统唯一依赖。正确的做法应该是:
锁 + 幂等 + 补偿机制 + 状态机保障
📥 十、附加福利:RedLock 加锁逻辑图
🚨你还在用 Redis 的单节点锁?别怪主节点挂了导致数据错乱!
点赞 + 收藏 + 关注,一起掌握分布式锁最强姿势🔥!
更多推荐
所有评论(0)