解决Redis分布式锁业务代码超时致使锁失效问题

『Redis系列』Redis分布式锁解锁案例 Redis分布式锁解锁案例 相关视频教程(来自动力节点):https://www.bilibili.com/video/BV1Uz4y1X72A 相关资料下载:http://www.bjpowernode.com/?csdn 1、解锁代码 还是先展示代码,再带大家慢慢解释为什么这样实现: public class RedisTool { private static final Long RELEASE_SUCCESS = 1L; /** * 释放分布式锁 ... 阅读详情

一、redis分布式锁的基本实现

redis加锁命令:redis

SETNX resource_name my_random_value PX 30000 

这个命令的做用是在只有这个key不存在的时候才会设置这个key的值(NX选项的做用),超时时间设为30000毫秒(PX选项的做用) 这个key的值设为“my_random_value”。这个值必须在全部获取锁请求的客户端里保持惟一。算法

SETNX 值保持惟一的是为了确保安全的释放锁,避免误删其余客户端获得的锁。举个例子,一个客户端拿到了锁,被某个操做阻塞了很长时间,过了超时时间后自动释放了这个锁,而后这个客户端以后又尝试删除这个其实已经被其余客户端拿到的锁。因此单纯的用DEL指令有可能形成一个客户端删除了其余客户端的锁,经过校验这个值保证每一个客户端都用一个随机字符串’签名’了,这样每一个锁就只能被得到锁的客户端删除了。安全

既然释放锁时既须要校验这个值又须要删除锁,那么就须要保证原子性,redis支持原子地执行一个lua脚本,因此咱们经过lua脚本实现原子操做。代码以下:服务器

if redis.call("get",KEYS[1]) == ARGV[1] then

         return redis.call("del",KEYS[1])     

else

         return 0

end 

二、业务逻辑执行时间超出锁的超时限制致使两个客户端同时持有锁的问题

若是在加锁和释放锁之间的逻辑执行得太长,以致于超出了锁的超时限制,就会出现问题。由于这时候第一个线程持有的锁过时了,临界区的逻辑尚未执行完,这个时候第二个线程就提早从新持有了这把锁,致使临界区代码不能获得严格的串行执行。并发

不难发现正常状况下锁操做完后都会被手动释放,常见的解决方案是调大锁的超时时间,以后若再出现超时带来的并发问题,人工介入修正数据。这也不是一个完美的方案,由于但业务逻辑执行时间是不可控的,因此仍是可能出现超时,当前线程的逻辑没有执行完,其它线程乘虚而入。而且若是锁超时时间设置过长,当持有锁的客户端宕机,释放锁就得依靠redis的超时时间,这将致使业务在一个超时时间周期内不可用。dom

基本上,若是在执行计算期间发现锁快要超时了,客户端能够给redis服务实例发送一个Lua脚本让redis服务端延长锁的时间,只要这个锁的key还存在并且值还等于客户端设置的那个值。 客户端应当只有在失效时间内没法延长锁时再去从新获取锁(基本上这个和获取锁的算法是差很少的)。分布式

启动另一个线程去检查的问题,这个key是否超时,在某个时间还没释放。lua

当锁超时时间快到期且逻辑未执行完,延长锁超时时间的伪代码:spa

if redis.call("get",KEYS[1]) == ARGV[1] then

          redis.call("set",KEYS[1],ex=3000)  

else

          getDLock();//从新获取锁    

三、redis的单点故障主从切换带来的两个客户端同时持有锁的问题

生产中redis通常是主从模式,主节点挂掉时,从节点会取而代之,客户端上却并无明显感知。原先第一个客户端在主节点中申请成功了一把锁,可是这把锁尚未来得及同步到从节点,主节点忽然挂掉了。而后从节点变成了主节点,这个新的节点内部没有这个锁,因此当另外一个客户端过来请求加锁时,当即就批准了。这样就会致使系统中一样一把锁被两个客户端同时持有,不安全性由此产生。线程

不过这种不安全也仅仅是在主从发生 failover 的状况下才会产生,并且持续时间极短,业务系统多数状况下能够容忍。

四、RedLock算法

若是你很在意高可用性,但愿挂了一台 redis 彻底不受影响,能够考虑 redlock。 Redlock 算法是由Antirez 发明的,它的流程比较复杂,不过已经有了不少开源的 library 作了良好的封装,用户能够拿来即用,好比 redlock-py。

import redlock

  addrs = [{

      "host": "localhost",

      "port": 6379,

      "db": 0

     }, {

      "host": "localhost",

      "port": 6479, 

      "db": 0 

      }, { 

       "host": "localhost",

       "port": 6579,

       "db": 0 

  }]

 dlm = redlock.Redlock(addrs)

 success = dlm.lock("user-lck-laoqian", 5000)

 if success:

     print 'lock success' 

     dlm.unlock('user-lck-laoqian') 

