news 2026/4/15 23:12:01

字节二面挂了!问 “Redis 分布式锁怎么实现”,我答 “SetNX”,面试官:业务没跑完锁过期了怎么办?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
字节二面挂了!问 “Redis 分布式锁怎么实现”,我答 “SetNX”,面试官:业务没跑完锁过期了怎么办?

最近一个 5 年经验的粉丝在群里复盘字节二面,哭晕在厕所。

面试官问了一个看似简单的题:“怎么用 Redis 实现分布式锁?

这哥们心想这题刷了八百遍了,张口就来:“简单!用 SETNX 命令,Key 存在就返回失败,不存在就写入成功,顺便设个过期时间防止死锁。释放锁的时候 DEL 掉就行了。”

面试官听完,冷冷地抛出三个死亡追问:

  1. “如果你设了 10 秒过期,但业务跑了 15 秒,锁提前释放了,别人进来了,并发不就穿透了吗?”

  2. “你的业务跑完去删锁,结果删的是别人加的锁(因为你自己的早过期了),这怎么解?”

  3. “Redis 主从切换时,锁还没同步到从库,主库挂了,从库上位,锁丢失了怎么办?

这哥们瞬间汗流浃背,支支吾吾答不上来,最后挂在了这道“送分题”上。

兄弟们,手写 SETNX 这种原始人做法,在生产环境就是埋雷。

今天 Fox 带你拆解这道题的3 种段位,看看大厂是如何做“企业级分布式锁”的。

一、 为什么 “手写 SETNX” 是自杀行为?

很多教程教你写 redis.setnx(key, value),这在玩具项目里能用,但在高并发核心链路下,有两大死穴:

  1. 非原子性(早期写法): 如果你先 SETNX 再 EXPIRE,中间刚好服务器挂了,这把锁就永不过期,造成死锁。(注:虽然 SET key value NX PX 是原子的,但依然解决不了下面的问题)。

  2. 锁续期(Lock Renewal): 这是最致命的。业务执行时间是不确定的。 设长了影响性能,设短了业务没跑完锁就丢了。

结论: 生产环境禁止裸写 SETNX,除非你能 100% 确定业务执行耗时极短且不可变。

二、 核心架构:3 种主流解法(从青铜到王者)

解法 1:原子指令 + Lua 脚本(基础防误删)—— 青铜段位

这是解决“原子性”和“误删别人锁”的基础方案。

逻辑:

  1. 加锁:必须使用原子命令 SET key uuid NX PX 30000。Value 必须是当前线程的唯一标识(如 UUID + ThreadID)。

  2. 解锁:必须用 Lua 脚本。先 GET 拿出来对比,如果是自己的 UUID 才执行 DEL。

Lua 代码(防误删):

if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end

Fox点评: 这只是达到了“能用”的标准,解决了原子性和误删问题,但依然无法解决“业务没跑完锁过期”的硬伤。

解法 2:Redisson WatchDog(看门狗)—— 黄金段位

这是目前 Java 界分布式锁的标准答案。别造轮子,直接用 Redisson。它不仅解决了续期,还帮你搞定了“可重入”和“阻塞等待”

原理(源码级细节):

  1. 加锁:默认加 30 秒过期时间。

  2. 启动看门狗:高能预警!只有在未指定锁过期时间(使用默认 leaseTime)且加锁成功时,Redisson 才会启动 WatchDog。

注意:如果你手动传了 leaseTime,看门狗机制将会失效,业务跑不完锁会直接过期!)

  1. 自动续期:WatchDog 基于 Netty 的 TimeTask(时间轮) 实现。它每隔 10 秒(internalLockLeaseTime / 3)检查一次,如果当前客户端还持有锁(校验 UUID),就通过 Lua 脚本 重置过期时间为 30 秒。

  1. 解锁/宕机:业务跑完显式解锁,或者客户端宕机(连接断开),WatchDog 任务取消,锁在 30 秒后自然过期。

