Redis分布式锁不止set nx那么简单

能进大厂的 Redis 分布式锁,和你现在写的差在哪? Redis 分布式锁几乎是每个 Java 社招面试都会问到的高频题,但真正理解它的人并不多。很多人只会背 setnx,却答不清楚死锁、误删锁和并发边界问题。本文用一个贴近真实业务的故事,带你从“踩坑”的角度,把 Redis 分布式锁一次讲透,帮你真正应对面试与实战。 阅读详情

01 引言

在分布式的场景下,分布式锁是经常遇到的。而Redis的分布式锁用的较为频繁。但是Redis的分布式锁是怎么实现的呢?

在我们公司的业务代码中经常会出现这样的代码:

image-20251107140655066

或者

这样的代码用来当分布式锁或者处理幂等性等问题。这样有没有什么问题呢?

我想应该不止我们公司有人写成那样的代码吧!因为我们公司的并发不大,反正遇到的问题并不多。我们一起来探索一下吧!

02 分布式锁

分布式锁大家已经耳熟能详了,其核心特性无非就那么几个:

  • 互斥性:同一时刻只有一个客户端能持有锁
  • 安全性:锁只能由持有者释放,防止误删
  • 容错性:在部分节点故障时仍能正常工作
  • 避免死锁:必须有超时机制,防止客户端崩溃导致锁无法释放

我们根据以上特性分析一下上面代码中setnx+expire和set可能会出现什么样的问题。

2.1 setnx + expire

我们还原一下伪代码:

let redisService = xxxxx;
try{
    if (1 == redisService.setnx(key, value)){
        redisService.expire(key, expire);
        // 后续业务....
    }
    
}finally {
    redisService.delete(key);          
}

setnx固然可以是保持互斥性,但是和expire方法是两个独立的方法。所以如果expire方法异常,就会导致setnx设为永久有效。虽然有redisService.delete兜底,但是如果出现服务器宕机,此处的代码几无法执行,而从造成死锁。

如果执行业务逻辑的时候由于网络抖动,分布式锁已经过期,业务还在阻塞中。这时第二个请求相同的Key就可以加锁了,业务逻辑还没有执行完,结果第一个方法的恢复正常执行了delete(key)的操作,就会误删掉第二个请求的key,也就是释放了第二个请求的锁。

还有就是由于业务复杂导致分布式锁过期,业务还没有执行完,就会自动释放锁。导致加锁失败。

简单总结问题:

  • setnx和expire没有原子性操作
  • 释放锁没有校验是不是自己的锁,可能会误删锁。
  • 锁没有续约

2.2 set

set的方法是setnx + expire的结合,属于原子性操作。我们来看看伪代码:

let redisService = xxxxx;
try{
    if ("OK" == redisService.setnx(key, value, "NX", "EX", 600)){
        // 后续业务....
    }
    
}finally {
    redisService.delete(key);          
}

这个方法比上面的好一点,保证了原子性。但是其他两个问题依然存在:

  • 释放锁没有校验是不是自己的锁,可能会误删锁。
  • 锁没有续约

2.3 优化

误删锁的问题容易解决,只需要在删除的时候,判断存入的Value是自己的Value即可。

String value = "xxxx";
if (value.equals(redisService.get(key)) {
    redisService.delete(key); 
}

锁的续约如何解决呢?我们耳熟能详的看门狗模式。简单来说就是启用一个线程,隔一段时间就去看当前客户端的Key有没有过期,快过期的时候,重新设置时间。

伪代码如下:

new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                if (redisService.expire(key) <= expire) {
                    // 续约
					redisService.expire(key, expire2);
                }
            }
        }, 10);

思路也是比较简单。但是难点就在续约的时间,检查锁是否过期的间隔。我们将通过几个开源案例了解一下具体的实现。

03 Lock4j

3.1 简介

Lock4j是一个分布式锁组件,其提供了多种不同的支持以满足不同性能和环境的需求,立志打造一个简单但富有内涵的分布式锁组件。其特性就是简单易用,功能强大,扩展性强,支持redission,redisTemplate,zookeeper。可混用,支持扩展。

该开源项目来自苞米豆社区,你可能没听过。但是Mybatis-Plus你一定听过,它的作者和Lock4j的作者是同一人。

3.2 RedisTemplate