else:

     print 'lock failed' 

RedLock算法的核心原理:

使用N个彻底独立、没有主从关系的Redis master节点以保证他们大多数状况下都不会同时宕机,N通常为奇数。一个客户端须要作以下操做来获取锁:

1.获取当前时间(单位是毫秒)。

2.轮流用相同的key和随机值在N个节点上请求锁,在这一步里,客户端在每一个master上请求锁时,会有一个和总的锁释放时间相比小的多的超时时间。好比若是锁自动释放时间是10秒钟,那每一个节点锁请求的超时时间多是5-50毫秒的范围,这个能够防止一个客户端在某个宕掉的master节点上阻塞过长时间,若是一个master节点不可用了,咱们应该尽快尝试下一个master节点。

3.客户端计算第二步中获取锁所花的时间,只有当客户端在大多数master节点上成功获取了锁((N/2) +1),并且总共消耗的时间不超过锁释放时间,这个锁就认为是获取成功了。

4.若是锁获取成功了,那如今锁自动释放时间就是最初的锁释放时间减去以前获取锁所消耗的时间。

5.若是锁获取失败了,不论是由于获取成功的锁不超过一半(N/2+1)仍是由于总消耗时间超过了锁释放时间,客户端都会到每一个master节点上释放锁,即使是那些他认为没有获取成功的锁。

五、知识扩展

5.1为何lua脚本结合redis命令能够实现原子性

Redis 提供了很是丰富的指令集,可是用户依然不知足,但愿能够自定义扩充若干指令来完成一些特定领域的问题。Redis 为这样的用户场景提供了 lua 脚本支持,用户能够向服务器发送 lua 脚原本执行自定义动做,获取脚本的响应数据。Redis 服务器会单线程原子性执行 lua 脚本,保证 lua 脚本在处理的过程当中不会被任意其它请求打断。

img

5.2 redis 可重入分布式锁

要实现可重入锁,方法很简单,当加锁失败时判断锁的值是否是跟当前线程设置值相同,伪代码以下:

if setnx == 0

    if get(key) == my_random_value

        //重入

    else

        //不可重入

else

大厂面试官问我:Redis的分布式锁怎么解决死锁问题?【后端八股文十:Redis分布式锁八股文合集(2)】 Redisson在Redis的基础上,实现了可重入锁、公平锁、联锁等多种类型的分布式锁。可重入锁通过维护一个持有锁的线程ID和锁的持有次数来实现。公平锁通过维护一个等待队列,按照请求顺序依次获取锁。联锁允许同时获取多个锁,只有全部获取成功才算获取锁成功。 阅读详情

相关推荐