Fox 点评: 这才是工业级的实现。它完美解决了“锁过期”问题,让锁的生命周期与业务执行时间自动绑定。

解法 3:Redlock vs Zookeeper(CP 还是 AP?)—— 王者段位

面试官的第三个追问:“主从切换锁丢失怎么办?

场景:线程 A 在 Master 加锁成功 -> Master 挂了 -> 锁没同步到 Slave -> Slave 升级为 New Master -> 线程 B 在 New Master 加锁成功。并发事故发生。

流派之争:

  1. Redlock(红锁): Redis 作者提出的算法。要求在 N 个独立的 Redis 节点上,至少 N/2+1 个加锁成功才算成功。

  • 缺点:极其复杂,运维成本高(要部署 5 个独立节点),且被分布式专家质疑存在时钟跳变问题。性价比往往不如 ZK/Etcd。

  1. Zookeeper(CP 模型)

  • 原理:利用 ZK 的临时顺序节点。

  • 优势:ZK 是 CP(强一致性),保证数据绝对不丢。随着 ZK 版本的迭代(如 3.6+),读性能已有很大提升。

  • 劣势:写吞吐量不如 Redis(但在读多写少场景表现尚可)。

王者回答:业务决定架构

  • 如果业务允许极小概率的并发(如优惠券扣减、常规限流),Redis 主从 + Redisson足矣。哪怕主从切换丢了锁,数据库层还有唯一索引兜底

  • 如果业务是核心金融场景(如资金划转),决不用 Redis,直接上Zookeeper 或 Etcd,牺牲性能换取强一致性。”

三、 最后的“防杠”指南(扫清死角)

答出 Redisson 后,面试官会继续深挖,这 3 个问题能帮你拿 SSP:

Q1:分布式锁需要“可重入”吗?Redisson 怎么实现的?

答:“必须可重入。想象一个场景:methodA 拿了锁,内部调用 methodB,methodB 也要拿同一把锁。如果锁不可重入,线程就会自己把自己锁死。 Redisson 内部利用Redis Hash 结构来存储锁

  • Key: 锁名(lock:order:1001)。

  • Field: UUID:ThreadID(客户端唯一标识 + 线程 ID)。

  • Value: 重入次数(Counter)。 加锁时 Counter +1,解锁时 Counter -1,归零时真正删除 Key,并发布释放消息。”

Q2:高并发下,所有线程都在自旋抢锁,Redis CPU 飙升怎么办?

答:“Redisson 做了优化,抛弃了简单的 While(true) 自旋,采用了Pub/Sub(发布订阅) 机制

  1. 线程 A 抢锁失败后,订阅锁对应的 Channel。

  2. 线程 A 进入 Semaphore/Future 阻塞状态(不占用 CPU),设置超时时间。

  3. 当线程 B 释放锁时,发布一条消息通知 Channel。

  4. 线程 A 被唤醒,再次加入竞争队列尝试抢锁。 这叫‘等待-通知’模式,极大减少了无效的轮询请求。”

Q3:Redisson 的 WatchDog 会导致死锁吗?(比如业务线程死循环)

答:“不会死锁,但锁会一直不过期。 WatchDog 的续期逻辑是依赖于客户端连接的。

  • 如果业务线程死循环,只要机器没挂、连接还在,WatchDog 确实会一直续期。但这属于代码逻辑 Bug,应该由长事务监控报警来解决,而不是靠锁机制强行断开(否则会导致业务并发安全问题)。

  • 如果服务器宕机,连接断开,WatchDog 机制失效,锁会自动过期。”

四、 面试标准答案模板(建议背诵)

下次被问到“Redis 分布式锁怎么实现”,建议按以下逻辑回答:

