当前位置: 首页 > news >正文

Redis分布式锁:8个常见面试题

Redis分布式锁:8个常见面试题

📌 1. 为什么需要分布式锁?

场景:双11秒杀,10000人抢100个商品

  • 单机锁不行:秒杀系统有10台服务器,每台都有自己的内存,锁不住其他服务器
  • 需要共享的锁:所有服务器都能访问的锁 → Redis分布式锁

📌 2. 最简单的分布式锁怎么写?(错误示范)

// ❌ 新手最容易写的错误代码publicbooleanlock(Stringkey){Stringresult=jedis.setnx(key,"1");// 尝试加锁returnresult==1;// 1表示加锁成功}publicvoidunlock(Stringkey){jedis.del(key);// 删除锁}

⚠️ 问题在哪里?

  1. 死锁风险:如果程序崩溃,锁永远不释放
  2. 误删别人锁:A的锁超时释放,B获得锁,A醒来删了B的锁

📌 3. 怎么设置过期时间?(还是不对)

// ❌ 这个也有问题publicbooleanlock(Stringkey,intseconds){// 两步操作:1.加锁 2.设置过期时间Longresult=jedis.setnx(key,"1");if(result==1){jedis.expire(key,seconds);// 设置过期returntrue;}returnfalse;}

⚠️ 问题:两步不是原子的!

  • 如果setnx成功,但expire前程序崩溃 → 锁变永久的!

📌 4. 正确写法是怎样的?

// ✅ 正确的加锁(一步完成)publicbooleanlock(Stringkey,Stringvalue,intseconds){// 一条命令完成:加锁+设置过期时间Stringresult=jedis.set(key,value,"NX","EX",seconds);return"OK".equals(result);}// ✅ 安全的解锁publicvoidunlock(Stringkey,Stringvalue){// 用Lua脚本保证原子操作:检查值再删除Stringscript="if redis.call('get', KEYS[1]) == ARGV[1] then "+" return redis.call('del', KEYS[1]) "+"else "+" return 0 "+"end";jedis.eval(script,1,key,value);}

✅ 关键点:

  1. 一条命令SET key value NX EX seconds
  2. value用唯一标识:UUID或线程ID
  3. 原子删除:用Lua脚本检查再删除

📌 5. 锁的value为什么不能用"1"?

// ❌ 错误:大家value都一样jedis.set("lock","1","NX","EX",10);// ✅ 正确:每人一个唯一标识StringmyId=UUID.randomUUID().toString();jedis.set("lock",myId,"NX","EX",10);

场景演示:

线程A:获得锁,value="A123",超时10秒 线程A:执行了15秒(锁在第10秒已过期) 线程B:获得锁,value="B456" 线程A:终于执行完,要删除锁 → 删了线程B的锁!❌

📌 6. 业务没执行完,锁过期了怎么办?

方案1:设置合理的过期时间

// 评估业务时间,设置更长过期jedis.set("lock",uuid,"NX","EX",30);// 设置30秒

方案2:自动续期(看门狗)

// 启动一个线程,定期续期newThread(()->{while(业务没执行完){Thread.sleep(8000);// 8秒续一次// 如果是自己的锁,就延长过期时间jedis.expire("lock",10);}}).start();

📌 7. Redis主从切换会丢锁吗?

会!这是Redis分布式锁的最大问题

场景:

1. 线程A在主节点获得锁 2. 主节点宕机(锁数据还没同步到从节点) 3. 从节点变成新主节点 4. 线程B在新主节点获得"相同"的锁 结果:A和B同时持有了锁!

解决方案:

  1. 用RedLock算法:在多个Redis实例上加锁
  2. 用ZooKeeper:更适合分布式锁
  3. 接受风险:业务上做幂等处理

📌 8. 实际开发用什么?(不要造轮子!)

// 使用Redisson框架(最省心)RedissonClientredisson=Redisson.create();RLocklock=redisson.getLock("myLock");try{lock.lock();// 加锁(自动续期)// 执行业务...}finally{lock.unlock();// 解锁}

📊 面试对比表

