分布式锁 setnx del

SpringBoot 多实例项目 使用 redis分布式锁 控制定时任务的执行 1. 项目背景: 随着业务的发展,很多项目都部署在多台机器上以保证可用性。而代码中的定时任务,如果不加控制, 那么相同的任务会在多个任务实例中重复执行,甚至可能出现资源竞争和数据冲突等问题。 出于实际情况的考虑,不考虑引入作业调度框架,继续沿用 Spring 自带的 @Scheduled。 这时 可使用Redis 的 SETNX、EXPIRE 和... 阅读详情

SETNX命令简介

SETNX key value

将key的值设为value,并且仅当key不存在。
若给定的key已经存在,则SETNX不做任何操作。
SETNX 是SET if Not eXists的简写。
返回整数,具体为

1,当 key 的值被设置
0,当 key 的值没被设置
使用SETNX实现分布式锁
多个进程执行以下Redis命令:

SETNX lock.foo <current Unix time + lock timeout + 1>

如果 SETNX 返回1,说明该进程获得锁,SETNX将键 lock.foo 的值设置为锁的超时时间(当前时间 + 锁的有效时间)。
如果 SETNX 返回0,说明其他进程已经获得了锁,进程不能进入临界区。进程可以在一个循环中不断地尝试 SETNX 操作,以获得锁。

解决死锁
正常第一反应利用SETNX实现分布式锁可能是这样的

if(SETNX key value){//如果设置成功表示拿到了锁
    return true;
}
return false;

然后释放锁的时候就直接 DEL掉;
简单思路是这样,但是这样会有很多问题

如果一个进程获得锁之后,断开了与redis的连接(进程挂断或者网络中断),那么锁一直的不断释放,其他的进程就一直获取不到锁,就出现了 “死锁”
然而,锁超时时,我们不能简单地使用 DEL 命令删除键 lock.foo 以释放锁。考虑以下情况,进程P1已经首先获得了锁 lock.foo,然后进程P1挂掉了。进程P2,P3正在不断地检测锁是否已释放或者已超时,执行流程如下:
1 . P2和P3进程读取键 lock.foo 的值,检测锁是否已超时(通过比较当前时间和键 lock.foo 的值来判断是否超时)
2.P2和P3进程发现锁 lock.foo 已超时
3.P2执行 DEL lock.foo命令
4.P2执行 SETNX lock.foo命令,并返回1,即P2获得锁
5.P3执行 DEL lock.foo命令将P2刚刚设置的键 lock.foo 删除(这步是由于P3刚才已检测到锁已超时)
6.P3执行 SETNX lock.foo命令,并返回1,即P3获得锁
7.P2和P3同时获得了锁
从上面的情况可以得知,在检测到锁超时后,进程不能直接简单地执行 DEL 删除键的操作以获得锁。

为了解决上述算法可能出现的多个进程同时获得锁的问题,我们再来看以下的算法。
我们同样假设进程P1已经首先获得了锁 lock.foo,然后进程P1挂掉了。接下来的情况:

进程P4执行 SETNX lock.foo 以尝试获取锁
由于进程P1已获得了锁,所以P4执行 SETNX lock.foo 返回0,即获取锁失败
P4执行 GET lock.foo 来检测锁是否已超时,如果没超时,则等待一段时间,再次检测
如果P4检测到锁已超时,即当前的时间大于键 lock.foo 的值,P4会执行以下操作
GETSET lock.foo <current Unix timestamp + lock timeout + 1>
由于 GETSET 操作在设置键的值的同时,还会返回键的旧值,通过比较键 lock.foo 的旧值是否小于当前时间,可以判断进程是否已获得锁
假如另一个进程P5也检测到锁已超时,并在P4之前执行了 GETSET 操作,那么P4的 GETSET 操作返回的是一个大于当前时间的时间戳,这样P4就不会获得锁而继续等待。注意到,即使P4接下来将键 lock.foo 的值设置了比P5设置的更大的值也没影响。
另外,值得注意的是,在进程释放锁,即执行 DEL lock.foo 操作前,需要先判断锁是否已超时。如果锁已超时,那么锁可能已由其他进程获得,这时直接执行 DEL lock.foo 操作会导致把其他进程已获得的锁释放掉。

