分布式锁——什么是看门狗?什么是redlock算法?带你全面了解~

目录

1、什么是分布式锁

2、引入setnx

3、引入过期时间

4、引入检验id

5、引入lua脚本

6、引入看门狗

7、redlock算法


1、什么是分布式锁

        我们在前面学习中,都有了解关于线程安全的问题,那引发这个问题的关键就是,多个线程去修改了同一个公共资源引发的“一票多卖”的问题,例如Java中就可以使用synchronized来保证线程安全。但这种方法只是在同一进程下管用,当我们引入了分布式系统后,是多个进程在工作,那多个进程在多个主机下,想要同时修改数据库中的某些公共资源而引发的问题,我们该如何解决呢?

        这里就要使用到分布式锁了。其本质上就是使用一个公共的服务器来记录加锁状态。这个公共服务器可以是Redis,也可以是其他组件如MySQL/ZooKeeper,也可以是我们自己写的一个服务器~

        上面这些听着云里雾里的,我们结合下图可以有一个更加清晰的思路:

不添加分布式锁:

        上图中,可以观察到,三个服务器,可能会出现同时查询票数的情况,此时查出来的票数都是1,都开始进行买票操作,此时就可能会出现,票已经为0了,还在售票的情况~

添加分布式锁:

 说明:

  • 如果服务器1尝试进行买票,就需要先访问Redis,在Redis上设置一个键值对,比如key就是车次,value设置为某个值(1)。
  • 如果这个操作设置成功,就视为当前没有节点对该key001车次枷锁,就可以进行数据库的读写操作了,操作完后,再把这个Redis上刚才的这个键值对删除即可。 
  • 如果在服务器1操作数据库的过程中,买票服务器2也想买票,也会尝试去给Redis上写一个键值对,key同样是车次,但此时key已经存在了,则认为已经有其他服务器正在持有锁,服务器2要么选择等待,要么选择暂时放弃~

2、引入setnx

        为什么引入setnx:

        上面提到添加分布式锁,在里面的一个实现思路是,在Redis中添加一个键值对,如果键值对存在,则加锁成功,否则加锁失败。那么结合我们前面学习过的Redis命令中,有一个命令和这里就非常的符合:setnx--->这里的就是设置key,不存在设置成功,否则设置失败。后续操作完成,解锁则是直接将这个键值对即可~

        总的来说就是三步:

  • 加锁,尝试设置key-value
  • 执行业务操作
  • 解锁,删除key-value

        上面的这个三个步骤中,也会引起一个问题:如果说加锁成功后,还没来得及解锁,服务就崩溃了,服务器直接给挂了,服务就卡这了,这时该怎么办?【这里要注意的一个点,挂掉的是业务服务器不是Redis服务器,相当于是服务器1把001车次锁住了,服务器1又挂掉了,但是Redis这边已经显示车次001还在加锁状态,所以其他服务器都没法来售卖001车次的票了...】

        下面就是引入过期时间,来解决上述问题:


3、引入过期时间

        引入过期时间,当时间到了,key就自动被删除了。例如:设置key的过期时间为1000ms,这就意味着,即使服务器1挂掉了,1000ms到了后,这个key就被删了,其他服务器可以正常售卖车次001的车票了~

        使用命令set ex nx来完成这样的设置,最好不要使用命令setnx    +  命令expire  ,因为Redis中多个命令之间无法保证原子性,可能会出现一个命令成功,一个命令失败了。

        上述操作也可能存在问题,Redis中的key被误删了~ 为什么会出现这种情况呢? 因为对于Redis中写入的加锁键值对,其他节点是可以对其进行删除的。例如服务器1设置了key,服务器2却把这个key去给删掉了。为什么会出现服务器2去平白无故在加锁服务器上删数据呢?最常见的就是可能出bug了,导致其误删了。

        下面就是引入了检验id,来解决上述问题:


4、引入检验id

        引入检验id,id添加在哪里呢?举例方法不唯一:例如我们可以设置value中,上述的value我们设为了1,现在可以修改一下,value存为服务器编号,例key:车次001,value:"服务器 1"

        这样设置后,再删除key时,需要先校验当前删除的key的服务器是否是当初加锁的服务器,如果是,才能执行删除操作~

        上述操作,又会出现一个问题,删除时,要先查询get,确认后再删除del,这是两个命令操作,无法保证其原子性。这两个操作无法保证原子性,为什么会带来问题呢?我们这两个操作都是在Redis加锁服务器中执行的,那一个服务器中,一个进程里,我们就需要考虑到线程安全问题。结合下图来看:

        上图中,体现的意思就是,服务器1向Redis服务器发送了两个请求,都是删除key,因为服务器id是正确的,所以两个get获取并对比后,都表示都可以进行删除操作,线程A删除后,线程B再删除一次到也没问题,就担心另一个服务器刚加过来一个key,转手就被刚才第二个del给删除掉了~

        因此,为了保证他的原子性,下面引入lua脚本就是为了解决该问题:


5、引入lua脚本

        我们为什么不使用事务来保证他的原子性呢?首先就是Redis的事务是可以解决上述这样的问题的,但是Redis官方有说明,更好地方案就是使用lua脚本来解决原子性问题~

        使用lua脚本的原因:

  • lua脚本非常的轻量(实现一个lua解释器消耗的体积非常小)
  • Redis执行lua脚本的过程是原子的,相当于执行一条命令一样(lua脚本中编写一些逻辑,把这个脚本上传到Redis服务器上,然后就可以让客户端来控制Redis执行上述脚本了)
  • Redis官方说明,lua就是属于事务的替代方案~

6、引入看门狗

        刚才引入过期时间,其实还会导致一个问题,如果设置的时间不合适,可能会导致操作还没有执行完毕,时间过期了,锁释放了;或者是时间太长了就会导致锁释放不及时这样的问题。为了解决这样的问题,我们就要考虑时间续约的问题。

        在Redis中,使用的“动态续约”,也就是说会有专门的一个线程来负责续约的事情,这个线程就叫做看门狗~

        实现的大致场景:

  • 初始情况下,设置一个过期时间(例:1s),还剩一点时间(例:300ms)的时候,如果当前任务还没有执行完,就把过期时间再续上(1s),等到时间快到了,任务没完,又可以继续续约了~
  • 如果说服务器中途崩溃了,自然就没有人续约了,此时锁就能在较短时间内被自然释放~

7、redlock算法

        我们这里使用分布式锁,是引入了一个新的Redis服务器,既然是一个服务器,我们就需要考虑到这个服务器如果挂了的情况,如果这个Redis服务器挂了,后续的业务操作没法进行加锁了,就可能会造成一些很严重的问题。

        错误的解决方案:引入从节点,使用主从复制的方式,再加上哨兵节点,主节点挂了,从节点就可以自动补上了。为什么说是错误的解决方案?因为主从节点的数据同步需要时间,如果主节点过来的加锁操作,从节点还没收到数据同步,主节点解挂了~

        正确的解决方案:使用redlock算法。

redlock算法简单介绍:

        引入多组Redis节点。其中每一组Redis节点都包含一个主节点和若干个从节点 并且组和组之间存储数据都是一致的,相互之间是“备份”关系【和集群不同,并不是一个主节点上只存储数据的一部分】。加锁的时候,按照一定的顺序,写多个Master节点。在写锁的时候需要设定操作的“超时时间”,例如50ms,如果setnx操作超过了50ms还没成功,就视为是加锁失败了~

结合下图来看:

上图的从节点,我就不画了~

说明:

  • 如果给某个节点加锁失败,就立即尝试下一个节点
  • 当加锁成功的节点数超过总数的一半,才视为加锁成功--》这样的话,即使有的节点挂了,也不会影响锁的正确性
  • 释放锁的时候, 也需要把所有节点都进⾏解锁操作. (即使是之前超时的节点, 也要尝试解锁, 尽量保 证逻辑严密).
  • Redlock 算法的核⼼就是, 加锁操作不能只写给⼀个 Redis 节点, ⽽要写个多个!! 分布式系统 中任何⼀个节点都是不可靠的. 最终的加锁成功结论是 "少数服从多数的"

好了,本篇文章就到这里啦,上面我们只是简单了解了一下 互斥锁~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/143872.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MIPI协议介绍-CPHY

MIPI协议概述 MIPI(Mobile Industry Processor Interface): 是MIPI联盟发起为移动应用处理器制定的开放标准.MIPI接口协议层主要包括CSI和DSI两种,其中CSI主要用于图像输出,如图像传感器等; DSI主要用于图像输入,如屏幕显示器等.对于camera而…

vs2019配置libcurl环境

一、libcurl下载地址:curl - Download 二、解压下载的压缩包,进入projects\Windows\VC14目录 三、用vs2019打开curl-all.sln工程,选择LIB Debug,x64进行编译 编译后的文件为:curl-8.2.1\build\Win64\VC14\LIB Debug\li…

【Git】轻松学会 Git(一):掌握 Git 的基本操作

文章目录 前言一、创建 Git 本地仓库1.1 什么是仓库1.2 创建本地仓库1.3 .git 目录结构 二、配置 Git三、认识 Git 的工作区、暂存区和版本库3.1 什么是 Git 的工作区、暂存区和版本库3.2 工作区、暂存区和版本库之间的关系 四、添加文件4.1 添加文件到暂存区和版本库中的命令4…

【python入门篇】列表简介及操作(2)

列表是什么? 列表是由一系列按特定顺序排列的元素组成。你可以创建包含字母表中的所有字母、数字 0~9 或所有家庭成员的列表;也可以将任何东西加入列表中,其中的元素之间可以没有任何关系。列表通常包含多个元素,因此给列表指定一…

太实用了! 20分钟彻底理解【Pointpillars论文】,妥妥的!

PointPillars: Fast Encoders for Object Detection from Point Clouds PointPillars:快就对了 摘要(可跳过): 这帮人提出了PointPillars,一种新颖的编码器,它利用PointNets来学习以垂直列组织的点云&am…