美团面试:Redis锁如何续期?Redis锁超时,任务没完怎么办?

Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还实现了可重入锁(Reentrant Lock)、公平锁(Fair Lock、联锁(MultiLock)、 红锁(RedLock)、 读写锁(ReadWriteLock)等,还提供了许多分布式服务。Redisson提供了使用Redis的最简单和最便捷的方法。

架构师尼恩 3001

Redis-Lua脚本详解

Redis中执行Lua脚本 SCRIPT LOAD 和 EVALSHA指令 错误处理函数pcall()与call() Script Kill 的原理

哆啦A梦 4126

大厂面试官问我:Redis的分布式锁,锁失效了该怎么办?【后端八股文十:Redis分布式锁八股文合集(1)】

本文为【Redis分布式锁八股文合集(1)】初版,后续还会进行优化更新,欢迎大家交流~💥💥。

qq_33445788的博客 1768

Redis(十一) 分布式锁

1

weixin_43189971的博客 938

京东面试:Redis主从切换,锁失效了,怎么办?

Redis 分布式锁 主从切换问题的,有两个层面的解决方案:按照两个层面进行 深度回答,可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”,然后实现”offer直提”。在面试之前,建议大家系统化的刷一波 5000页《尼恩Java面试宝典PDF》,里边有大量的大厂真题、面试难题、架构难题。很多小伙伴刷完后, 吊打面试官, 大厂横着走。在刷题过程中,如果有啥问题,大家可以来 找 40岁老架构师尼恩交流。另外,如果没有面试机会,可以找尼恩来改简历、做帮扶。前段时间,

架构师尼恩 1617

【Macbook-Latex安装部署教程】【Win-Texlive镜像下载】【简单易上手】MacTex+Vscode/Texstudio

该教程记录自己在mac()上安装部署Latex环境的经验,整个教程操作简单,配置要求少,易上手。教程分成三部分:Mactex下载与安装,Vscode插件下载与配置文件修改,Texstudio安装。

sunriseOvO的博客 2568

已超过了锁请求超时时段_redis分布式锁深度剖析

redis分布式锁的实现主要是基于redis的setnx 命令(setnx命令解释见:http://doc.redisfans.com/string/setnx.html),我们来看一下setnx命令的作用:1、redis分布式锁的基本实现redis加锁命令:SETNX resource_name my_random_value PX 30000 这个命令的作用是在只有这个key不存在的时候才会设...

weixin_39809168的博客 759

基于 Python 的 LIF 模型:探索神经元同步与小世界网络

首先,我们定义了一个LIFNeuronself.soma.L = self.soma.diam = 12.6157 # 固定神经元形状self.cm = cm # 电容self.V_rest = V_rest # 静息电位self.V = V_rest # 初始化膜电位在初始化过程中,每个神经元被赋予初始的静息电位,并且其膜电位会在后续的模拟过程中动态变化。

qq_36224726的博客 1423

【redis】原子性的实现--lua脚本

Lua 脚本可以将多条 Redis 命令写在一个脚本中。Redis 会将这个脚本作为一个整体执行,确保脚本内的所有命令是原子操作。脚本会检查 Redis 中的键是否等于传入的值,如果相等,则删除该键。

thorandloki的博客 629

AI 代码赋能短视频带货:服装及多赛道批量内容生产全流程实操

本文聚焦 AI 技术在短视频带货领域的落地应用,以服装赛道为核心,延伸至花卉绿植、图书、茶具等热门领域,系统拆解 AI 工具在选品、素材处理、视频制作(含动态效果、场景搭建)、运营优化等环节的实操方法。针对从业者普遍面临的 “内容生产低效”“无专业技术难出优质视频”“流量运营踩坑” 等痛点,提供从基础工具使用到高阶视频制作的全流程技术方案,助力相关从业者借助 AI 实现批量、高效的短视频内容产出。

m0_67958922的博客 3083

在Matlab中开发AutoSAR模型的流程(自下而上)

前面介绍了AutoSAR软件组件开发的两种方式,其中自下向上的方式,是从模型出发,流程如下。

小胡同学的工程师学习之路 5365

Redis分布式锁失效场景分析

本文主要介绍了分布式锁失效的三种场景,并通过一些案例进行分析。

ZDK_csdn的博客 1万+

别再手动敲代码了!用STM32CubeMX+FreeRTOS图形化配置,5分钟搞定多任务通信框架

本文详细介绍了如何利用STM32CubeMX和FreeRTOS快速搭建多任务通信框架,大幅提升嵌入式开发效率。通过图形化配置工具,开发者可在5分钟内完成任务调度、时钟配置和内核对象生成,特别适合物联网设备开发。文章还提供了代码优化和调试技巧,帮助开发者轻松应对复杂应用场景。

weixin_30363285的博客 291

解决Redis分布式锁业务代码超时导致锁失效问题

1、redis分布式锁的基本实现 redis加锁命令: SETNX resource_name my_random_value PX 30000 这个命令的作用是在只有这个key不存在的时候才会设置这个key的值(NX选项的作用),超时时间设为30000毫秒(PX选项的作用) 这个key的值设为“my_random_value”。这个值必须在所有获取锁请求的客户端里保持唯一。 SETNX 值保持唯...

SpringForAll的博客 2322

手把手教你学Simulink——电机电磁兼容与可靠性场景示例:基于Simulink的电机噪声抑制控制仿真

本文带你完成了电机噪声抑制控制的Simulink仿真,实现了:✅ 揭示了电磁噪声从电流到声音的传递机理✅ 搭建了含死区、固定载波等噪声源的高保真模型随机PWM(消除啸叫)谐振控制器(抑制5/7次嗡鸣)谐波注入(降低THD) ✅ 通过综合方案将噪声降低10 dB以上(感知响度减半!) ✅ 为产品静音品质提升提供可落地的控制方案。

MHD0815的博客 94

一文吃透 OData Deep Insert:从框架原理到 ABAP 实战

本文面向ABAP工程师,解析OData服务中的Deep Insert技术。文章首先阐述Deep Insert的业务背景,说明其适用于父子层级数据必须成组创建的场景(如销售订单与行项目)。随后深入框架实现机制,介绍SAP Gateway如何通过CREATE_DEEP_ENTITY方法处理嵌套请求,并强调开发者的责任边界。通过销售订单案例,文章对比了Deep Insert与$batch的适用场景差异,提供请求负载示例和DPC_EXT实现骨架代码。最后给出MPC_EXT声明深结构的三种套路,以及事务处理和错误处理

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 225

Redis 篇-深入了解分布式锁 Redisson 原理(可重入原理、可重试原理、主从一致性原理、解决超时锁失效)

Redisson 是一个在 Redis 的基础上实现的 Java 驻内存数据网络。它不仅提供了一系列的分布式的 Java 常用对象,还提供了许多分布式服务,其中包含了各种分布式锁的实现。Redisson 解决了不可重入问题、不可重试问题、超时释放问题、主从一致性问题。比如说,分布式锁的可重入锁、公平锁、联锁、红锁等等。

小扳手 8466

STM32F407中文手册

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

锁失效_解决Redis分布式锁业务代码超时导致锁失效问题

点击上方☝SpringForAll社区轻松关注!及时获取有趣有料的技术文章本文来源:http://arick.net/content/121、redis分布式锁的基本实现redis加锁命令:SETNX resource_name my_random_value PX 30000 这个命令的作用是在只有这个key不存在的时候才会设置这个key的值(NX选项的作用),超时时间设为30000...

weixin_39846186的博客 1657

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Redis分布式锁(二):锁超时后导致多个线程获得锁的解决方案

使用现状 Redis分布锁的基础内容,我们已经在基于AOP和Redis实现的简易版分布式锁这篇文章中讲过了,也在文章中示范了正常的加锁和解锁方法。 分布式锁在之前的项目中一直运行良好,没有辜负我们的期望。 发现问题 但在最近查线上日志的时候偶然发现,有一个业务场景下,分布式锁偶尔会失效,导致有多个线程同时执行了相同的代码。 我们经过初步排查,定位到是因为在这段代码中间调用了第三方的接口导致。 因为...

weixin_33943347的博客 1万+

Redis分布式锁之红锁

一、问题 分布式锁,当我们请求一个分布式锁的时候,成功了,但是这时候slave还没有复制我们的锁,masterDown了,我们的应用继续请求锁的时候,会从继任了master的原slave上申请,也会成功。 这就会导致,同一个锁被获取了不止一次。 二、办法 Redis中针对此种情况,引入了红锁的概念。 三、原理 用Redis中的多个master实例,来获取锁,只有大多数实例获取到了锁,才算是获取成功。具体的红锁算法分为以下五步: 获取当前的时间(单位是毫秒)。 使用相同的key和随机值在N个节点上请求锁。这

2万+

Redis 分布式锁续期:锁还在,不代表业务安全

Redis 分布式锁续期要校验锁值、设置 TTL 和最大持有时间,并用业务幂等兜底。锁还在,不代表业务安全。真正安全的是锁、状态和约束一起工作。

dicky_zhang3的博客 1018

Redis的分布式锁分析

开发同学都知道,在分布式系统中,为了保证多个机器并发操作的数据一致性,常常需要使用分布式锁机制。常用的比如数据库锁,ZK锁,Reis锁等等,今天我们就探讨下Redis分布式锁,说说他的实现原理和应用场景,并介绍如何正确使用分布式锁来解决并发问题

战斧的博客 7273

分布式锁-Redisson红锁(Redlock)深度实战教程:解决Redis分布式锁主从宕机失效问题

文章目录1:分布式锁的概念1:概念2:锁/分布式锁/事务区别2:本文使用的案例场景1:需求2:controller层代码3:锁控制层代码(使用synchronized 不成功)4:调用的订单业务代码3:数据库mysql方案1:原理2:musql锁工具类3:业务使用代码4:优缺点4:Redis解决方案-手写redis1:原理和问题优化处理2:锁机制代码-设置过期时间和只能释放自己的锁3:锁机制代码-手动增加续约时间5:Redis解决方案-redisson1:Redisson 一个用来进行分布式锁的工具类2:导

苍煜 7592

分布式锁超时问题的处理(只是参考,推荐使用redission框架和ZK做分布式锁)

1、redis分布式锁的基本实现 redis加锁命令: SETNX resource_name my_random_value PX 30000 这个命令的作用是在只有这个key不存在的时候才会设置这个key的值(NX选项的作用),超时时间设为30000毫秒(PX选项的作用) 这个key的值设为“my_random_value”。这个值必须在所有获取锁请求的客户端里保持唯一。 SET...

jaryle的专栏 9671

Redis分布式锁的缺陷及可能产生的问题

Redis分布式锁的缺陷及可能产生的问题

liuruiaaa的博客 1207
上一篇: redis有序集合zset的底层实现——跳跃表skiplist
下一篇: Redis6.0 实际应用问题
wrr-cat
博客等级 码龄9年 128粉丝 302原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值