程序代码
用以下python代码来实现上述的使用 SETNX 命令作分布式锁的算法。

LOCK_TIMEOUT = 3
lock = 0
lock_timeout = 0
lock_key = 'lock.foo'

获取锁

while lock != 1:
    now = int(time.time())
    lock_timeout = now + LOCK_TIMEOUT + 1
    lock = redis_client.setnx(lock_key, lock_timeout)
    if lock == 1 or (now > int(redis_client.get(lock_key))) and now > int(redis_client.getset(lock_key, lock_timeout)):
        break
    else:
        time.sleep(0.001)

已获得锁

do_job()

释放锁

now = int(time.time())
if now < lock_timeout:
    redis_client.delete(lock_key)
java代码


while (timeout >= 0) {
            long expires = System.currentTimeMillis() + expireMsecs + 1;
            String expiresStr = String.valueOf(expires); //锁到期时间
            if (this.setNX(lockKey, expiresStr)) {
                // lock acquired
                locked = true;
                return true;
            }

            String currentValueStr = this.get(lockKey); //redis里的时间
            if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {
                //判断是否为空,不为空的情况下,如果被其他线程设置了值,则第二个条件判断是过不去的
                // lock is expired

                String oldValueStr = this.getSet(lockKey, expiresStr);
                //获取上一个锁到期时间,并设置现在的锁到期时间,
                //只有一个线程才能获取上一个线上的设置时间,因为jedis.getSet是同步的
                if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {
                    //防止误删(覆盖,因为key是相同的)了他人的锁——这里达不到效果,这里值会被覆盖,但是因为什么相差了很少的时间,所以可以接受

                    //[分布式的情况下]:如过这个时候,多个线程恰好都到了这里,但是只有一个线程的设置值和当前值相同,他才有权利获取锁
                    // lock acquired
                    locked = true;
                    return true;
                }
            }
            timeout -= DEFAULT_ACQUIRY_RESOLUTION_MILLIS;

            /*
                延迟100 毫秒,  这里使用随机时间可能会好一点,可以防止饥饿进程的出现,即,当同时到达多个进程,
                只会有一个进程获得锁,其他的都用同样的频率进行尝试,后面有来了一些进行,也以同样的频率申请锁,这将可能导致前面来的锁得不到满足.
                使用随机的等待时间可以一定程度上保证公平性
             */
            Thread.sleep(DEFAULT_ACQUIRY_RESOLUTION_MILLIS);

        }
NX二次开发新建组件 NXOpen新建组件 阅读详情

相关推荐

SRAM vs RRAM:存算一体芯片选型指南(含最新技术对比)

本文深入对比了SRAM与RRAM在存算一体芯片设计中的核心差异,为硬件工程师和架构师提供实战选型指南。文章从技术本质、性能、功耗、成本及设计风险等多维度剖析,指出SRAM基于成熟CMOS工艺,适合高精度、低延迟场景;而RRAM凭借非易失性和高密度潜力,在超低功耗、固定模型应用中优势明显。决策需综合项目预算、上市时间及技术储备。

e4f5g6h的博客 942

Redis分布式锁的简单实现_使用setnx和del命令实现redis分布式锁(1)

随着业务发展的需要,原来单机部署的系统演化成分布式集群系统之后,由于分布式系统多线程、多进程并且分布在不同的机器上,使得原来单机部署情况下的并发控制策略失效,单纯的Java API并不能提供分布式锁的能力,为了解决这个问题就需要一种跨JVM的互斥机制来控制共享资源的访问,这就是分布式锁要解决的问题。当我们初次调用setnx命令设置lock的值时,lock还不存在,所以可以设置成功,后续再调用setnx设置相同的key,也就是lock时,却无法设置成功,这就是setnx的作用。那么这个问题怎么解决呢?

2401_84183628的博客 863

AI气象预报:数值模式融合与短临预警的工程实践