StringRedisTemplate和RedisTemplate是SpringBoot自带的客户端。我们看看Lock4J是如何实现分布式锁的。

实现类:com.baomidou.lock.executor.RedisTemplateLockExecutor

从源码可以看出,对于分布式锁的加锁、释放锁以及续约,为了保证原子性,都是用了Lua脚本。

加锁

通过ForkJoin线程池启动线程,加锁后根据参数执行是否续约。然后等待加锁的结果,并返回加锁的结果。

释放锁

释放锁就比较简单了。根据Lua脚本,先查询对比,然后根据结果删除对应的key。

续约

同样是先获取判断,然后在续约。都是通过Lua脚本处理的。但是要这里要说的是,通过new Timer()启动了一个调度任务,每到过期时间的三分之一,就会触发续约逻辑。

问题

我们会发现,在续约的时候启动的线程资源并没有被回收。如果加锁的线程很多,就会有很多任务在空跑。消耗了资源。小编在Gitee也返现了有人提出这个问题,并尝试优化:

https://gitee.com/baomidou/lock4j/issues/IBIE4A

3.3 Redisson

Redisson同样是一款经典的Redis客户端。该客户端自己实现分布式锁,并启用了看门狗模式。

加锁

直接通过RedissonClient客户端获取锁并尝试加锁,返回加锁结果。

释放锁

判断线程是否持有,有的话就释放锁。

续约

几乎没有代码。因为Redisson本身自带看门狗机制。我们追一下Redisson的源码。当执行lock()->tryAcquire()->tryAcquireAsync()->scheduleExpirationRenewal()->renewExpiration()

①我们可以看到依然通过TimerTask这样的调度任务。

②不续约的话就释放资源:

zookeeper的分布式锁我们暂且讨论,因为不是基于Redis的。

04 小结

分布式锁不是想象的那么简单,但也不是那么复杂。使用Redis分布式锁,直接Redssion客户端,使用完善的功能。使用Redis的Set或者setnx,可以满足日常并发不大的场景,设置合理的过期时间,就能够满足大部分的场景了。

【坑】分布式锁之误 “解锁”(Redis为例) 基于Redis的分布式锁有各种实现。。。 阅读详情

相关推荐

C++分布式锁实现:Redis方案与工程实践详解

在分布式系统中,当多个进程或服务需要协调访问共享资源时,互斥访问机制成为核心需求。其基本原理是通过一个全局可见的协调服务,确保在任意时刻只有一个客户端能执行关键操作。这项技术的核心价值在于保障数据一致性与系统正确性,尤其在高并发场景如电商秒杀、金融交易中至关重要。常见的实现方案包括基于Redis、ZooKeeper和etcd等,它们各自在一致性模型和性能上有所权衡。其中,基于Redis的SET NX PX命令配合Lua脚本是实现分布式锁的流行方案,因其高性能和简洁性被广泛采用。在实际的C++工程实践中,需要

weixin_34253126的博客 258

Redis 分布式锁怎么实现?SET NX、Lua、Redisson 与 WatchDog

本文详细介绍 Redis 分布式锁的实现原理,包括 `SET NX PX` 原子加锁、唯一 Token 与 Lua 脚本安全释放锁,以及 Redisson 的可重入锁和 WatchDog 自动续期机制。同时分析锁提前过期、误删锁、主从切换等问题,并介绍 Fencing Token、数据库约束和幂等性设计,帮助理解 Redis 分布式锁的应用场景与可靠性保障。

2403_87560480的博客 734

@Autowired(required=false)注入注意的问题

1、前言在使用spring开发过程中,我们基本上都是使用@Autowired这个注解,用来注入已有的bean。但是有些时候,会注入失败。当我们加上参数(required=false)就能解决。今天整理一个我在实际开发中的例子2、required属性@Autowired(required=true):当使用@Autowired注解的时候,其实默认就是@Autowired(required=true)...

static_coder的博客 12万+

Redlock:为什么你的 Redis 分布式锁需要不止一个节点?

RedLock是一种基于Redis的分布式锁算法,相比单节点实现更安全可靠。它具有互斥访问、避免死锁和容错性三大特性,要求过半节点存活即可运行。单节点实现通过SET NX PX和Lua脚本确保原子性操作。完整的RedLock算法需要5个独立master节点,客户端获取锁时需在多数节点成功且总耗时不超过TTL。失败需快速释放已获锁并延时重试。系统需考虑持久化策略,宕机节点需延迟重启超过最大TTL才能保证安全性,但这可能影响系统可用性。该算法在安全性和性能之间取得平衡,适合分布式环境下的锁管理需求。

