我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Redis分布式锁怎么应用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Redis分布式锁怎么应用

这篇文章主要讲解了“Redis分布式锁怎么应用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Redis分布式锁怎么应用”吧!

分布式锁

在单进程应用中,当一段代码同一时间内只能由一个线程执行时,

多线程下可能会出错,例如两个线程同时对一个数字做累加,两个线程同时拿到了该数字,例如40,一个线程加了10,一个线程加了20,正确结果应该是70,

但由于两个线程在自己的内存中一个算出的是50,一个算出的是60,此时二者都将自己的结果往该数字原本的地方写(保存),

这时候,肯定会有一个线程的值会被覆盖,因为读取->计算->保存 并不是原子操作(原子操作是指不会被线程调度机制打断的操作,这种操作一旦开始,就会一直运行结束,中间不会有任何线程切换),

也就是说最终的结果要么是50,要么是60,而不可能是70(出现并发或并行的情况下,这种情况大概率会发生),

Redis分布式锁怎么应用

单进程应用发生这种情况时,可以由程序提供的锁语义直接上锁(例如java中的sychornized)保证该段代码只会被一个线程执行,按照顺序来进行,结果将是正确的。

在分布式应用中,由于一台机器上可能跑着相同的应用进程,或者在不同的机器上跑着,原本程序自带的语义锁已经无法起到作用,

因为相同的代码可能是在不同的机器、进程中执行,所以此时需要一个能够让不同机器、进程中,相同的应用代码执行到同一段代码时,也能够按照顺序执行(或者同一时间内只有一个线程能够执行),

这就需要用到中间件来协调,可以实现分布式锁的中间件有很多,redis就是其中一个。

redis实现分布式锁的原理

redis中分布式锁的原理其实就是在redis当中设置一个值(当然要保证分布式应用连的都是同一个redis,以这个redis作为中间点,否则当然是没用的),这个值只能由一个线程来存放,当其他线程(或者不同机器上的进程)也来存放时,发现这个值已经存在了,就说明此时已经有人在用这把锁了,这时候要么进行重试等待,要么进行放弃。

设置一般使用 SETNX (set if not exists) 指令,如果该值没有,则进行设置,有了则不设置,这就是拿锁的关键了,当拿到锁的人执行处理完毕后,再调用 DEL 执行进行锁的释放。

死锁问题

使用 SETNX 和 DEL 实现了分布式锁,但是有一种情况,如果一个线程进行了 SETNX 拿到锁成功后,突然这个线程因为某种原因崩溃了,导致没有进行 DEL 释放锁,

那么此时,将会导致其他所有的应用都再也没办法拿到这把锁,也就是 死锁 ,这个问题的解决方式是将锁设置一个有效期,到了有效期之后该锁将被自动释放,

使用 EXPIRE 可以给锁设置一个有效期,如下

SETNX LOCK-KEY-NAME trueEXPIRE LOCK-KEY-NAME 5

但是还有一个问题,因为 SETNX 和 EXPIRE 是分为两个指令执行的,这中间依然有可能出现 SETNX 执行完毕后,由于认为或者机器、程序发生的故障 导致 EXPIRE 没有执行成功,此时还是有可能会发生死锁,

Redis分布式锁怎么应用

事务能不能解决这个问题?

NO,因为 EXPIRE 是依赖 SETNX 的执行结果执行的,只有 SETNX 成功后,才能进行 EXPIRE,否则是不可以执行的,事务里并没有 if else 的分支逻辑,要么全部执行,要么一个都不执行。

在 redis2.8 的版本中,引入了set指令的拓展参数,可以让 SETNX 和 EXPIRE 同时执行(原子),解决了超时问题,

SET LOCK-KEY-NAME true ex 5 nx

超时问题

上面虽然说到利用给锁设置过期时间解决可能会发生的死锁问题,但是万一我的程序代码执行时间超过了设置的过期时间,这时候锁自动释放了,但是我的代码还没执行完毕,其他人又进行执行了,导致结果出错怎么办?