标题:探寻电大搜题,广东开放大学的智慧之旅

随着信息技术的快速发展和互联网的普及,越来越多的人开始选择通过电大学习。作为知名的广东开放大学,一直致力于提供高质量的教育资源,让更多人实现自己的梦想。在这个过程中,电大搜题微信公众号成为了学生们的得力助手&#xff0…

Arduino PLC IDE

Arduino PLC IDE MCU单片机进入全新的PLC领域概述需要的硬件和软件下一步操作1. Arduino PLC IDE Tool Setup2. Arduino PLC IDE Setup3. Project Setup4. Download the Runtime5. Connect to the Device6. License Activation with Product Key (Portenta Machine Control) 结…

【小笔记】fasttext文本分类问题分析

【学而不思则罔,思维不学则怠】 2023.9.28 关于fasttext的原理及实战文章很多,我也尝试在自己的任务中进行使用,是一个典型的短文本分类任务,对知识图谱抽取的实体进行校验,判断实体类别是否正确,我构建了…

解决Spring Boot 2.7.16 在服务器显示启动成功无法访问问题:从本地到服务器的部署坑

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

定义豪车新理念 远航汽车亮相2023中国(天津)国际汽车展览会

近年来,随着汽车行业竞争持续加剧,老品牌面临积极转型,新势力则经验不足、实力欠佳,到底是难抵市场的风云变幻。在此背景下,有着“老品牌 新势力”双重基因的远航汽车可谓底气十足。作为大运集团携手博世、华为、阿里斑…

陪诊系统|陪诊软件医疗陪护的创新之路

陪诊服务系统源码功能及解决方案,在一对一专属服务,就医经验丰富的专业陪诊师的陪伴下,就医体验得以优化,就医全程无须自行探究和寻找,就医过程更加省心,同时减轻了家属时间精力的负担。陪诊服务系统提供的…

城市智慧公厕:引领科技创新的新时代

城市智慧公厕已经成为当下社会治理模式的升级范式,催生了无限的科技创新。如智慧公厕源头厂家广州中期科技有限公司,所推出的智慧公厕整体解决方案,除基本的厕位监测与引导、环境监测与调节、安全防范与管理、保洁考勤管理、多媒体交互、综合…

【Verilog 教程】6.2Verilog任务

关键词:任务 任务与函数的区别 和函数一样,任务(task)可以用来描述共同的代码段,并在模块内任意位置被调用,让代码更加的直观易读。函数一般用于组合逻辑的各种转换和计算,而任务更像一个过程&a…

高防服务器给企业带来的优势有哪些?

高防服务器主要指的是能够提供给网络安全提供高防护的服务器,通过流量清洗、负载均衡等手段来抵御DDoS攻击、CC攻击这一类流量攻击,为企业提供了强大的数据保障,互联网时代数据安全是放在第一位的,数据泄漏的话不论对于企业还是对…

google的日志glog安装及使用

1.glog glog是google出的一个轻量级的c日志库 2.下载及编译 下载或克隆库,我选择的是V0.6.0版本: github.com/goolge/glog/releases/tag/v0.6.0 我用cmake编译(参考:github.com/google/glog#cmake) 按照说明步骤进…

Python入门自学进阶-Web框架——42、Web框架了解-bottle、flask

WEB框架的三大组件:路由系统、控制器(含模板渲染)、数据库操作 微型框架:依赖第三方写的socket,WSGI, 本身功能少 安装: pip install bottle pip install flask 安装flask,同时安…

力扣每日一题(+日常水题|树型dp)

740. 删除并获得点数 - 力扣(LeetCode) 简单分析一下: 每一个数字其实只有2个状态选 or 不 可得预处理每一个数初始状态(不选为0,选为所有x的个数 * x)累加即可 for(auto &x : nums)dp[x][1] x;每选一个树 i 删去 i 1 和 i - 1 故我们可以将 i…

【笔记】离线Ubuntu20.04+mysql 5.7.36 + xtrabackup定时增量备份脚本

一、环境 ● Ubuntu版本查看 lsb_release -a● mysql 版本查看 mysql --version我的是ubuntu 20.04,mysql是5.7.36,所以要用 install_percona-xtrabackup-24 二、原理 备份 通过ubuntu自带的定时器运行增量备份脚本备份文件可以存储在映射后的其他…

26593-2011 无损检测仪器 工业用X射线CT装置性能测试方法

声明 本文是学习GB-T 26593-2011 无损检测仪器 工业用X射线CT装置性能测试方法. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了工业用X 射线CT 装置(以下简称CT 装置)性能测试的术语、定义、缩略语以及空间 分辨力、密度分辨率…

#硬件电路设计VL817-Q7(B0)芯片拓展USB3.0一转四调试心得

供电电路 基于XL4005的电源供电电路 SS34肖特基二极管 ZMM5V1稳压二极管 SMAJ15A TVS (注意这个封装搞错5V会短接) Vout0.8*[1(R2R3)/R1] D14 SR05静电防护器件 一路稳压两路TVS 共模电感 : 型号: SDCW2012-2-900TF 品牌&#…