“对于 Redis 分布式锁,我会根据业务场景选择不同方案:

  1. 基础实现: 使用 SET key uuid NX PX 30000(原子操作)保证互斥性,解锁时通过 Lua 脚本(先 GET 对比 UUID 再 DEL)避免误删。

  2. 工业级实现(Java): 优先使用 Redisson 框架,它解决了核心痛点:

  • WatchDog 自动续期: 针对未设置过期时间的锁,每隔 10 秒检测并续期,解决业务执行时间不确定导致锁失效的问题。

  • 可重入锁: 通过 Hash 结构(Key=锁名, Field=UUID:ThreadID)存储重入次数,支持嵌套调用。

  • 性能优化: 基于 Pub/Sub + 本地等待 机制替代自旋,减少 CPU 消耗。

  1. 一致性权衡

  • 普通场景: Redis 主从 + Redisson,数据库唯一索引兜底。

  • 核心场景: 选择 Redlock(多数派确认)或 Zookeeper(CP 模型),避免单点故障和主从切换导致的锁丢失。”

写在最后

分布式锁没有“银弹”。Redis 是 AP 锁(高性能,弱一致),Zookeeper 是 CP 锁(强一致,写吞吐较低)。面试官考的不是 API 怎么调,而是你看待“CAP 取舍”的架构师视角。

https://mp.weixin.qq.com/s/PWZVfzet9nBRPT-UBhMZ0w

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/12 16:21:33

COMSOL模拟瓦斯抽采过程中的变渗透率模型与煤体变形耦合效应研究

comsol瓦斯抽采数值模拟 变渗透率模型 煤体变形耦合瓦斯抽采巷道里瓦斯浓度警报突然响起,这是我第三次在井下遇到传感器闪红。矿工们常说瓦斯像弹簧——你压得越狠,它反弹越凶。在COMSOL里重建这种煤岩与瓦斯的博弈,关键在于让渗透率参数活起…

作者头像 李华
网站建设 2026/4/13 10:34:48

编程培训班新增课题:教学生使用lora-scripts掌握LoRA微调技能

编程培训班新增课题:教学生使用lora-scripts掌握LoRA微调技能 在AI生成内容(AIGC)迅速普及的今天,越来越多企业和个人开始尝试定制专属模型——无论是为品牌打造独特的视觉风格,还是让大语言模型具备专业领域知识。然而…

作者头像 李华
网站建设 2026/4/13 11:27:12

医学影像描述生成:lora-scripts在放射科报告辅助写作中的尝试

医学影像描述生成:lora-scripts在放射科报告辅助写作中的尝试 在放射科医生每天面对数百份影像的现实压力下,一份结构清晰、术语规范的诊断报告往往需要耗费大量时间。尤其在基层医院或高峰时段,重复性描述的撰写不仅消耗精力,还可…

作者头像 李华
网站建设 2026/4/13 14:19:28

揭秘C++26契约编程中的异常传递机制:5步实现零崩溃健壮代码

第一章:C26契约编程与异常安全的演进C26 正在推进契约编程(Contracts)和异常安全机制的深度整合,旨在提升代码的可维护性与运行时可靠性。通过将契约作为语言一级特性,开发者能够在函数接口层面声明前置条件、后置条件…

作者头像 李华
网站建设 2026/4/15 22:05:14

政府机构试点应用:公共服务领域引入lora-scripts提升办事效率

政府机构试点应用:公共服务领域引入 lora-scripts 提升办事效率 在政务服务窗口前,一位市民问:“新生儿落户需要哪些材料?” 工作人员打开系统,输入关键词,等待几秒后,一条结构清晰、政策依据明…

作者头像 李华
网站建设 2026/4/12 21:44:16

NFT艺术品创作流水线:艺术家结合lora-scripts打造系列作品

NFT艺术品创作流水线:艺术家结合lora-scripts打造系列作品 在数字艺术与区块链交汇的今天,NFT 已不再是简单的“头像”或“收藏卡牌”。越来越多艺术家开始思考:如何用 AI 技术规模化地表达个人风格?如何将灵感固化为可重复生成、…

作者头像 李华