前言
在分布式系统中,多个服务实例共享资源时需通过分布式锁保证操作原子性,Redis凭借高性能、高可用特性成为实现分布式锁的主流方案。本文从核心原理、关键实现细节、常见问题及面试高频考点展开解析,帮助理解Redis分布式锁的设计逻辑与实践要点。
在后端面试中,Redis分布式锁堪称“必考题之王”——从初级工程师到架构师,几乎每个技术面都会被追问。不少候选人能说出SET NX EX命令,却栽在“脑裂怎么解决”“锁过期了怎么办”上,错失心仪offer。今天这篇文章,帮你吃透Redis分布式锁的核心逻辑、高频考点和避坑要点,让你面对追问时游刃有余。
一、先搞懂:Redis分布式锁到底用来解决什么问题?
在单体应用里,用Java的synchronized或ReentrantLock就能保证线程安全;但到了分布式系统,多个服务实例共享同一资源(比如库存扣减、订单创建),本地锁完全失效——这时候就需要“分布式锁”,让多个服务像排队一样,同一时间只有一个能操作资源。
Redis凭借高性能(单机QPS万级)、支持原子操作的特性,成为实现分布式锁的首选方案。它的核心逻辑特别简单:用一个唯一的Redis key当“锁”,谁能成功创建这个key,谁就拿到锁;操作完资源后,再删除这个key释放锁。
篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题& G中hao 小琪码料库
二、面试必问的3个核心考点,答案直接背!
考点1:最基础的加锁命令,为什么必须用SET NX EX?
很多面试候选人会说“用SETNX加锁,再用EXPIRE设过期时间”,但这恰恰是第一个坑!
因为SETNX和EXPIRE是两步操作,不是原子的——如果SETNX成功后,服务突然宕机,EXPIRE没执行,这个锁就会永久存在,导致其他服务永远拿不到锁(死锁)。
正确答案:用Redis 2.6.12以上版本支持的SET命令多参数组合,把“加锁+设过期时间”变成原子操作:
# key=锁名称(如lock:stock),value=唯一标识(IP+线程ID)
# NX=仅当key不存在时创建,EX=设10秒过期时间
SET lock:stock 192.168.1.100:thread1 NX EX 10
这句话一定要记牢:NX保证互斥(同一时间只有一个人能加锁),EX避免死锁(服务宕机后锁会自动释放),原子操作解决“两步走”的风险。
考点2:释放锁时,直接DEL命令行吗?
绝对不行!这是第二个高频坑。
比如:服务A加的锁过期了,Redis自动删除了key;这时候服务B成功加锁,开始执行业务;但服务A恢复后,直接用DEL命令删除了锁——相当于服务A误删了服务B的锁,导致多个服务同时操作资源,锁彻底失效。
正确答案:释放锁必须先“校验身份”,再“删除锁”,而且这两步要原子化。解决方案是用Lua脚本:
# 先判断锁的持有者是不是自己(对比value),是就删除
if redis.call("GET", KEYS[1]) == ARGV[1] then
return redis.call("DEL", KEYS[1])
else
return 0
end
原理:Redis执行Lua脚本时会阻塞其他命令,确保“校验+删除”不会被打断,彻底避免误删他人锁的问题。
考点3:Redis主从架构下,分布式锁有什么风险?怎么解决?
这是区分候选人“基础款”和“进阶款”的关键问题,90%的初级工程师答不上来。
风险点:Redis主从同步是异步的。比如服务A在主节点加锁成功,但主节点还没把这个锁同步到从节点就宕机了;从节点升级成新主节点后,因为没同步到锁信息,服务B就能成功加锁——这时候出现“两把锁”,也就是“脑裂”问题。
正确答案:用Redlock(红锁)算法。核心逻辑是:
1.部署至少3个独立的Redis节点(无主从关系,各自独立);
2.加锁时,同时向这3个节点发送SET NX EX命令;
3.只有当超过半数节点(比如3个节点中至少2个) 加锁成功,才认为整体加锁成功;
4.释放锁时,向所有节点发送释放命令。
原理:通过“多节点投票”,即使某个节点宕机,只要多数节点正常,就能保证锁的唯一性,降低脑裂风险。生产中不用自己实现,直接用Redisson组件的RedissonRedLock即可。
三、实战避坑:2个生产环境常见问题,面试提一句加分!
1.问题1:业务执行时间超过锁过期时间怎么办? 比如锁设了10秒过期,但业务需要20秒才能执行完——锁过期后,其他服务会加锁,导致数据冲突。 解决方案:用“锁续约”机制(比如Redisson的“看门狗”线程)。业务执行过程中,看门狗线程每隔3秒检查一次:如果当前服务还持有锁,就把锁的过期时间延长到10秒,直到业务执行完再释放锁。
2.问题2:分布式锁支持重入吗?怎么实现? 基础版的SET NX EX不支持重入(同一线程多次加锁会失败,比如递归调用场景)。 解决方案:用可重入锁设计。在value中存储“持有者标识+重入次数”,比如value=192.168.1.100:thread1:2(最后一位是重入次数)。加锁时:
• 如果是新线程,执行SET NX EX;
• 如果是当前持有锁的线程,直接把重入次数+1; 释放时:
• 重入次数-1,当次数减到0时,再执行DEL命令删除锁。 生产中直接用Redisson的RLock,开箱即用支持重入。
四、总结:面试应答框架,直接套用!
当面试官问“Redis如何实现分布式锁”时,别上来就说命令,按这个逻辑答,条理清晰还加分:
1.先讲核心场景:分布式系统共享资源需互斥,Redis因高性能成为首选;
2.再讲基础实现:用SET NX EX原子加锁,Lua脚本原子释放,避免死锁和误删;
3.然后讲进阶风险:主从架构的脑裂问题,用Redlock算法解决;
4.最后提实战优化:锁续约解决过期问题,可重入锁支持递归场景,生产用Redisson组件。
记住:面试不是背命令,而是讲清“是什么、为什么、有什么风险、怎么解决”。把这篇文章的考点吃透,下次再被问Redis分布式锁,你就是面试官眼里“懂原理、能落地”的靠谱候选人!