Redis 实现分布式锁时可能遇到的问题有哪些?

Redis分布式锁遇到的问题(面试Markdown结构化)

1. 加锁不原子,出现死锁

  • 问题:分开执行set和expire,set成功后Redis宕机,没设置过期时间,锁永久存在,其他线程永远拿不到锁。
  • 解决:使用set key value NX EX一条命令原子加锁。

2. 锁被其他客户端误删除

  • 问题:业务执行时间超过锁过期时间,锁自动释放;别的线程抢到锁,原线程执行del,直接删掉别人持有的锁。
  • 解决:加锁存入客户端唯一标识;释放锁用Lua脚本,校验value属于自己才删除,禁止直接del。

3. 业务没执行完,锁提前过期释放

  • 问题:业务逻辑耗时 > 锁TTL,锁过期释放,多个线程同时执行业务,并发冲突。
  • 解决:看门狗续期(Redisson),业务没结束就不断延长锁过期时间;不要设置过小锁超时。

4. 主从架构下锁丢失(单机最大坑)

  • 问题:master加锁成功,锁还没异步同步到slave,master宕机,slave晋升为主节点,锁消失,多个客户端获取锁。
  • 解决:
    • 方案1:RedLock红锁(有缺陷,很少线上使用)
    • 方案2:强一致性场景改用Zookeeper/Etcd

5. RedLock自身带来的问题

  1. 时钟漂移、NTP时间跳变,导致锁提前失效
  2. 客户端GC停顿、网络延迟,锁过期,依然会锁失效
  3. 需要维护多套独立Redis节点,性能差、运维成本高

6. 锁不可重入

  • 问题:同一个线程,递归/嵌套再次获取同一个锁,直接加锁失败,造成自己把自己阻塞。
  • 解决:Redisson内部实现可重入锁,记录线程持有计数;自己手写很难实现。

7. 锁等待、死锁(线程A拿锁,线程B无限阻塞)

  • 问题:获取锁失败后,如果无限循环自旋,会大量消耗CPU,压垮Redis。
  • 解决:设置最大等待时间,加退避重试,不要死循环抢锁。

8. 网络抖动问题

  • 问题:Redis已经拿到锁,网络超时,客户端没收到返回;客户端认为加锁失败,实际锁已经存在,资源死锁。
  • 解决:设置合理的网络超时,失败主动释放所有节点残留锁。

总结

手写Redis分布式锁很难做到完备,会踩原子性、误删、锁过期、主从丢锁、不可重入、自旋风暴这些坑;开发中优先直接使用Redisson,不要自己实现。

如果业务对互斥要求极高,不建议用Redis分布式锁。

相关推荐
李兆龙的博客6 小时前
问津集 #26:Lakebase——Postgres 的版本化页面存储、数据库分支与计算弹性
数据库
倔强的石头_8 小时前
聊聊金仓KFS:一款把数据同步软件做扎实的产品
数据库
闲云野鹤在人间8 小时前
MySQL|从理论、安装、备份到主从复制、MHA高可用详解
linux·运维·数据库·mysql·云计算
禾小西8 小时前
Redis:从两大维度和三大主线建立知识体系
数据库·redis·缓存
禾小西9 小时前
Redis 数据结构:快速的 Redis 有哪些慢操作?
数据结构·数据库·redis
数据库小学妹9 小时前
数据共享交换平台选型:交换方式对比与避坑指南
数据库·信创·数据同步·数据交换平台·政务数据共享·数据共享交换平台·数据库底座
loong_XL11 小时前
决策模型做内容安全检测:从踩坑到上线
数据库·安全·jev·决策模型
这个DBA有点耶11 小时前
数据库双轨并行实战:全量并行策略、增量延迟控制、双向回切与一致性校验
数据库·架构·dba
adinnet202612 小时前
保单、赔付与渠道问数:保险经营数据如何实现按需查询
大数据·数据库·人工智能
云贝贝贝12 小时前
PostgreSQL 分区表:从设计到运维,大表不再卡
运维·数据库·postgresql