在一般的开发场景中,我们会尽量将锁的时间设置的长一些,例如60s,一般应用程序在60s内都能执行完毕,但是怕就怕的是较真,如果60s内也执行不完怎么办?

此时可以使用一种续期的方案,就是当程序在执行过程中,不断的判断锁是否快要过期,代码是否执行完毕,如果快过期了没有执行完毕,就将这把锁进行续期,保证锁不会被自动释放,直到我们的代码执行完毕为止,这种方案在java中由一个叫做 redisson 的框架实现了,可以直接引入使用。

锁误放问题

在锁的使用过程中,很有可能出现其他应用没有拿到锁,但是也执行了 DEL 指令,将我们正在执行中的程序的锁释放了,导致其他地方拿到锁,进入代码段开始执行,

这里的解决方式是,在SETNX的时候,可以将value设置成一个随机生成并全局唯一的一串数字或字符,该线程一直持有字符,在释放锁的时候,将字符与锁中的字符进行比对,如果匹配,则可以进行释放锁,如果不匹配,说明是其他人误放,此时拒绝释放,

但是判断字符是否相同与释放锁并不是原子操作,redis也并不提供这么一种命令,所以我们考虑使用lua脚本执行这几步操作(redisson也实现了),

最重要的一点是,程序中使用释放锁的入口一定要统一,万一有的应用程序不使用上面所述的方法释放,直接使用 DEL ,那么上面说的方案就没用了(笔者为了测试,直接用DEL释放过)。

可重入性

可重入性是指线程在持有锁的情况下,再次请求加锁,如果一个锁支持同一个线程的多次加锁,那么这个锁就是可重入的,Java中的 ReentrantLock 就是可重入锁,大致的原理就是每次获取到锁后对一个数字进行 +1,每次释放的时候进行 -1,当数字为0时,分布式锁被释放,

redis锁如果要支持可重入性,也需要用上面的方式进行支持,不过该逻辑加重了复杂性,一般推荐将需要锁的代码段进行逻辑调整,避免重复获取分布式锁来处理。(当然redisson也支持了可重入锁)

Redlock

上面的方式看起来没有太多的问题了,但是由于redis本身可能也会发生问题,例如在Sentinel集群中,主节点挂掉,从节点变成主节点,但是客户端这时候是不知道的,

如果客户端在刚刚挂掉的主节点上SETNX成功了,但是这把锁还没有同步到从节点中,从节点这时候变成了主节点,这时候新主节点中没有这把锁的信息,

此时另一个客户端来请求这把锁,直接 SETNX 成功,又导致了两个客户端同时在执行相同的代码,又出现了不安全性,

Redis分布式锁怎么应用

为此业界提供了叫做 Redlock 的解决方案,原理大致是,提供多台redis实例,这些实例之间相互独立,没有主从关系(没有任何关系),同其他分布式算法一样,使用了大多数机制,

加锁时,它会向过半节点发出 set(key, value, nx = True, ex = xxx)指令,只要过半节点设置成功,这把锁就算拿到了,释放锁时向所有节点发出 DEL 指令,

Redlock算法(Redisson已支持)需要考虑出错重试,时钟漂移等等细节问题,同时Redlock需要向多个节点进行读写,性能将要比单例redis下降,

如果业务场景对错误的发生容忍度很低,又可以接受性能稍微有点下降,可以考虑采用Redlock算法。

感谢各位的阅读,以上就是“Redis分布式锁怎么应用”的内容了,经过本文的学习后,相信大家对Redis分布式锁怎么应用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Redis分布式锁怎么应用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Redis分布式锁怎么应用

这篇文章主要讲解了“Redis分布式锁怎么应用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Redis分布式锁怎么应用”吧!分布式锁在单进程应用中,当一段代码同一时间内只能由一个线程执行时,
2023-06-21

redis分布式锁怎么使用

使用Redis分布式锁的一般步骤如下:获取锁:在Redis中使用SET命令尝试设置一个带有过期时间的键值对作为锁。可以使用命令SET key value EX seconds NX,其中key为锁的唯一标识,value可以是任意值,seco
2023-10-21

