21.Redis之分布式锁
1.什么是分布式锁
- 在⼀个分布式的系统中, 也会涉及到多个节点访问同⼀个公共资源的情况. 此时就需要通过 锁 来做互斥控制, 避免出现类似于 "线程安全" 的问题.
- ⽽ java 的 synchronized 或者 C++ 的 std::mutex, 这样的锁都是只能在当前进程中⽣效, 在分布式的这种多个进程多个主机的场景下就⽆能为⼒了.
- 此时就需要使⽤到分布式锁

- 在分布式系统中,是有很多进程的(每个服务器,都是独立的进程)因此,之前的锁,就难以对现在分布式系统中的多个进程之间产生制约.....分布式系统中,多个进程之间的执行顺序也是不确定的 =>随机性
- 引入"分布式锁"来解决上述问题


- 不存在就设置
- 存在就出错(失败)
- setnx
2.引入setnx
3.引入过期时间
- 当 服务器1 加锁之后, 开始处理买票的过程中, 如果 服务器1 意外宕机了, 就会导致解锁操作 (删除该 key) 不能执⾏. 就可能引起其他服务器始终⽆法获取到锁的情况
- 为了解决这个问题, 可以在设置 key 的同时引⼊过期时间. 即这个锁最多持有多久, 就应该被释放.
- 可以使⽤ set ex nx 的⽅式, 在设置锁的同时把过期时间设置进去
- 注意! 此处的过期时间只能使⽤⼀个命令的⽅式设置.
- 如果分开多个操作, ⽐如 setnx 之后, 再来⼀个单独的 expire, 由于 Redis 的多个指令之间不存在关
- 联, 并且即使使⽤了事务也不能保证这两个操作都⼀定成功, 因此就可能出现 setnx 成功, 但是 expire失败的情况.
- 此时仍然会出现⽆法正确释放锁的问题.

4.引入校验id
- 对于 Redis 中写⼊的加锁键值对, 其他的节点也是可以删除的.
- ⽐如 服务器1 写⼊⼀个 "001": 1 这样的键值对, 服务器2 是完全可以把 "001" 给删除掉的.
- 当然, 服务器2 不会进⾏这样的 "恶意删除" 操作, 不过不能保证因为⼀些 bug 导致 服务器2 把锁误删除.
- 为了解决上述问题, 我们可以引⼊⼀个校验 id.
- ⽐如可以把设置的键值对的值, 不再是简单的设为⼀个 1, ⽽是设成服务器的编号. 形如 "001": "服务器1".
- 这样就可以在删除 key (解锁)的时候, 先校验当前删除 key 的服务器是否是当初加锁的服务器, 如果是, 才能真正删除; 不是, 则不能删除