气象预报正经历从物理推演到数据驱动的认知范式转变。AI气象预报并非替代传统数值模式,而是通过数值模式融合弥补其在参数化误差、初值敏感性和计算效率上的固有瓶颈。其技术价值在于提升短临预警时效性与空间精度,支撑航空调度、电力调控、防洪应急等关键场景。实践中需兼顾物理一致性、可解释性与业务系统兼容性,避免纯黑箱建模带来的外推失效与不确定性缺失风险。本文聚焦AI作为超分辨率引擎、误差矫正器和短临加速器的三类落地路径,解析HEALPix投影、多尺度图建模、轻量级U-Net等核心适配方法。

weixin_28221501的博客 299

Redis分布式锁的简单实现

Redis分布式锁 随着业务发展的需要,原来单机部署的系统演化成分布式集群系统之后,由于分布式系统多线程、多进程并且分布在不同的机器上,使得原来单机部署情况下的并发控制策略失效,单纯的Java API并不能提供分布式锁的能力,为了解决这个问题就需要一种跨JVM的互斥机制来控制共享资源的访问,这就是分布式锁要解决的问题。 也就是说,当我们使用分布式锁时,该锁多分布式系统内的所有应用都有效。 分布式锁的主流实现方案有多种,包括基于数据库实现的分布式锁、基于缓存(如redis)实现(性能最高)、基于zookeep

wyg1973017714的博客 462

别再手动调参了!用BERTopic分析500篇论文摘要,我总结了这份超全参数调优指南

本文详细介绍了如何通过BERTopic参数调优从500篇论文摘要中挖掘高质量主题。从文档嵌入、降维到聚类,每个环节的关键参数设置都直接影响主题分析效果。文章提供了学术文本特有的调优技巧,包括预处理、主题多样性与专注度的平衡,以及评估指标与迭代优化方法,帮助研究者高效完成NLP主题分析任务。

weixin_31235909的博客 216

手把手教你用Kokoro-82M-v1.1-zh搭建本地TTS服务(含WebSocket接口)

本文详细介绍了如何使用Kokoro-82M-v1.1-zh模型搭建本地TTS服务,包括环境配置、模型部署、WebSocket接口实现及性能优化。通过实战指南,开发者可以快速掌握本地部署TTS系统的关键技术,提升语音交互应用的开发效率。

weixin_30776273的博客 184

SETNX分布锁详解

SETNX作为分布式锁详解

qq_47288175的博客 2万+

Andriod应用开发基础项目——记账本

本项目采用Java语言编写,是一款基于Android Studio开发的简易项目,本项目可以提高Java语言编写软件的能力,同时加深对开发软件Android studio有了更深层次的掌握,很适合初学者。在项目过程中,遇到了一些挑战和问题,但通过不断的努力和学习,最终取得了成功。未来,可以还可以继续优化App的功能和性能,增加更多实用的功能,提升用户体验。

eryasd的博客 3469

分布式锁教程

分布式锁在分布式系统中至关重要,它确保了多个进程或服务对共享资源的同步访问。本文介绍了从JVM本地锁到分布式锁的实现及其优化方法,包括使用Redis的SETNX命令、添加过期时间、使用Lua脚本来保证操作的原子性和安全性。通过这些方法,可以有效解决锁的获取和释放问题,防止死锁和误释放,提升系统的可靠性和性能。下一篇文章会详细介绍 Redisson 分布式锁的加锁、解锁原理。Redisson。

weixin_51429644的博客 1146

实战拆解:RAG vs Agent在金融风控中的性能对比

2024年上半年我帮某华东地区城商行做零售交易反欺诈系统升级时,技术团队曾发生过一次激烈争论:一派认为应该优先上RAG(检索增强生成)方案,成本低、落地快、合规性好;另一派坚持要上Agent(智能体)方案,推理能力强、能应对复杂新型欺诈。最终我们做了完整的AB测试,结论是两者没有绝对的优劣,只有场景适配的差异:RAG适合高并发、低时延的实时风控场景,Agent适合低并发、高准确率要求的事后核查/大额审批场景,两者结合的 hybrid 方案能覆盖95%以上的风控需求。本文我会结合真实项目的测试数据,从核心概念

