大家好,我是小米,今年 31 岁,一个在 Java 世界里摸爬滚打多年的程序员大哥哥。
前几天,我在帮朋友模拟社招面试的时候,面试官突然抛出一个问题:
“你了解 Redis 的 RedLock 吗?它解决了什么问题?”
朋友愣了三秒钟,憋出一句:
“呃……分布式锁的一种实现?”
面试官点点头,又补了一刀:
“那为什么要有 RedLock?SETNX 不行吗?”
好,熟悉的气息来了。这是一个典型的:面试官想看看你“到底理解到哪一层”的问题。
今天这篇文章,我不打算一上来就甩论文、甩算法、甩名词。我们还是老规矩讲个故事。
故事的开始:全村只有一把锁
想象一个场景。你住在一个村子里,村里有一间公共仓库,里面放着村里唯一的“宝贝资源”:比如水泵、电动车充电口、发电机。
为了避免大家同时抢,村长规定:谁用,谁先拿锁。 这把锁就挂在仓库门口。
单机时代:一把锁,世界和平
一开始,村子很小,只有一个仓库。
- 锁是真的锁
- 钥匙只有一把
- 谁先拿到,谁用
这就像:单体应用 + 本地锁(synchronized / ReentrantLock)
简单、直接、世界和平。
问题来了:村子扩张了(分布式时代)
后来,村子发展了。
- 东村
- 西村
- 南村
- 北村
每个村口都建了一个仓库副本,数据是同步的。于是问题来了: “锁放哪?”
如果还只有一把锁,大家跑来跑去,效率极低。于是村长拍板: “每个仓库门口,都放一把锁!”
听起来很合理,对吧?
Redis 分布式锁的第一形态:SETNX
这时候,我们就进入了Redis 分布式锁的基础阶段。
Redis 单节点锁的思路
在 Redis 里,我们通常这么做:
含义是:
- NX:只有不存在才设置(加锁)
- PX:设置过期时间(防止死锁)
Java 示例代码:
这套方案,在单 Redis 实例下,基本可用。
单点问题:锁的“唯一仓库”塌了
故事开始变得刺激。有一天,西村仓库塌了(Redis 宕机) 。发生了什么?
- 锁没了
- 其他人以为“锁不存在”
- 大家一起冲进仓库
问题本质:单个 Redis 节点 = 单点故障
只要 Redis 挂了:
- 锁状态丢失
- 分布式一致性直接破产
进阶方案:主从 + 哨兵,够了吗?
你可能会说:“那我用 Redis 主从 + 哨兵不就好了?”
这是一个非常典型的面试陷阱点,主从复制的时间差问题。
Redis 的主从复制是:异步复制。想象这个场景:
- 客户 A 在 Master 上加锁成功
- Master 还没来得及同步给 Slave
- Master 宕机
- Slave 被提升为 Master
- 客户 B 再次加锁成功
结果是:两个客户端,同时持有“同一把锁”
故事转折:村长发明了“五把锁机制”
这时候,村长终于意识到: “不能只信一把锁了。”
于是他提出一个疯狂的方案:在 5 个独立的仓库里,各放一把锁,谁能同时拿到其中 3 把,谁才算真的拿到锁。”
这,就是 RedLock 的核心思想。
什么是 RedLock?一句话说清楚
RedLock 是 Redis 作者提出的一种基于多个独立 Redis 节点的分布式锁算法,通过“多数派原则”来提升锁的可靠性。
关键词拆解一下:
RedLock 的加锁流程(面试必考)
RedLock 的加锁流程,面试官最爱问。
加锁步骤
假设有 5 个 Redis 节点:
1、记录当前时间 T1
2、依次向 5 个 Redis 节点尝试加锁
3、每个节点使用相同的:
- key
- value
- 过期时间
4、如果:
- 成功节点 ≥ 3
- 且总耗时 < 锁过期时间
5、则加锁成功
6、否则:
- 向已成功的节点释放锁
- 加锁失败
RedLock 的核心判断条件(表格版)
RedLock Java 代码示例(基于 Redisson)
现实中,我们不建议手写 RedLock。最常用的是 Redisson。
1、Maven 依赖
2、配置多个 Redis 节点
3、使用 RedLock
RedLock 的优点和争议(高阶加分点)
优点
争议(面试官最喜欢的)
Redis 官方作者提出,但学术界和工程界一直有争论:
- 网络分区问题
- 时间漂移问题
- 锁有效性依赖系统时间
Martin Kleppmann 曾公开质疑: “RedLock 并不能在所有情况下保证安全性。”
面试官真正想听的答案是什么?
当面试官问: “你怎么看 RedLock?”
一个成熟的回答是:
- RedLock 适合高可用场景
- 成本较高,复杂度高
- 并非强一致性方案
- 是否使用,取决于业务容错能力
总结
最后,用一句话总结:
RedLock 不是银弹,它只是在“可用性”和“复杂度”之间,给出的一种工程折中方案。
如果你的业务:
- 能容忍极小概率的锁失效
- 对可用性要求极高
RedLock 值得考虑。
如果你的业务:
- 对一致性要求极端严格
- 不能接受任何并发错误
请考虑 数据库锁 / Zookeeper。
END
我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!