JavaEdge全是干货的技术号 845

基于知识图谱的旅游推荐系统

这一系统整合了当今先进的数据技术:采集携程等大型平台的景点数据,通过爬虫技术源源不断地获取最新的旅游信息。此外,我们采用Neo4j图数据库来存储和处理这些数据,结合自然语言处理技术,为你提供精准的旅游建议。:通过直观的知识图谱展示,了解各个景点之间微妙的联系,无论是文化背景还是地理方位,你都能从中发现新的旅行灵感。准备毕业设计的同学,关注我们,这是一个集成了多种前沿技术的项目,为你的学术成果锦上添花。:不再浪费时间,系统根据你的偏好和历史评分,利用协同过滤技术推荐适合的旅游目的地。

qalangtao的博客-qalangtao.com 774

Altium Designer 16来自原理图/PCB的各种报错 (持续更新):

NO1.Nets with only one pin: 根本原因: 在BGA的原理图绘制时,我一般习惯拉出该元件的所有IO的网络,这方便利于我开发其他款板卡。同样也会因为不同板卡的需求不同而造成有些IO并没有使用到,也就是整个原理图中only one pin。 解决方案: 鼠标右键工程文件>工程参数>下图圈中的选项将“错误”更改为“警告/不报告” ...

优快云@猿谷攻城狮 1万+

Redis不止能存储字符串,还有List、Set、Hash、Zset,用对了能给你带来哪些优势?

Redis不止能存储字符串,还有List、Set、Hash、Zset,用对了能给你带来哪些优势?

我是Java程序员廖志伟,感谢朋友们的支持! 472

Apache Flink集成HDFS报错Failed to create checkpoint storage at checkpoint coordinator side.

在网上查询相关资料后,在flink的lib目录添加flink-shaded-hadoop-3-3.1.1.7.0.3.0-79-7.0.jar、commons-cli-1.5.0.jar两个包,但报错依旧存在,添加了export HADOOP_CLASSPATH=后面发现是hadoop与flink的兼容性问题,hadoop原先使用的是3.3.4,与多个版本的flink集成都会出现报错,最后将Hadoop的版本改成3.1.3,使用flink run运行jar包就没有这个错误了,在hdfs上成功保存了检查点。

zywenmag的博客 625

【07期】Redis中是如何实现分布式锁的?

分布式锁常见的三种实现方式: 数据库乐观锁; 基于Redis的分布式锁; 基于ZooKeeper的分布式锁。 本地面试考点是,你对Redis使用熟悉吗?Redis中是如何实现分布式锁的。 要点 Redis要实现分布式锁,以下条件应该得到满足 互斥性 在任意时刻,只有一个客户端能持有锁。 不能死锁 客户端在持有锁的期间崩溃而没有主动解锁,也能保证后...

Java笔记虾 5548

2026 最新安全 Skill 合集(CTF / 审计 / 渗透 / 红队)威胁建模一网打尽

2026年安全领域进入"Skill化"时代,各类安全能力被结构化封装为可复用的AI Skill。本文介绍了7个核心安全Skill项目:渗透测试全流程的AgentSkillsHub、CTF解题技能库ctfskills、多语言代码审计工具codeaudit、PHP专项审计系统、Java自动化审计流水线、威胁建模工具threatmodeling以及覆盖30+领域的Anthropic-Cybersecurity-Skills。这些项目将传统安全经验转化为标准化、可验证、可自动执行的模块化能力,支

Chengbei11的博客 1892

Orange3实战教程:实例---文本分类

我们可以使用预测模型按作者、类型、情感等对文档进行分类。在此工作流中,我们根据文档的Aarne Thompshon Uther索引对文档进行归类,这是故事的主题定义。我们使用两个简单的学习器,Logistic回归和朴素贝叶斯,两者都可以在诺谟图中检查。然后再从可视化分类中添加列线图组件,观察哪些词对逻辑回归最重要。也可以尝试使用在朴素贝叶斯模型上,并编辑连线属性。再从模型中添加朴素贝叶斯模型,以尝试不同的学习器。