AI天才研究院 252

【无人机基站】基于K-mean算法实现无人机基站部署附matlab代码

【无人机基站】基于K-mean算法实现无人机基站部署附matlab代码

天天酷科研的博客 246

分布式锁三种实现方式(数据库实现,缓存Redis等,Zookeeper)

分布式锁三种实现方式: 1. 基于数据库实现分布式锁; 2. 基于缓存(Redis等)实现分布式锁; 3. 基于Zookeeper实现分布式锁; 一, 基于数据库实现分布式锁 1. 悲观锁 利用select … where … for update 排他锁 注意: 其他附加功能与实现一基本一致,这里需要注意的是“where name=lock ”,name字段必须要走索引,否则会锁表...

1085

49、Linux内核内存管理:MGLRU、DAMON与OOM杀手详解

本文详细解析了Linux内核内存管理中的三大核心机制:MGLRU(多代LRU)页面追踪与回收机制、DAMON数据访问监控工具及其在内存优化中的应用,以及OOM(内存不足)杀手的工作原理和触发方式。同时,文章还介绍了VM overcommit_memory策略的设置及其对内存分配的影响,帮助开发者和系统管理员更好地理解Linux内存管理机制,从而优化系统性能和稳定性。

dropout6artist的博客 108

redis分布式锁 setnx del

SETNX命令简介 将key的值设为value,并且仅当key不存在。 若给定的key已经存在,则SETNX不做任何操作。 SETNX 是SET if Not eXists的简写。 返回整数,具体为 1,当 key 的值被设置 0,当 key 的值没被设置 使用SETNX实现分布式锁 多个进程执行以下Redis命令: 如果 SETNX 返回1,说明该进程获得锁,SETNX将键 lock.foo...

Rika_Sir_Zhong的博客 545

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Redis分布式锁 setnx del

SETNX命令简介 Redis有一系列的命令,特点是以NX结尾,NX是Not eXists的缩写,如SETNX命令就应该理解为:SET if Not eXists。这系列的命令非常有用,这里讲使用SETNX来实现分布式锁。 用SETNX实现分布式锁 利用SETNX非常简单地实现分布式锁。例如:某客户端要获得一个名字foo的锁,客户端使用下面的命令进行获取: SETNX lock.foo <c...

Master_Dk的博客 376

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

2024年最全Redis分布式锁的简单实现_使用setnx和del命令实现redis分布式锁,2024年最新12个View绘制流程高频面试题

setnx只有当key不存在的情况下,才将key的值设置为value,若key已经存在,那么setnx命令不做任何操作。例如:当我们初次调用setnx命令设置lock的值时,lock还不存在,所以可以设置成功,后续再调用setnx设置相同的key,也就是lock时,却无法设置成功,这就是setnx的作用。其实setnx就是[SET if Not eXists(如果不存在则SET)]的简写。那么加锁之后我们如何释放锁呢,此时就需要调用del命令删除key,以此来释放锁。

2401_84586462的博客 1014

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

【别再用setnx+del了:一次Redis分布式锁把接口卡成PPT的真实事故】

午高峰领券接口卡成PPT,定位到Redis分布式锁用SETNX+EXPIRE分步、且解锁直接DEL,导致无过期“僵尸锁”和误删他人锁。改成SET NX PX原子加锁+Lua校验解锁,限时退避并引入指标后恢复。

m0_54803659的博客 239

redis的setnx锁到了超时时间失效,并发的问题

SETNX命令简介 命令格式 SETNX key value 将 key 的值设为 value,当且仅当 key 不存在。 若给定的 key 已经存在,则 SETNX 不做任何动作。 SETNX 是SET if Not eXists的简写。 返回值 返回整数,具体为 - 1,当 key 的值被设置 - 0,当 key 的值没被设置 例子 redis> SETNX ...

360linker 4480

使用 Redis 的 SETNX 命令实现分布式锁

