[Redis]典型应用——分布式锁

news2024/9/19 6:39:09

什么是分布式锁?

在一个分布式系统中,也会涉及到多个节点访问同一个公共资源的情况。此时就需要通过锁来做互斥控制,避免出现类似于"线程安全"的问题

举个例子,在平时抢票时,多个用户可能会同时买票,但票数有限,现在存在多个服务器节点,都可能需要处理这个买票的逻辑:先查询指定车次的余票,如果余票>0,则设置余票值-=1 。显然,这样的情况是存在线程安全问题的,如果不加锁控制,就会导致超卖或数据错误。但是,这可能涉及到不同的机器,而不是传统的同一个线程可以加锁,不同的机器间怎么保证线程安全呢?

为了解决上述问题,我们就可以把redis作为架构中分布式锁的管理器。

分布式锁本质上就是一个架构内一台公共的服务器,用来记录加锁状态,而redis就可以完成这样的工作

工作原理 

 为了防止出现线程安全问题,我们可以在服务器操作数据库之前要先访问redis,在redis上设置一个键值对(mutex:1),如果设置成功,视为获取锁成功,就可以对数据库操作,操作完后,就把redis对应的数据删掉,视为释放锁。在这期间,如果其他服务器想操作数据库,也必须先设置同样的key,设置失败就不能访问数据库。

引入过期时间

但是上述方案还是有问题,如果设置key后,服务器宕机了怎么办?锁就永远无法释放了,所以我们就要设置key的过期时间

服务器在设置key的时候,同时设置key的过期事件,也就是说这个锁最多持有多久,过期自动释放。

注意!此处的过期时间只能使用一个命令的方式设置

如果分开多个操作,比如setnx之后,再来一个单独的expire,由于Redis的多个指令之间不存在关 联,并且即使使用了事务也不能保证这两个操作都一定成功,因此就可能出现setnx成功,但是expire 失败的情况

此时仍然会出现无法正确释放锁的问题

 引入校验id

有没有可能自己设置的锁被别人释放了呢?请看下图

可能会因为一些潜在bug或误操作,释放了别人设置的锁,就会发生很大的问题

为了解决这个问题,我们可以引入校验id

 也就是设置key时设置的value改成有意义的能表示身份的值,比如可以把客户端编号,几号客户端设置的key就把value设置成几

这样,在释放锁,也就是删除key的时候,先校验删除的key的value是不是对应当初加锁的值,如果是,再删数据

引入lua

但是上面这个操作中,先get key再del key 这两步并不是原子的,也会有线程安全问题。

为了让解锁操作原子性,可以使用redis的lua脚本功能

Lua也是一个编程语言.读作"撸啊"。是葡萄牙语中的"月亮"的意思

为什么redis会选择lua作为内嵌的脚本语言呢?因为Lua语法简单精炼,执行速度快,解释器也比较轻量,内嵌到redis中不会太过于臃肿

lua脚本可以编写成一个.lua后缀的文件,可以由 redis-cli 发送给redis,由redis服务器来执行脚本

一个lua脚本会被redis服务器以原子的方式执行

引入看门狗(watch dog)

上述方案仍然有一定问题,当我们设置过期时间(比如10s)后,如果任务还没有执行完,锁就已经过期失效了,怎么办?

那就可以引入看门狗,本质上是服务器上的一个单独的线程,通过这个线程来对锁过期时间进行"续约"

比如说,我们设置10s过期,设置看门狗每隔3s检测一次,每过3s,看门狗就去判定当前任务是否完成,如果任务完成了,就释放锁,如果任务未完成,就把过期时间重新设置成10s(续约)

值得一提的是,看门狗线程应该是业务服务器的线程,而不是redis服务器的线程

这样,不用担心锁提前过期,就算服务器挂了,看门狗线程也就挂了,就没人去续约,过期就会释放锁了

引入redlock算法

到这里,方案还是有一定问题,如果redis服务器(也就是分布式锁管理器)挂了,怎么办?那我们可以对redis服务器设计主从架构,保证redis服务器的可用性

那么就有一个问题,如果当我获取锁之后,redis主服务器挂了,从服务器变成了主服务器,但是加锁的数据还没有同步,这时候获取的锁失效了,别的服务器仍然可以获取锁

为了解决这个问题,Redis的作者提出了Redlock算法