5.引入lua脚本
- 为了使解锁操作原⼦, 可以使⽤ Redis 的 Lua 脚本功能
- Lua 也是⼀个编程语⾔. 读作 "撸啊". 是葡萄⽛语中的 "⽉亮" 的意思. (出⾃于 Lua 官⽅⽂档 https://www.lua.org/about.html)
- Lua 的语法类似于 JS, 是⼀个动态弱类型的语⾔. Lua 的解释器⼀般使⽤ C 语⾔实现. Lua 语法简单精炼, 执⾏速度快, 解释器也⽐较轻量(Lua 解释器的可执⾏程序体积只有 200KB 左右).
- 因此 Lua 经常作为其他程序内部嵌⼊的脚本语⾔. Redis 本⾝就⽀持 Lua 作为内嵌脚本.
很多程序都⽀持内嵌脚本, ⽐如 MySQL 8 ⽀持 JS 作为内嵌脚本, ⽐如 Vim ⽀持 VimScript 和 Python 作为内嵌脚本.... 通过内嵌脚本来实现更复杂的功能, 提供更强的扩展性.Lua 除了和 Redis 搭伙之外, 在很多场景也会作为内嵌脚本. ⽐如在游戏开发领域常常作为编写逻辑的语⾔. (⽐如魔兽世界, ⼤话西游等) 使⽤ Lua 脚本完成上述解锁功能if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) elsereturn 0 end;
- 上述代码可以编写成⼀个 .lua 后缀的⽂件, 由 redis-cli 或者 redis-plus-plus 或者
- jedis 等客⼾端加载, 并发送给 Redis 服务器, 由 Redis 服务器来执⾏这段逻辑.
- ⼀个 lua 脚本会被 Redis 服务器以原⼦的⽅式来执⾏.
6.引入看门狗(过期时间的续约问题)
- 上述⽅案仍然存在⼀个重要问题. 当我们设置了 key 过期时间之后 (⽐如 10s), 仍然存在⼀定的可能性, 当任务还没执⾏完, key 就先过期了. 这就导致锁提前失效.
- 把这个过期时间设置的⾜够⻓, ⽐如 30s, 是否能解决这个问题呢? 很明显, 设置多⻓时间合适, 是⽆⽌境的.
- 即使设置再⻓, 也不能完全保证就没有提前失效的情况.
- ⽽且如果设置的太⻓了, 万⼀对应的服务器挂了, 此时其他服务器也不能及时的获取到锁.
- 因此相⽐于设置⼀个固定的⻓时间, 不如动态的调整时间更合适
- 所谓 watch dog, 本质上是加锁的服务器上的⼀个单独的线程, 通过这个线程来对锁过期时间进⾏ "续约".注意, 这个线程是业务服务器上的, 不是 Redis 服务器的.举个具体的例⼦:初始情况下设置过期时间为 10s. 同时设定看⻔狗线程每隔 3s 检测⼀次.那么当 3s 时间到的时候, 看⻔狗就会判定当前任务是否完成.• 如果任务已经完成, 则直接通过 lua 脚本的⽅式, 释放锁(删除 key).• 如果任务未完成, 则把过期时间重写设置为 10s. (即 "续约")
- 这样就不担⼼锁提前失效的问题了. ⽽且另⼀⽅⾯, 如果该服务器挂了, 看⻔狗线程也就随之挂了, 此时⽆⼈续约, 这个 key ⾃然就可以迅速过期, 让其他服务器能够获取到锁了
7.redlock算法
- 实践中的 Redis ⼀般是以集群的⽅式部署的 (⾄少是主从的形式, ⽽不是单机). 那么就可能出现以下⽐较极端的⼤冤种情况:
- 服务器1 向 master 节点进⾏加锁操作. 这个写⼊ key 的过程刚刚完成, master 挂了; slave 节 点升级成了新的 master 节点. 但是由于刚才写⼊的这个 key 尚未来得及同步给 slave 呢, 此时 就相当于 服务器1 的加锁操作形同虚设了, 服务器2 仍然可以进⾏加锁 (即给新的 master 写⼊ key. 因为新的 master 不包含刚才的 key).
- 为了解决这个问题, Redis 的作者提出了 Redlock 算法.
- 我们引⼊⼀组 Redis 节点. 其中每⼀组 Redis 节点都包含⼀个主节点和若⼲从节点. 并且组和组之间存 储的数据都是⼀致的, 相互之间是 "备份" 关系(⽽并⾮是数据集合的⼀部分, 这点有别于 Redis cluster).
- 加锁的时候, 按照⼀定的顺序, 写多个 master 节点. 在写锁的时候需要设定操作的 "超时时间". ⽐如50ms. 即如果 setnx 操作超过了 50ms 还没有成功, 就视为加锁失败.
相关文章:
21.Redis之分布式锁
1.什么是分布式锁 在⼀个分布式的系统中, 也会涉及到多个节点访问同⼀个公共资源的情况. 此时就需要通过 锁 来做互斥控制, 避免出现类似于 "线程安全" 的问题. ⽽ java 的 synchronized 或者 C 的 std::mutex, 这样的锁都是只能在当前进程中⽣效, 在分布式的这种多…...
Mysql基础学习:mysql8 JSON字段查询操作
文章目录 一、查询JSON中某个属性值为XXX的数据量1、方式一2、方式二 二、查询的JSON中的value并去除双引号 一、查询JSON中某个属性值为XXX的数据量 1、方式一 select count(*)from table_namewhere JSON_CONTAINS(json-> $.filed1, "xxx")or JSON_CONTAINS(jso…...
搭建基于Django的博客系统数据库迁移从Sqlite3到MySQL(四)
上一篇:搭建基于Django的博客系统增加广告轮播图(三) 下一篇:基于Django的博客系统之用HayStack连接elasticsearch增加搜索功能(五) Sqlite3数据库迁移到MySQL 数据库 迁移原因 Django 的内置数据库 SQL…...
24年护网工具,今年想参加护网的同学要会用
24年护网工具集 吉祥学安全知识星球🔗http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247483727&idx1&sndb05d8c1115a4539716eddd9fde4e5c9&chksmc0e47813f793f105017fb8551c9b996dc7782987e19efb166ab665f44ca6d900210e6c4c0281&scene21…...
解决TrueNas Scale部署immich后人脸识别失败,后台模型下载异常,immich更换支持中文搜索的CLIP大模型
这个问题搞了我几天终于解决了,搜遍网上基本没有详细针对TrueNas Scale部署immich应用后,CLIP模型镜像下载超时导致人脸识别失败,以及更换支持中文识别的CLIP模型的博客。 分析 现象:TrueNas Scale安装immich官方镜像应用后&…...
面试高频问题----2
一、进程、线程、协程有什么区别? 1.进程:进程是操作系统中独立运行的程序实例,每个进程都有自己的内存空间和系统资源;进程之间相互独立,每个进程有自己的内存地址空间,一个进程无法直接访问另一个进程的…...
Nginx的配置文件-详细使用说明
Nginx的配置文件是Nginx服务器运行的核心,它决定了Nginx如何响应和处理各种请求。以下是对Nginx配置文件(通常名为nginx.conf)的详细解析,按照常见的结构和配置项进行分类: 1. 全局块 user:指定Nginx运行的用户和用户组。例如:user nginx;worker_processes:指定工作进…...
YOLOv5改进 | 卷积模块 | 提高网络的灵活性和表征能力的动态卷积【附代码+小白可上手】
💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡 轻量级卷积神经网络由于其低计算预算限制了CNNs的深度(卷积层数)和宽度(通道数),…...
23、linux系统文件和日志分析
linux文件系统与日志分析 文件时存储在硬盘上的,硬盘上的最小存储单位是扇区,每个扇区大大小是512字节。 inode:元信息(文件的属性 权限,创建者,创建日期等) block:块,…...
安装VS2017后,离线安装Debugging Tools for Windows(QT5.9.2使用MSVC2017 64bit编译器)
1、背景 安装VS2017后,Windows Software Development Kit - Windows 10.0.17763.132的Debugging Tools for Windows默认不会安装,如下图。这时在QT5.9.2无法使用MSVC2017 64bit编译器。 2、在线安装 如果在线安装参考之前的文章: Qt5.9.2初…...
路由策略实验2
对R7,重发布直连路由 对R2,做双向 对R3同样 先不改优先级 查看,知道所有给R3的路由为151,全部为OSPF。 知道了是错误的,先把3,4之间的线路断掉 接着对R3,让优先级全部回到100(displa…...
Linux网络-守护进程版字典翻译服务器
文章目录 前言一、pid_t setsid(void);二、守护进程翻译字典服务器(守护线程版)效果图 前言 根据上章所讲的后台进程组和session会话,我们知道如果可以将一个进程放入一个独立的session,可以一定程度上守护该进程。 一、pid_t se…...
Python 推导式详解:高效简洁的数据处理技巧
推导式是 Python 提供的一种简洁而强大的语法,用于创建列表、集合和字典。它可以让代码更简洁、更易读,同时提高运行效率。 基本语法 列表推导式 基本语法: [expression for item in iterable if condition]示例: # 生成平方…...
车联网安全入门——ICSim模拟器使用
文章目录 车联网安全入门——ISCim模拟器使用介绍主要特点:使用场景: 安装使用捕获can流量candumpcansnifferwiresharkSavvyCAN主要特点:使用场景: 重放can报文cansendSavvyCAN 总结 车联网安全入门——ISCim模拟器使用 …...
leetcode - 20.有效的括号(LinkedHashMap)
leetcode题目有效的括号,分类是easy,但是博主前前后后提交了几十次才通过,现在记录一下使用Java语言的写法。 题目链接: 20.有效的括号 题目描述: 给定一个只包括 (,),{,},[&…...
多维数组的动态内存分配(malloc和new)
一.区别指针类型 动态分配二维数组的内存不要赋值给行指针,而要赋值给二级指针。 二.分配动态二维数组的方法 1.使用指针数组 然后对指针数组的每一个元素分别malloc一维数组 2.直接使用malloc // 分配了一个指针数组,row为二维数组行数 int **p (i…...
71、评测OrangePi AIpro开发板和USB CAMERAOAK视频解码+推理+编码+推流测试
基本思想:csdn赞助了OrangePi AIpro开发板,花点时间简单和oak深度相机绑定测试一下,反正之前玩过atlas 200 dk A2,应该差不多,引用了之前的usb相机,方便小伙伴测试使用 第一步:系统刷机,参考官方吧,懒得刷机了,参考官方手册即可链接:https://pan.baidu.com/s/1umXM3i…...
为什么需要开局调用函数?
初始化操作:在你的应用程序启动时,可能需要执行一些初始化操作,例如设置默认值、加载配置、建立数据库连接等。开局调用函数可以帮助你集中管理这些操作,确保它们在应用程序启动时顺利执行。 统一入口:通过一个统一的…...
QT-demo:0轴分布图表
版本:5.9 第一种: 使用 PyQt5 和 Matplotlib 库 安装所需的库: pip install PyQt5 matplotlib创建和显示图表: import sys import numpy as np import matplotlib.pyplot as plt from PyQt5.QtWidgets import QApplication, QMainWindow f…...
git远程仓库限额的解决方法——大文件瘦身
Git作为世界上最优秀的分布式版本控制工具,也是优秀的文件管理工具,它赋予了项目成员对项目进行远程协同开发能力,因此受到越来越多的行业从业人员的喜爱。很多优秀的项目管理平台,比如国内的Gitee,国外的Github&#…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...