使用 Redis 实现分布式锁,具体实现思想是使用 Redis 的 SETNX 命令尝试获取锁,如果 SETNX 返回 1,则表示成功获取锁;如果 SETNX 返回 0,则表示锁已经存在,需要判断锁是否已经过期,如果锁已经过期,则使用 GETSET 命令尝试获取锁。如果 GETSET 返回的值等于之前获取的值,则表示成功获取锁;如果 GETSET 返回的值不等于之前获取的值,则表示锁已经被其他进程获取。释放锁时,使用 DEL 命令删除锁的键。

weixin_45106532的博客 766

Redis_23_Redis实现分布式锁

Redis实现分布式锁

毛毛的专栏 846

Redis 分布式锁

1、 使用数据结构:string 2、 使用操作命令 Redis 字符串(String) // 只有在 key 不存在时设置 key 的值。成功返回1,失败返回0 SETNX key value // 将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)。 SETEX key seconds value // 获取指定 key 的值。 GET key // 该命令用于在 key 存在时删除 key。成功返回1,失败返回0 DEL key 3、 实

myinsert的博客 143

redis实现的分布式锁

文章目录【一】介绍【二】redis锁【三】代码实现【四】链接 【一】介绍 【二】redis锁 【三】代码实现 【四】链接

wenge1477的博客 313

分布式锁之RedisLockRegistry

在传统单体应用单机部署的情况下,可以使用并发处理相关的功能(如Java并发处理相关的API:ReentrantLcok或synchronized)进行互斥控制来解决。但是,随着业务的发展,系统架构也会逐步优化升级,原本单体单机部署的系统被演化成分布式集群系统,由于分布式系统多线程、多进程并且分布在多个不同机器上,这将使原单机部署情况下的并发控制锁策略无法满足,并不能提供分布式锁的能力。为了解决这个问题就需要一种跨机器的互斥机制来控制共享资源的访问,这就是分布式锁解决的难题!

硬水果糖 1747

redis lua 设置过期_分布式锁没那么难,手把手教你实现 Redis 分布锁!|保姆级教程...

书接上文上篇文章「MySQL 可重复读,差点就让我背上了一个 P0 事故!」发布之后,收到很多小伙伴们的留言,从中又学习到很多,总结一下。上篇文章可能举得例子有点不恰当,导致有些小伙伴没看懂为什么余额会变负。这次我们举得实际一点,还是上篇文章 account 表,假设 id=1,balance=1000,不过这次我们扣款 1000,两个事务的时序图如下:这次使用两个命令窗口真实执行一把:注意事务 ...

weixin_39637700的博客 150

@scheduled cron启动后和每小时执行_小耶哥: 一个Redis分布式锁又要和小鑫同学扯半个小时!...

1 Redis分布式锁|1-1 定时任务重复执行-问题引入最近小耶哥在做一个功能, 什么功能呢? 就是超时未支付的订单我们要定时关闭, 释放库存, 并且短信通知用户该订单因超时被取消了。由于小耶哥很难接到这么”隆重”的任务, 就挖空心思的想把这个功能做”好”。由于小耶哥超高的coding能力, 代码三下五除二就写好了, 话不多说, 直接上代码![手动狗头]方塔园byXiaoYeGe暂...

weixin_42521424的博客 1048

Redis学习指南(34)-基于Redis的分布式锁的设计

分布式锁是一种用于在分布式系统中控制并发访问的机制。在分布式系统中,多个进程或线程可能同时访问共享资源,为了避免数据不一致或竞态条件等问题,需要使用分布式锁来保证同一时刻只有一个进程或线程能够访问共享资源。通过以上示例,我们了解了Redis分布式锁的基本原理和实现方式。在分布式系统中使用分布式锁可以避免并发访问引起的数据不一致等问题。但需要注意合理设置超时时间、处理异常情况和锁的重入等,以确保分布式锁的正确使用。

俞兆鹏的博客 999
上一篇: CAP和hashmap
下一篇: 布隆过滤器
小亮彡
博客等级 码龄7年 6粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值