我们引入一组Redis节点,其中每一组Redis节点都包含一个主节点和若干从节点.并且组和组之间存储的数据都是一致的,相互之间是"备份"关系

首先,获取锁

客户端依次向Redis 节点(通常是 5 个)请求加锁。每个节点使用相同的 key 和一个唯一的随机值(UUID)(校验用)。

客户端在每个节点上设置锁的过期时间(TTL),以防止锁的持有者崩溃后锁无法释放。

如果客户端无法在某个节点上设置锁(例如,实例不可用或已经被其他客户端持有锁),则立即尝试下一个节点。

其次,检查锁的有效性

客户端计算从开始尝试加锁到完成加锁操作的总时间。

如果总时间小于锁的 TTL ,且客户端至少在 N/2 + 1 个节点上成功加锁,则认为锁获取成功。如果锁获取失败(未能在足够多的节点上成功加锁),客户端应立即在所有节点上释放已获取的锁。

比如说锁过期时间为50ms,有5个redis节点,从给第一个节点加锁开始算,到最后一个节点加锁截止,如果加起来总时间小于锁的过期时间(50ms),而且至少有3个节点加锁成功,那么就获取一个锁成功(50ms)

因为如果加锁流程时间太长,比如锁过期时间是50ms,结果光去各个节点加锁就用了100ms,那肯定有部分锁都已经过期了,这时候也就不能认为加锁成功了 

最后,释放锁

客户端在所有实例上依次释放锁。释放锁时,客户端需要检查锁的值是否与自己持有的随机值一致,以确保只有持有锁的客户端才能释放锁。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux——多路复用之poll

目录 前言 一、poll的认识 二、poll的接口 三、poll的使用 前言 前面我们学习了多路复用的select,知道多路复用的原理与select的使用方法,但是select也有许多缺点,导致他的效率不算高。今天我们来学习poll的使用,看看poll较于…

利用AI与数据分析优化招聘决策

一、引言 在竞争激烈的职场环境中,招聘是组织获取人才、实现战略目标的关键环节。然而,传统的招聘方式往往依赖人力资源部门的主观经验和直觉,难以准确预测招聘效果,评估招聘渠道的效率。随着人工智能(AI)…

Windows右键新建Markdown文件类型配置 | Typora | VSCode

🙋大家好!我是毛毛张! 🌈个人首页: 神马都会亿点点的毛毛张 今天毛毛张分享的是如何在右键的新建菜单中添加新建MarkdownFile文件,这是毛毛张分享的关于Typora软件的相关知识的第三期 文章目录 1.前言🏝…

Android车载MCU控制音量和ARM控制音量的区别和优缺点—TEF6686 FM/AM芯片

不要嫌前进的慢,只要一直在前进就好 文章目录 前言一、系统架构图1.MCU控制音量的架构图(老方法)2.ARM控制音量的架构图(新方法) 二、为啥控制音量不是用AudioManager而是执着去直接控制TDA7729?三、MCU控制…

[数据集][目标检测]婴儿车检测数据集VOC+YOLO格式1073张5类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):1073 标注数量(xml文件个数):1073 标注数量(txt文件个数):1073 标注…

Matlab基础语法篇(下)

Matlab基础语法(下) 一、逻辑基础(一)逻辑运算符(二)all、any、find函数(三)练习 二、结构基础(一)条件结构(1)if-elseif-else-end&am…

通过albumentation对目标检测进行数据增强(简单直接)

albumentation官方文档看不懂?xml文件不知道如何操作?下面只需要修改部分代码即可上手使用 要使用这个方法之前需要按照albumentation这个库还有一些辅助库,自己看着来安装就行 pip install albumentation pip install opencv-python pip install json…

<数据集>蛋壳裂缝检测数据集<目标检测>

数据集格式:VOCYOLO格式 图片数量:2520张 标注数量(xml文件个数):2520 标注数量(txt文件个数):2520 标注类别数:2 标注类别名称:[crack, egg] 序号类别名称图片数框数1crack245128352egg25142514 使…

揭秘饲料制粒机:生产颗粒料加工的利器

随着现代畜牧业的发展,饲料的质量和加工效率成为了养殖业者关注的焦点。在这个背景下,饲料制粒机——这一饲料加工设备的核心,凭借其稳定、环保的特点,逐渐加入养殖行业中。 一、饲料制粒机的工作原理 饲料制粒机主要通过挤压、切…