方案优点缺点适用场景
Redis单节点简单、快主从切换丢锁测试环境、不重要的锁
RedLock相对可靠实现复杂、性能差重要的业务锁
Redisson功能全、自动续期依赖框架推荐的生产方案
ZooKeeper最可靠性能较差强一致性的场景

❓ 面试常见问题

Q1: “说一下Redis分布式锁的实现原理”

:“用SET命令的NX和EX参数,NX保证只有一个能设置成功,EX设置过期时间防止死锁。删除时用Lua脚本原子操作,避免删别人锁。”

Q2: “Redis锁和ZooKeeper锁的区别?”

  • Redis:AP系统,性能好,但可能丢锁
  • ZooKeeper:CP系统,可靠但性能差
  • 选择:要高性能用Redis,要可靠性用ZooKeeper

Q3: “怎么实现可重入锁?”

:“在value里记录线程ID和重入次数。加锁时如果是同一线程,计数+1;解锁时计数-1,计数为0才真正删除锁。”

📝 记住三句话

  1. 加锁要原子SET key uuid NX EX seconds
  2. 解锁要安全:用Lua脚本先检查再删除
  3. 生产别造轮子:直接用Redisson

🎯 快速检查清单

你的分布式锁:

  • 设置过期时间了吗?
  • value是唯一的吗?
  • 删除前检查value了吗?
  • 考虑锁续期了吗?
  • 知道主从切换会丢锁吗?

满足这5条,面试官就难不倒你了!

http://www.jsqmd.com/news/308660/

相关文章:

  • Java毕设选题推荐:基于springboot+vue的电影院票务预定系统基于Spring Boot的在线票务预订平台【附源码、mysql、文档、调试+代码讲解+全bao等】
  • DevOps实战系列 - 使用Arbess+GitLab实现.Net 项目自动化构建并主机部署
  • DevOps实战系列 - 使用Arbess+Gitee+PostIn实现自动化部署及接口自动化测试
  • DevOps实战系列 - 使用Arbess+GitLab实现Java项目自动化构建并多主机集群部署
  • DevOps实战系列 - 使用Arbess+GitHub实现Java项目自动化Docker构建并部署
  • 计算机网络经典问题透视:手机通过Wi-Fi接入到互联网是没有流量因而是免费的吗?
  • 计算机网络经典问题透视:不买SIM卡,只用Wi-Fi,我们能连接世界吗?
  • springboot-nodejs高校社团迎新平台vue
  • 神经网络的简单实现
  • 开发Agent自动玩手机游戏,附代码
  • 导师严选2026 一键生成论文工具TOP8:本科生毕业论文写作全攻略
  • 手把手一次学会20个电脑冷知识!ToDesk加持电脑也能变手机?
  • 2026年液冷板/水冷板厂家实力推荐榜:高效散热与精密工艺,源头工厂技术解析与选购指南
  • 2026最新三亚定制游旅行社TOP5评测!专业服务+品质保障权威榜单发布,打造独特三亚旅行体验
  • 2025年市场上有实力的地铁广告厂家需要多少钱,商圈广告/明星应援广告/电梯广告/电梯电子屏广告,地铁广告品牌需要多少钱
  • KGPS中频炉全球与国内领军企业推荐
  • 职场经验:收入vs繁忙vs身体差
  • 深度测评9个AI论文平台,本科生搞定毕业论文+格式规范!
  • 2026年靠谱的移民申请AI服务公司盘点,聚焦移民规划AI解决方案
  • 松果获客AI作为移民行业人工智能公司推荐,看哪家口碑好?
  • 2026年测试员比开发者更稀缺:专业洞察与应对策略
  • 2026年趋势:开发者跨界医疗AI的黄金路径
  • 山东菏泽测试员:我是如何靠AI逆袭年薪60万的?
  • 山东菏泽样本:小城开发者的全球化接单攻略
  • 10分钟冥想:提升软件测试效率的2026新科学
  • 从测试员到CTO:非技术技能的晋升密码
  • 2026口碑好的包装机厂家榜:选对能省30%成本?
  • 在远程团队中崛起:测试员的领导力成长记
  • 动态磁盘转化成基本磁盘
  • Android AI 实战:手把手教你用 Compose + CameraX 跑通 YOLOv8