Redis分布式锁面试全解析:从SET NX到Redisson与RedLock

Redis分布式锁面试全解析:从SET NX到Redisson与RedLock 搞Redis分布式锁面试题很多人第一反应就是背答案SET NX、Redisson、看门狗、红锁……背得滚瓜烂熟结果面试官一句“你们生产环境用哪种为什么不用另一种”就卡壳了。原因很简单分布式锁这东西看着是一道题背后是一整套分布式系统的核心矛盾怎么在不可靠的网络、会宕机的进程、可能脑裂的集群里保证“同一时刻只有一个客户端能干活”。这篇文章我不打算给你罗列八股答案而是把这几年用Redis做分布式锁踩过的坑、面试官真正想听到的回答、以及那些网上没人细讲的细节完整拆给你。内容围绕8个高频面试题展开从最基础的SET NX起步到Lua脚本、看门狗续期、RedLock争议、主从切换丢锁再到分段锁优化一条线拉通。不管你是准备面试还是团队里要落地分布式锁方案这篇文章都值得花十五分钟看完。看完你会发现分布式锁的核心不在一行命令而在你对“不确定性”的理解有多深。1. 面试官真正想考什么分布式锁的三座大山先搞清楚一件事分布式锁面试题本质上不是考你Redis命令记得多熟而是考你对分布式系统几个最基本问题的理解。1.1 互斥、安全与可用性的三角博弈任何一个分布式锁方案核心诉求只有三个互斥性任意时刻只能有一个客户端持有锁。这条做不到锁就没有意义。安全性锁不能被错误释放比如A客户端释放了B客户端的锁不能因为异常情况导致死锁。可用性持有锁的客户端挂了锁要能被其他客户端获取加锁服务本身也不能因为单点问题导致全部业务瘫痪。这三者往往互相打架。你为了安全性加了复杂的确认机制可用性就下降你为了性能做了本地缓存互斥性就可能被破坏。面试官想看到的是你能在不同场景下做出合理取舍。1.2 从单机锁到分布式锁的本质跨越单机锁好办JVM里一个ReentrantLock状态全在内存里线程挂了锁自动释放。但分布式环境下锁的持有者是不同机器上的不同进程大家通过网络通信来协商。这就引入了单机锁完全不需要考虑的问题网络延迟和超时你发一个加锁请求到底成功没有超时了算不算进程崩溃拿到锁之后进程挂了锁什么时候释放时钟漂移如果依赖时间判断锁是否过期各机器时钟不一致怎么办网络分区集群里一部分节点联系不上还能不能正常加锁这些才是分布式锁面试题背后真正要考察的东西。如果你在面试中能把这些问题主动抛出来而不是被动等着问SET NX那这轮基本就稳了。2. 第一题怎么用Redis实现一个最简单可靠的分布式锁这是最基础的入门题但恰恰是很多人的第一个知识盲区。2.1 从setnx到set NX EX的演进老一点的方案是SETNX命令SETNX key value这个命令只有key不存在时才会设置成功返回1存在则返回0。但是这里有个很明显的坑如果客户端拿到锁之后还没来得及释放就挂了这个key会一直存在其他客户端永远加锁失败死锁了。于是有了后续补救EXPIRE key 30设置过期时间。但问题又来了SETNX和EXPIRE是两条命令如果第一条执行成功第二条执行前客户端宕机锁还是有失效时间等于没有的死锁问题。正确的姿势是把两步合成一步SET key value NX EX 30其实SET命令在Redis 2.6.12版本就支持了NX和EX选项很多老项目还在用两条命令分开执行纯粹是历史包袱。这条命令做了三件事NX只有key不存在时才设置保证了互斥性EX 30设置30秒过期时间避免死锁整体原子性一个命令执行完不需要担心中间崩溃这个操作面试时一定要说出来这是整个分布式锁的地基。2.2 加锁参数怎么定过期时间不能拍脑袋很多人直接写死一个EX 10问为什么是10秒答不上来。过期时间应该怎么估算正确的方法是评估持有锁期间的最长业务执行时间。比如你的业务是更新一个订单状态正常情况50毫秒就搞完了但极端情况下可能要做远程调用、查数据库耗时可能到2秒。那你应该设置一个比最坏情况更长的时间比如5-10秒留出足够余量。但余量又有矛盾设太短业务还没执行完锁就过期了其他客户端趁虚而入出大事故设太长持有锁的客户端一旦真的挂了其他客户端要干等很久。所以过期时间本身就是一个需要根据业务特性动态调整的参数光这一点就能看出候选人对线上环境有没有敬畏心。注意只设一个固定过期时间本质上仍然不完美。业务执行时间是不可预测的所以才有后面要讲的看门狗续期机制。3. 第二题锁误删问题与Lua脚本的第一次登场加了锁、设了过期时间看着没问题了但第一个经典bug在等着你。3.1 超时误删一个足以引发线上事故的细节想象这个场景A客户端加锁成功设置过期时间10秒A执行业务超过10秒锁自动过期了B客户端加锁成功开始执行业务A终于执行完了执行DEL key释放锁B的锁被A释放了此时C客户端又加锁成功B执行完又执行DEL key释放锁……看到问题的严重性了吗锁的互斥性彻底被破坏了。A和B可能同时操作同一个资源数据被覆盖、重复下单、库存扣超什么事故都有可能发生。问题的根源在于删除锁之前没有确认这个锁是不是自己持有的。解决思路也很直接加锁时设置一个只有自己知道的唯一标识释放时先校验再删除。3.2 用Lua脚本保证检查与删除的原子性很多人的第一反应是if GET key uniqueValue then DEL key end逻辑上没毛病但这是两条命令中间如果有另一个线程把锁拿走了那这个判断就不准了。校验和删除必须是一个原子操作Redis里有一个机制专门干这个——Lua脚本。if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end用EVAL执行这段脚本Redis会保证脚本内所有命令的原子性。执行过程可以理解为get、比较、del这三步要么全部完成要么全部不执行中间不可能插入其他命令。加锁时的对应代码// 唯一标识可以用UUID 线程ID生成 String value UUID.randomUUID().toString() : Thread.currentThread().getId(); // 加锁 Boolean locked redisTemplate.opsForValue().setIfAbsent(key, value, 30, TimeUnit.SECONDS); // 释放锁 String script if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end; redisTemplate.execute(new DefaultRedisScript(script, Long.class), Arrays.asList(key), value);注意value的生成必须全局唯一且不可猜测目的是让每个客户端能识别自己持有的锁。用UUID是基本操作生产环境我习惯再拼上机器IP和线程ID排查问题会方便很多。这一步几乎是分布式锁面试必考点Lua脚本的原子性一定得讲清楚。4. 第三题锁超时后业务还没跑完怎么办看门狗续期机制设了过期时间防死锁结果业务执行时间超了锁提前释放照样出事。这是分布式锁方案里最核心的矛盾之一面试官必问。4.1 为什么固定过期时间是不完善的方案回到本质我们在用一个不可预知的时间上限来约束一个不可预知的执行过程。业务执行时间受很多因素影响数据库慢查询、下游接口超时、GC停顿、CPU竞争……任何一个环节抖动都可能让业务远远超过预设的过期时间。你设10秒业务跑了30秒锁在10秒时就没了后面的20秒全是裸奔。可能有人说那把过期时间设成1小时不就行了不行。持有锁的进程如果真挂了比如被kill -9锁要等1小时才能释放其他客户端干等一小时系统可用性直接崩掉。所以矛盾的本质是过期时间设短了 → 业务没跑完就丢锁过期时间设长了 → 进程挂了锁释放太慢。要同时解决这两个问题只能让锁的过期时间动态可续。4.2 看门狗原理后台续期到底做了什么Redisson的做法是引入一个“看门狗”Watchdog机制正常情况下加锁时不给锁设置固定的过期时间而是使用默认的30秒锁超时时间。同时启动一个后台定时任务每隔10秒也就是锁超时时间的1/3检查一次锁是否还持有着如果还持有就把过期时间重新刷回30秒。整个逻辑可以这样理解看门狗在锁的存活期内不断给它“续命”。只要持有锁的客户端还活着锁就永远不会因为超时而提前释放一旦持有者挂了看门狗线程也跟着没了锁自然在30秒后过期其他客户端就能拿到锁。时序上看是这样的加锁成功初始过期时间30秒10秒后看门狗检测到锁还在把过期时间重置为30秒20秒后再次续期重置为30秒……业务执行完释放锁看门狗任务取消如果进程中途崩溃看门狗线程同步消失锁最多30秒后自动释放这个方案同时解决了“业务超时不丢锁”和“进程挂了不死锁”两个问题。4.3 手动控制续期 vs 框架自动续期Redisson帮我们把续期逻辑做好了但我们也要理解这个机制不是免费的午餐自动续期期间如果Redis节点宕机看门狗线程会疯狂重试期间锁的状态是不确定的续期本身有网络开销高并发场景下频繁续期也会造成一定的Redis压力自动续期掩盖了业务执行过慢的问题有时候反而是隐患。更理想的情况是业务本身能预估自己的执行时间所以生产环境里我见过不少团队选择不用看门狗而是主动设置一个合理的过期时间同时把业务拆小确保每个锁的持有时间足够短。这也是一种合理的取舍核心是评估风险概率十万分之一的执行超时概率 vs 看门狗带来的复杂度哪个代价更高。实操心得如果你用Redisson的lock.lock(30, TimeUnit.SECONDS)这种带leaseTime参数的方式加锁看门狗是不会启动的。只有不传leaseTime的时候才会启用默认30秒看门狗续期。这个细节面试官经常挖坑得记住了。5. 第四题Redisson的可重入锁是怎么实现的深入源码看细节可重入性是Java并发里很自然的诉求。一个线程已经拿到锁了方法里又递归调用自己或者嵌套调用另一个需要同一把锁的方法如果锁不可重入就直接死锁了。Redis分布式锁同样要解决这个问题。5.1 为什么分布式锁也需要可重入举个例子你有这样一个业务方法public void processOrder(Long orderId) { String lockKey lock:order: orderId; RLock lock redissonClient.getLock(lockKey); lock.lock(); try { // 做订单主流程 doUpdateStatus(orderId); // 内部也要加同一把锁 sendMessage(orderId); } finally { lock.unlock(); } } public void sendMessage(Long orderId) { String lockKey lock:order: orderId; RLock lock redissonClient.getLock(lockKey); lock.lock(); try { // 发消息逻辑 } finally { lock.unlock(); } }如果锁不支持重入sendMessage里的加锁操作会因为锁已经被自己持有而死等程序直接卡死。所以可重入是真实业务场景的硬需求不只是面试考点。5.2 Hash结构 引用计数可重入锁的实现核心Redisson可重入锁的实现核心是Redis的Hash数据结构。锁的key对应一个HashHash里有多个field-value对field是客户端唯一标识UUID 线程IDvalue是重入次数加锁时执行类似这样的Lua脚本-- 锁不存在直接加锁重入次数设为1 if (redis.call(exists, KEYS[1]) 0) then redis.call(hset, KEYS[1], ARGV[1], 1) redis.call(pexpire, KEYS[1], ARGV[2]) return nil end -- 锁存在且是当前线程持有重入次数1 if (redis.call(hexists, KEYS[1], ARGV[1]) 1) then redis.call(hincrby, KEYS[1], ARGV[1], 1) redis.call(pexpire, KEYS[1], ARGV[2]) return nil end -- 锁被其他线程持有返回剩余过期时间 return redis.call(pttl, KEYS[1])这个脚本一次性做了三件事加锁、重入计数、刷新过期时间。释放锁的逻辑也是原子操作重入次数减1如果减到0就删除整个锁如果还没到0就只更新计数和过期时间。这就像Java里ReentrantLock的state字段每到一处需要锁的代码就state1退出就state-1减到0才真正释放。唯一区别是Java的state在内存里Redis的state在Hash里。5.3 锁等待和公平性公平锁与非公平锁的区别Redisson还提供了FairLock公平锁。非公平锁下客户端抢锁失败后会循环重试先到的不一定先拿到锁公平锁则把请求排队按顺序分配。公平锁用Redis的List结构维护一个等待队列加锁时如果锁被占用就把当前线程的请求信息push到队尾释放锁时从队头pop出下一个等待者通知它可以获取锁。这里有一个经典问题公平锁能不能保证全局严格公平答案是不能。因为分布式环境下存在网络延迟请求到达Redis的先后顺序不代表客户端发起请求的先后顺序。所以Redisson的公平锁只能保证在Redis节点上看到的请求顺序严格意义上的“全局公平”在分布式系统里是不存在的。注意面试时提到可重入锁一定要说清楚Hash结构和重入计数这两个关键点。只说“Redisson支持可重入”而不解释实现原理等于没说。6. 第五题Redis主从架构下锁会不会丢聊聊RedLock的争议这个问题在业界争论了很久但恰恰最能体现候选人对分布式系统一致性的理解。6.1 主从复制的异步延迟是锁丢失的根源经典场景我们用Redis做主从架构保证高可用Master挂了自动切换到Slave。但Redis的主从复制默认是异步的Master执行完写命令后立即返回Replica同步数据是后面的事。假设这样一个时间线客户端A向Master发送加锁命令Master写入成功还没来的及把这条写命令同步到SlaveMaster宕机了哨兵检测到Master故障把Slave提升为新的Master客户端B向新Master发送加锁命令新Master上压根没有A的锁记录加锁成功此时A和B同时持有锁互斥性被破坏这不是理论推演这是任何基于Redis主从架构的分布式锁方案都绕不开的隐患。6.2 RedLock算法到底是什么Martin Kleppmann《Designing Data-Intensive Applications》作者和Redis作者antirez曾就这个问题展开过著名论战。antirez给出的方案就是RedLock。算法的核心思路是不再依赖单个Redis节点而是部署N个官方建议5个完全独立的Redis节点。加锁时客户端向所有N个节点发起加锁请求每个节点都使用SET key value NX EX命令客户端计算获取锁消耗的时间如果满足以下两个条件才算加锁成功超过N/2 1个节点加锁成功加锁总耗时小于锁的有效时间加锁成功后锁的有效时间要减去加锁消耗的时间如果加锁失败向所有节点发起释放锁请求比如5个节点至少3个加锁成功才算成功。释放锁时向所有节点发送DEL命令带Lua脚本校验value。6.3 为什么很多团队不用RedLockRedLock看着很美好但实际落地时有一系列问题第一性能开销大。每次加锁要对5个节点发命令还要等待最慢的那个节点返回延迟增加明显。对于追求低延迟的业务来说代价太高。第二运维复杂度高。你需要维护5个独立的Redis实例没有主从关系、没有哨兵任何一个节点挂了都要人工介入。相当于是为了锁的可靠性专门维护一套比业务Redis更复杂的架构。第三算法本身仍有争议。Martin Kleppmann提出了一个GC停顿导致的时钟问题客户端A加锁成功后发生长时间GCGC期间锁过期了GC恢复后A认为自己还持有锁继续操作共享资源。而Redis的过期时间依赖系统时钟如果时钟发生跳跃比如NTP同步RedLock也不能保证绝对安全。所以结论是RedLock在某些极端场景下仍然不是绝对安全的方案。如果业务对锁的可靠性要求真的极高比如涉及资金操作那Redis分布式锁本身可能就不是正确的选择应该考虑ZooKeeper或etcd这类带强一致性和线性一致性的协调服务。这也是面试里最能拉分的点能说出RedLock的适用边界和争议说明你真的思考过分布式锁的可靠性问题而不是停留在会用API的层面。7. 第六题Redis分布式锁的性能优化分段锁的思路从哪来面试进行到这里如果前面的问题都答顺了面试官大概率会抛出一个开放性问题高并发场景下分布式锁太慢了怎么优化7.1 锁粒度与并发量的关系一个很直观的公式锁的粒度越细能并行的业务就越多。假设你要操作一个库存锁的key是lock:stock:1所有对库存1的操作都串行执行。如果你把锁的粒度拆到lock:stock:1:segment:1、lock:stock:1:segment:2……每个段维护一部分库存那不同段的操作可以并行并发量直接翻了好几倍。这就是分段锁的整体思路本质上和ConcurrentHashMap的分段锁思想如出一辙。从单机并发走向分布式并发底层思路是通用的减少锁竞争提高资源利用率。7.2 高并发扣减库存用分段锁但别忘了超卖问题分段锁在扣减库存场景下需要注意一个细节把库存分成N段每段独立加锁扣减但如果整段库存都扣完了请求就需要去其他段寻找剩余库存。如果所有段都扣完了要返回库存不足。实现上大概是这样// 库存分成10段 public static final int SEGMENT_COUNT 10; public boolean deductStock(int productId, int quantity) { // 先尝试所有分片 for (int i 0; i SEGMENT_COUNT; i) { String lockKey lock:stock: productId :segment: i; RLock lock redissonClient.getLock(lockKey); lock.lock(); try { int stock getSegmentStock(productId, i); if (stock quantity) { reduceSegmentStock(productId, i, quantity); return true; } } finally { lock.unlock(); } } return false; }但这个写法有个问题如果9个分片都被扣完了第10个分片剩一点库存但每次请求都是从第1个分片开始找会把前9个分片都遍历一遍才能走到第10个。随着分片被扣完查找效率越来越低。优化方案是加一层路由记录当前哪个分片还有库存每次直接跳到有库存的分片。或者按固定路由规则把请求散列到不同分片减少无谓的遍历。注意分段锁的前提是业务允许分段。库存数据天然可以分段但比如“用户积分变更”“订单状态流转”这类强一致性的业务胡乱分段是有风险的。分段锁优化的是并发吞吐代价是实现复杂度显著上升不是所有场景都适合。7.3 锁之外的方向能不能根本上避免锁聊到优化很多候选人只顾着讲分段锁、降低锁粒度但真正的资深工程师还会考虑另一个方向这个锁真的非加不可吗很多“分布式锁”保护的业务本质上只是需要一个“幂等判断”。比如防止重复下单、防止重复回调。这类场景可以用数据库唯一索引、Redis的Setnx幂等标记、消息队列的去重机制来解决根本不需要加锁。举个最简单的例子防止用户重复提交订单方案A分布式锁拿到锁才能下单方案B订单表加一个唯一索引user_id biz_id插入冲突就直接返回“重复提交”方案B的实现复杂度远低于分布式锁性能也更好但很多人一上来就想锁。面试官问到优化时如果能说出**“优先考虑能否用幂等设计规避锁”**这个思路会让人觉得你不只是个会用工具的而是真的在设计系统。8. 第七题Redis分布式锁和ZooKeeper锁、etcd锁怎么选面试官问这个问题不是真的让你背对比表格而是考察你在技术选型时的权衡能力。8.1 三种最主流分布式锁方案的原理对比这里稍微展开一下ZK和etcd的实现原理ZooKeeper分布式锁基于临时顺序节点实现。客户端在锁目录下创建临时顺序节点然后检查自己创建的节点是不是序号最小的。如果是说明拿到锁如果不是监听前一个节点的删除事件前一个释放后重新检查。核心特性是临时节点。客户端断开连接后ZK会自动删除对应节点不用依赖超时时间天然不死锁。同时ZK的写请求通过Zab协议保证线性一致性锁的互斥性更可靠。etcd分布式锁etcd基于Raft协议实现线性一致性和租约机制。加锁时创建key并绑定lease过期未续约自动删除同时通过Revision机制实现排队客户端拿到锁后短暂续约直到业务完成。Redis锁结构最简单性能最高但主从切换时存在锁丢失的风险窗口。8.2 选择的核心指标一致性与可用性的平衡直接给一个实际选型的参考标准维度RedisZooKeeperetcd一致性保证单节点强一致主从切换时有窗口线性一致性线性一致性锁丢失风险主从切换丢锁极低极低性能加锁延迟微秒到毫秒级毫秒级毫秒级死锁处理过期时间临时节点自动清理租约自动过期运维成本低高中适用场景大多数业务场景严格要求一致性的场景云原生、K8s生态我还想多说一句很多时候选ZK不是因为它“好”而是因为你的系统里已经部署了ZK。同样的道理你的基础设施是K8s加etcd那用etcd实现分布式锁就比额外维护一套ZK更合理。技术选型不能脱离现有技术栈。实操心得如果业务核心是秒杀、库存这类高吞吐场景我一般推荐Redis锁加合理的过期时间与重试机制性能好落地快。如果业务核心是分布式任务调度、配置变更这类对一致性要求极高的场景那用ZK或etcd更稳。钱和机器都是小事出一次数据不一致的事故代价才大。9. 第八题分布式锁的完整实现需要哪几个模块系统性地聊方案很多候选人能答出Redis命令、能说出Redisson但让他从零设计一个分布式锁组件就乱了。这题其实是在考架构能力和工程素养。9.1 加锁模块、续期模块、释放模块的职责划分一个完整的分布式锁组件至少应该有四个模块加锁模块负责执行加锁命令处理加锁失败后的重试逻辑。需要支持阻塞等待和超时控制不能无限重试。续期模块负责看门狗续期。需要处理续期失败的情况如果Redis连接断了续期失败一定次数后要考虑主动释放锁避免变成僵尸锁。释放锁模块负责安全释放锁。必须带唯一标识校验使用Lua脚本保证原子性同时要做好幂等——锁已经过期或被别人获取时释放不能影响到别人的锁。状态管理模块负责维护锁的本地状态比如当前线程是否持有锁、重入次数、锁的剩余过期时间等。还要处理锁的“传播”线程池异步任务中锁怎么传递这都是工程细节。9.2 几个容易被忽略的工程细节模块划分写完还有几个边角料问题特别能看出工程能力锁的续约信号续期是个后台任务但什么时候该停如果业务代码执行完了释放锁和取消续期之间有一个时间窗口可能出现续期任务把一把新的锁刷新了的情况。Redisson的做法是释放锁时同时取消续期任务并且续期脚本里也会校验持有者身份。锁的等待队列加锁失败后是立刻返回失败还是阻塞等待实际业务里“拿不到锁就放弃”通常不可接受所以需要一个阻塞等待机制。简单做法是循环重试复杂做法是利用Redis的Pub/Sub订阅锁释放事件被唤醒后再尝试加锁。Redisson用的是第二种。锁的可观测性生产环境里分布式锁出问题最难排查的是“到底谁持有锁”。所以好的锁组件要记录持有者的业务身份、持有时间、获取次数。我见过很多公司最后栽在锁的排查上加锁的日志不规范线上出问题只能靠猜。锁的优雅降级Redis挂掉时分布式锁用不了业务是全链路熔断还是降级为本地锁这个问题没有标准答案但必须提前设计。比如非核心链路的锁Redis挂掉时可以降级为不进锁直接放行但要接受极端情况下的数据风险。10. 面试实战怎么把这8道题串成一个连贯的答案最后聊点实际的。面试的时候不要面试官问一句你答一句那样很容易陷入“背诵知识点”的陷阱。更好的策略是把相关题目串起来展示你的系统思考。10.1 从加锁到释放的完整链路闭卷演练如果面试官问你“怎么用Redis实现分布式锁”你可以这样组织回答我会分三步。第一步加锁要有原子性和自动过期能力用SET key uniqueValue NX EX 30一条命令实现第二步释放锁要防止误删用Lua脚本先校验持有者身份再删除第三步业务执行可能超过过期时间需要看门狗续期机制。这三步对应的就是分布式锁的三个核心模块加锁、安全释放、续期。然后再把这个链路延伸到高可用场景主从架构下存在锁丢失风险所以要么接受这个风险并用合理的过期时间限制风险窗口要么用RedLock或者改用ZK/etcd。这样一段话把前四道题全串起来了而且逻辑连贯面试官可以顺着你的思路追问下去。10.2 追问环节怎么随机应变面试官最常用的追问方式“Redisson为什么用Hash结构不用String”——答需要存持有者和重入次数两个维度Hash天然合适“看门狗续期失败但锁还持有怎么办”——答本地内存维护一个锁状态线程连续续期失败N次主动中断业务或至少记录告警日志避免锁信息在集群中长时间残留“你们线上真的遇到过失锁问题吗”——答遇到过最典型的是业务代码在锁保护外又做了一次RPC导致整体耗时超过过期时间后来通过监控锁持有时间分布才定位到“Redis锁过期了业务还在跑数据已经不一致了怎么办”——答这种问题锁本身救不了要做的是在业务代码里加乐观锁校验比如更新数据时带上版本号版本不匹配就抛异常这些问题如果你都能接住面试基本上就从“考察知识点”变成了“交流工程经验”完全是另一个level。10.3 简历上写了Redis分布式锁项目里怎么落地才算数最后说点写在简历和项目经验里的建议。现在很多人简历上都写“使用Redis分布式锁解决了XX问题”但面试官一听就知道你是不是真的做过。有含金量的描述一般是这样的有异常处理锁获取失败后的重试策略是什么、重试上限是多少有压测数据锁的平均耗时、P99耗时是多少加锁前和加锁后对比有故障预案Redis挂了怎么办、锁超时了怎么办、业务执行时间和锁过期时间的比例关系是什么有踩坑记录遇到过什么坑、怎么定位的、怎么修复的这个最能体现真实经验比如“我们对订单扣减接口做了分布式锁压测TPS从2000提升到8000过程中发现锁过期时间设置过短导致偶发重复扣减最后通过看门狗续期和分段锁解决了”——这种表述就很有说服力。写在最后Redis分布式锁面试题几乎所有Redis相关的面试都会涉及但很多人的认知都停留在“背命令”的层面。说实话那些基础命令五分钟就能学会真正拉开差距的是对分布式环境下各种异常情况的判断和处理。以我自己的经验这类问题在面试中最好的状态不是“背得很好”而是能结合自己做过的项目把加锁、续期、释放、高可用、性能优化这条链路讲成一个完整的故事。面试官也是从业者他听得出来你是真踩过坑还是只看过教程。如果你正在准备面试不妨拿这8道题做一个自测SET NX为什么比SETNX加EXPIRE好Lua脚本在释放锁里起什么作用看门狗续期的实现原理是什么主从切换为什么可能导致锁丢失RedLock的争议点在哪分段锁什么时候用三种分布式锁方案的选型标准和依据是什么一个完整分布式锁组件要包含哪些职责这8个问题能不看资料答出来Redis分布式锁这一块就问题不大了。真到了生产环境多留个心眼记录加锁耗时、监控锁持有时间这些顺手做的事总有一天会在关键时刻帮你避开一次线上事故。