msyql (8.4,9.0) caching_sha2_password 转换 mysql_native_password用户认证

mysql 前言 caching_sha2_password 主要特性 用于增强用户账户密码的存储和验证安全性。这种插件利用 SHA-256 散列算法的变体来存储和验证密码 安全的密码散列: caching_sha2_password 使用基于 SHA-256 的算法来生成密码的散列值。这意味着即使数据库被未授权访…

【JS特效之手风琴效果】基于jquery实现手风琴网页特效(附源码)

HTMLCSSJS手风琴效果目录 🍔涉及知识🥤写在前面🍧一、网页主题🌳二、网页效果🐋三、网页架构与技术3.1 脑海构思3.2 实现原理 🌈四、网页源码4.1 手风琴模块4.2 完整源码获取方式 🌅 作者寄语 &…

机械学习—零基础学习日志(高数05——函数概念与特性)

零基础为了学人工智能,真的开始复习高数 本小节讲解隐函数,有点神奇,我竟然完全没有隐函数记忆了。 隐函数 隐函数,我个人通俗理解就是,在复杂的环境里,发现纯净天地。例如,在外太空的某个大陆…

《JavaSE》---14.<面向对象系列之(附:this和super关键字)>

目录 系列文章目录 前言 一、为什么要有this引用 1. 用代码看有this与无this的区别 1.1 代码示例 1.2 输出结果: 1.3 代码示例: 1.4 输出结果: 2. this深度理解 3. 什么是this引用 3.1 this引用的概念 4. this引用的特性 二、th…

【TAROT学习日记】韦特体系塔罗牌学习(5)——皇帝 THE EMPEROR IV

韦特体系塔罗牌学习(5)——皇帝 THE EMPEROR IV 目录 韦特体系塔罗牌学习(5)——皇帝 THE EMPEROR IV牌面分析1. 基础信息2. 图片元素 正位牌意1. 关键词/句2.爱情婚姻3. 学业事业4. 人际财富5. 其他象征意 逆位牌意1. 关键词/句2…

大盘周期性复苏之际,英诺赛科的新叙事如何开讲?

半导体行业已经开始周期性复苏。 据同花顺iFinD统计,截至目前,已有37只半导体个股披露了上半年业绩预告,其中27股预喜,或扭亏或预增,预喜率超七成,长川科技净利预增幅度位居第一,暂列上半年半导…

Cadence OrCAD Capture原理图搭建及仿真方法

1 安装Cadence Allegro 略。 2 搭建原理图 2.1 打开软件 1、点击Capture CIS。 2、在弹出的产品选择栏点击OrCAD Capture,点击OK。 打开的软件界面如下: 2.2 新建工程 1、点击左上角File,New,Project,或者直接点…

王权与自由Steam国际服下载教程分享

王权与自由,一款集合了所有mmorpg游戏内玩法的游戏,包含爬塔、小队副本、团队副本、休闲竞技、装备打造、人物养成、攻城战、大型的pvp团战等多种游戏玩法,在游戏中只有我们想不到的内容,没有游戏不包含的内容,而且有意…

【Git远程操作】克隆远程仓库 https协议 | ssh协议

目录 前言 克隆远程仓库https协议 克隆远程仓库ssh协议 前言 这四个都是Git给我们提供的数据传输的协议,最常使用的还是https和ssh协议。本篇主要介绍还是这两种协议。 ssh协议:使用的公钥加密和公钥登录的机制(体现的是实用性和安全性&am…

AIGC工具:IPAdapter和ControlNet 指导控制生成工具

ControlNet强调对生成过程的直接控制,如通过线条、边缘、形状等信息;而IPAdapter侧重于风格迁移和内容的间接引导。 IPAdapter 它专注于通过迁移图片风格来生成新的图像内容。IPAdapter的强项在于能够将一张图片的风格迁移到另一张图片上,实现风格融合,甚至可以进行多图风格…

【Android】ConstrainLayout约束布局基本操作

文章目录 介绍约束条件添加方式外边距设置删除方式 添加约束条件父级位置对齐方式基线对齐引导线约束屏障约束 约束偏差使用链控制线性组 介绍 约束布局ConstraintLayout是 Android Studio 2.3 起创建布局后的默认布局 主要是为了解决布局多层嵌套问题,以灵活的方式…