err2008的专栏 386

Redis字符串命令全解析:从SET参数到分布式锁与位图统计

Redis字符串是缓存与分布式系统中的基础数据结构,其命令语义直接影响缓存穿透、分布式锁和原子计数等核心场景的可靠性。SET命令通过NX、XX、EX、KEEPTTL等参数组合,在单线程模型下实现原子操作,是分布式锁和缓存写入的基石;INCR系列提供原子计数能力,SETBIT与BITCOUNT则以位图方式高效完成活跃统计。理解这些命令的语义差异与边界行为,能帮助开发者在缓存更新、限流器、用户活跃统计等场景中避免TTL意外清除、类型冲突和集群跨槽等常见问题。

weixin_33600816的博客 100

WPF 上位机可视化天花板:HandyControl 搭建 SCADA 系统

HandyControl 凭借「丰富的工业级控件、灵活的主题定制、优异的性能」,成为 WPF 开发 SCADA 系统的首选 UI 库。本文搭建的 SCADA 系统涵盖实时监控、设备控制、报警管理、趋势分析四大核心功能,通过 HandyControl 实现了工业级可视化效果,开发效率提升 60% 以上。控件开箱即用:无需自定义仪表盘、趋势图、指示灯等 SCADA 核心控件;可视化效果专业:工业风主题、动态颜色切换、清晰的状态呈现,契合工业场景需求;

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1127

【大厂面试题】Redis中是如何实现分布式锁的?

分布式锁常见的三种实现方式:数据库乐观锁;基于Redis的分布式锁;基于ZooKeeper的分布式锁。本地面试考点是,你对Redis使用熟悉吗?Redis中是如何实现分布式锁的。要点Re...

民工哥的博客 3152

android osmdroid 加载常用离线地图格式(开源的在线地图)

osmdroid是(几乎)完整/免费更换为Android MapView(v1 API)类。它还包括一个模块化的瓷砖供应商系统支持众多的在线和离线瓷砖来源和覆盖支持内置覆盖绘制图标,跟踪位置和形状。如果想在你项目中使用osmdroid,绝对是灵活度最高,不用申请百度,高德等的key。还有一堆规则要遵循。osmdroid可以支持多图层叠加,绘制自已的图层。离线加载常用地图格式zip,sqlite,.

mmsx990的博客 1万+

最适合入门的100个深度学习项目

本专栏整理了《PyTorch深度学习项目实战100例》,内包含了各种不同的深度学习项目,包含项目原理以及源码,每一个项目实例都附带有完整的代码+数据集。

优快云 精品推荐 12万+

Redis分布式锁深度解析:从原生实现到Redisson进阶

本文深入解析Redisson分布式锁的实现机制与优势,揭示其如何解决原生Redis锁的痛点问题。Redisson通过自动续命看门狗机制、可重入锁设计、集群环境适配等创新,提供了生产级分布式锁解决方案。文章详细拆解了Redisson的Lua脚本实现、数据结构选择、锁续期原理等核心细节,并介绍了公平锁、读写锁等高级特性。相比手动实现,Redisson显著提升了分布式锁的可靠性和易用性,是Java技术栈中的首选方案。

2301_80017072的博客 1509

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

【Redis 进阶】分布式锁深度演进:从 SETNX 到 Redlock,一步步写对工业级分布式锁

在分布式系统开发中,并发资源控制是绕不开的核心问题。单机时代,我们用 C++ 的 std::mutex、Java 的 synchronized 就能搞定进程内的线程安全;但当业务部署到多个服务器节点上,每个节点都是独立进程,共享同一份业务资源时,进程内锁就完全失效了。超卖、重复创建、资源竞争,各类并发问题随之而来。Redis 凭借单线程原子性、高性能、接入简单的特点,成了实现分布式锁最主流的方案。但很多开发者实现分布式锁,往往停留在「setnx 加锁、del 解锁」的最简版本,线上要么出现死锁、要么误解锁、

会当凌绝顶,一览众山小 2102

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

07面试常问:Redis中是如何实现分布式锁的?

分布式锁常见的三种实现方式: 数据库乐观锁; 基于Redis的分布式锁; 基于ZooKeeper的分布式锁。 本地面试考点是,你对Redis使用熟悉吗?Redis中是如何实现分布式锁的。 要点 Redis要实现分布式锁,以下条件应该得到满足 互斥性 在任意时刻,只有一个客户端能持有锁。 不能死锁 客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。 容错性 只要大部分的Redis节点正常运行,客户端就可以加锁和解锁。 实..