怎么使用redis分布式锁

本篇内容介绍了“怎么使用redis分布式锁”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. redis在实际的应用中不仅可以用来缓存数据,
2023-06-25

Redis怎么实现分布式锁

这篇文章主要介绍“Redis怎么实现分布式锁”,在日常操作中,相信很多人在Redis怎么实现分布式锁问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Redis怎么实现分布式锁”的疑惑有所帮助!接下来,请跟着小编
2023-06-02

redis分布式锁怎么释放

如何释放 redis 分布式锁Redis 分布式锁是一种用于在分布式系统中协调对共享资源的访问的技术。释放分布式锁至关重要,因为它可以确保资源在使用后被正确释放,从而防止死锁和数据不一致。释放 Redis 分布式锁的步骤:1. 获取锁
redis分布式锁怎么释放
2024-05-21

分布式锁的原理及Redis怎么实现分布式锁

这篇文章主要介绍“分布式锁的原理及Redis怎么实现分布式锁”,在日常操作中,相信很多人在分布式锁的原理及Redis怎么实现分布式锁问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”分布式锁的原理及Redis怎么
2023-02-02

怎么用Go+Redis实现分布式锁

这篇文章主要介绍怎么用Go+Redis实现分布式锁,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!为什么需要分布式锁用户下单锁住 uid,防止重复下单。库存扣减锁住库存,防止超卖。余额扣减锁住账户,防止并发操作。分布式
2023-06-22

Redis分布式锁有什么用

这篇文章给大家分享的是有关Redis分布式锁有什么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1. 什么是分布式锁分布式与单机情况下最大的不同在于其不是多线程而是多进程,而数据只有一份(或有限制),也就是说单
2023-06-25

redis怎么用分布锁

如何使用 redis 实现分布式锁?获取锁:使用 setnx 设置唯一键为当前进程 id,若不存在则成功获取锁。设置过期时间:使用 expire 设置锁的过期时间,以防进程意外崩溃。执行临界区操作:在获取锁后执行共享资源操作。释放锁:完成后
redis怎么用分布锁
2024-05-21

Laravel中怎么使用Redis分布式锁

这篇文章主要介绍“Laravel中怎么使用Redis分布式锁”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Laravel中怎么使用Redis分布式锁”文章能帮助大家解决问题。创建锁use Illum
2023-07-04

Redis怎么样实现分布式锁

这篇文章主要介绍了Redis怎么样实现分布式锁,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。在一个分布式系统中,会遇到一些需要对多个节点共享的资源加锁的情况,这个时候需要用到
2023-06-21

spring redis分布式锁怎么实现

在Spring中实现Redis分布式锁可以使用RedisTemplate来操作Redis进行加锁和解锁。首先,我们需要定义一个分布式锁的实体类,包含锁的名称和锁的过期时间:public class RedisLock {private
2023-10-27

Redis分布式锁怎么实现及应用场景是什么

本篇内容介绍了“Redis分布式锁怎么实现及应用场景是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!引言锁是开发过程中十分常见的工具,你
2023-06-29

java怎么使用redis实现分布式锁

使用Redis实现Java分布式锁使用RedisSETNX和EXPIRE命令,可以实现分布式锁,协调对共享资源的访问。获取锁时,尝试设置唯一键,并设置过期时间。释放锁时,删除键。使用Redis的分布式特性和命令的易用性,可以简单且健壮地实现分布式锁。但需要注意键的唯一性、过期时间和竞争条件等注意事项。
java怎么使用redis实现分布式锁
2024-04-11

java怎么使用redis实现分布式锁

在Java中使用Redis实现分布式锁可以通过以下步骤:1. 引入Redis相关的依赖,例如Jedis或Lettuce。2. 创建一个Redis连接池或连接工厂,用于获取Redis连接。3. 使用Redis连接实例,调用setnx命令(或相
2023-10-09

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录