AI乔治 1256

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Redis中是如何实现分布式锁的?

分布式锁常见的三种实现方式: 数据库乐观锁; 基于Redis的分布式锁; 基于ZooKeeper的分布式锁。 本地面试考点是,你对Redis使用熟悉吗?Redis中是如何实现分布式锁的。 实现 可以直接通过 set key value px milliseconds nx 命令实现加锁, 通过Lua脚本实现解锁。 //获取锁(unique_value可以是UUID等) SET resource_name unique_value NX PX 30000 //释放锁(lua脚本中,一定要比

辉的范你学不来的博客 345

面试官常问:Redis中是如何实现分布式锁的?

其次,由于我们对锁设置了过期时间,即使锁的持有者后续发生崩溃而没有解锁,锁也会因为到了过期时间而自动解锁(即key被删除),不会发生死锁。我们可以看到,RedissonLock是可重入的,并且考虑了失败重试,可以设置锁的最大等待时间, 在实现上也做了一些优化,减少了无效的锁申请,提升了资源的利用率。如果存储锁对应key的那个节点挂了的话,就可能存在丢失锁的风险,导致出现多个客户端持有锁的情况,这样就不能实现资源的独享了。需要获取以下这些面试题答案以及学习资料得话麻烦关注+好评之后。

Java后端架构V 418

redis实现分布式锁_Redis中是如何实现分布式锁的?

分布式锁常见的三种实现方式:数据库乐观锁;基于Redis的分布式锁;基于ZooKeeper的分布式锁。本地面试考点是,你对Redis使用熟悉吗?Redis中是如何实现分布式锁的。要点Redis要实现分布式锁,以下条件应该得到满足互斥性在任意时刻,只有一个客户端能持有锁。不能死锁客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。容错性只要大部分的Redis节点正常运行,客户端就可...

weixin_39520988的博客 68

redis分布式锁实战

Redis 的核心价值在于 “用内存的速度解决实际问题”,通过灵活的数据结构和丰富的特性,既能做简单的缓存,也能支撑复杂的分布式场景。掌握 5 种基础数据结构的适用场景和命令;理解持久化、主从、集群等特性的原理(知其然更知其所以然);结合业务场景选择合适的用法(如缓存需考虑过期策略,计数器需保证原子性)。如果需要进一步深入,可以学习 Redis 的底层实现(如跳表、哈希表)、集群槽位分配、分布式锁的进阶方案(如 Redisson)等内容。redis分布式锁实战已完成思考。

qq_37782946的博客 937

redis分布式锁 在集群模式下如何实现_Redis中是如何实现分布式锁的?

分布式锁常见的三种实现方式:数据库乐观锁;基于Redis的分布式锁;基于ZooKeeper的分布式锁。本地面试考点是,你对Redis使用熟悉吗?Redis中是如何实现分布式锁的。更多面试题:面试题内容聚合要点Redis要实现分布式锁,以下条件应该得到满足互斥性在任意时刻,只有一个客户端能持有锁。不能死锁客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。容错性只要大部分的Redi...

weixin_39734987的博客 325

Redis分布式锁实战:从原理到高可用架构设计

分布式锁是解决分布式系统中资源并发访问冲突的核心技术,其原理是在多个进程或服务间建立互斥访问机制,确保关键操作(如库存扣减、全局ID生成)的原子性。在技术实现上,基于Redis的分布式锁因其高性能和易用性成为主流方案,通过原子性SET命令、唯一客户端标识和Lua脚本保障了锁的安全获取与释放。然而,在生产环境中,还需应对锁续期、可重入性、主从切换等挑战,并借助Redisson等成熟客户端库实现看门狗机制。对于高可用场景,RedLock算法通过多主节点投票进一步提升了锁的可靠性。理解这些技术细节,结合合理的监控

weixin_33508411的博客 311
上一篇: 还在为HTML转PDF发愁?再介绍两款工具,为你保驾护航!
下一篇: OCR告别付费!分享两款可部署的开源项目
智_永无止境
博客等级 码龄10年 803粉丝 406原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智_永无止境

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值