redis应用-分布式锁
目录
什么是分布式锁
分布式锁的基本实现
引入过期时间
引入校验id
引入lua
引入看门狗
引入redlock算法
什么是分布式锁
在一个分布式系统中,也会涉及到多个节点访问同一个公共资源的情况,此时就需要通过锁来做互斥控制,避免出现类似于"线程安全"的问题.
而Java中的synchronized这样的锁只能在当前进程中生效,在分布式这样的多个进程多个主机的场景下就无能为力了.
在分布式系统中,有很多进程(每个服务器,都是独立的进程),因此synchronized就难以对现在的分布式系统中的多个进程之间产生制约.
分布式系统中,多个进程之间的执行顺序也是不确定的,充满随机性.
此时就需要分布式锁来控制.
分布式锁本质上是使用一个公共的服务器,来记录加锁状态.这个公共的服务器可以是redis,也可以是其他组件,比如mysql等,还可以是自己写的一个服务.
分布式锁的基本实现
通过一个键值对来表示锁的状态.
考虑一个买票的场景,现在车站提供了若干车次,每个车次的票数都是固定的.现在存在多个服务器节点,都可能需要处理这个买票的逻辑:先查询指定车次的车票,如果余票>0,则设置余票值-1.
客户端1先执行查询余票,发现剩余一张,在即将执行1->0的过程之前,客户端2也执行查询余票,查询到的也是剩余一张,客户端2也会执行1->0的过程,就出现了超卖.
显然上述场景存在"线程安全"问题,会出现超卖的情况,需要用锁来控制.
如何进行加锁?
在上述架构中引入一个redis,作为分布式锁的管理器.
此时,如果买票服务器1尝试买票,就需要先访问redis,在redis上设置一个键值对,比如key为车次,value随便设个值,比如1.
如果这个操作设置成功,就视为当前没有节点对该车次加锁,就可以进行数据库的读写操作了,操作完之后,再把redis上刚才的键值对删除掉.
如果在买票服务器1操作数据库的过程中,买票服务器2也想买票,也会尝试给redis上写一个键值对,key同样是车次,但是此时设置的时候发现该车次的key已经存在了,则认为已经有其他服务器正在持有锁,此时服务器2就需要等待或者暂时放弃了.
redis中提供了setnx操作,正好适合上述场景,key不存在则设置,存在则设置失败.
引入过期时间
当服务器1加锁之后,开始处理买票的过程,如果在此过程中服务器1意外宕机,就会导致后续的解锁操作无法执行,就可能引起其他服务器始终无法获取到锁的情况.
为了解决这个问题,就可以在设置key的同时引入过期时间,即这个锁最多持有多久,就应该被释放.
使用 set ex nx的方式,在设置锁的同时把过期时间也设置进去.此处只能使用一条命令来完成,不能拆分成setnx和expire.
引入校验id
所谓的加锁就是给redis上设置一个key-value,所谓的解锁就是给redis上这个key-value删除掉.
那么也就有可能出现,服务器1执行了加锁,服务器2执行了解锁.
当然服务器2不会进行这样的恶意删除,不过不能保证因为一些bug导致服务器2把锁误删掉.
为了解决上述问题,我们可以引入一个校验id.
比如可以把设置的键值对的值,不在简单的设置为一个而是设置成服务器的编号,形如"001:"服务器1".
这样就可以在删除key的时候,先校验当前删除key的服务器是否是当初加锁的服务器,如果是才能真正的删除,不是则不能删除.
但是很明显,解锁逻辑中的get和del两部操作并非是原子的!!!
引入lua
为了使解锁操作是原子的,可以使用redis的lua脚本功能.
上述情况来说,看起来重复执行DEL好像问题不大?实则不然!!
主要是引入一个新的服务器,执行加锁就可能出现问题了. .
在线程A执行完DEL之后,B执行DEL之前
服务器2的线程C正好要执行加锁(set),此时由于A已经把锁释放了,C的加锁是能够成功的!!
但是紧接着,线程B DEL就到来了.就把刚刚服务器2的加锁操作给解锁了.
服务器1和服务器2进行加锁, key是资源的编号(比如车次),服务器的id是value.
新加的锁被删除了.归根结底是因为get和del不是原子产生的问题.
使用redis的事务可以解决上述问题,但是实践中往往使用更好的方案,lua脚本.
lua是一个变成语言,作为redis内嵌的脚本,lua语言特别轻量.
使⽤Lua脚本完成上述解锁功能.
引入看门狗
如果要在加锁的时候,给key设定过期时间.
过期时间设置多少合适呢?
如果设置过短,那么可能业务逻辑没有执行完,锁就被释放了.
如果设置的太长,就会导致锁释放不及时的问题.
更好的方式是动态续约.往往需要服务器这边有一个专门的线程,负责续约,把这个负责的线程就叫做看门狗(watch dog).
初始情况下,设置一个过期的时间(比如设置1s),就提前在还剩比如300ms的时候,如果当前任务还没执行完,就把过期时间在续上1s,等到时间又快到了,任务还没执行完,就在续.
如果服务器,中途崩溃了,自然就没有线程负责续约了,此时,锁也能在较短的时间内被自动释放!!!
引入redlock算法

相关文章:

redis应用-分布式锁
目录 什么是分布式锁 分布式锁的基本实现 引入过期时间 引入校验id 引入lua 引入看门狗 引入redlock算法 什么是分布式锁 在一个分布式系统中,也会涉及到多个节点访问同一个公共资源的情况,此时就需要通过锁来做互斥控制,避免出现类似于"线程安全"的问题. 而…...
51单片机程序
利用动态扫描和定时器1在数码管上显示出从765432开始以1/10秒的速度往下递减直至765398并保持显示此数,与此同时利用定时器O以500MS速度进行流水灯从土至下移动,当数码管上数减到停止时,实验板上流水灯也停止然后全部开始闪烁,3秒后ÿ…...

Android 分享小结
关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、商业变现、人工智能等,希望大家多多支持。 目录 一、导读二、微信 分享 三、 QQ 、QQ空间(Qz…...

Ubunutu18.04 ROS melodic 无人机 XTDrone PX4 仿真平台配置
一、依赖安装 sudo apt install ninja-build exiftool ninja-build protobuf-compiler libeigen3-dev genromfs xmlstarlet libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev python-pip python3-pip gawk pip2 install pandas jinja2 pyserial cerberus pyulog0.7.0 n…...

JVM 命令行监控及诊断工具
面试题 你使用过Java虚拟机性能监控和故障处理工具吗?(美图) 怎么打出线程栈信息。(字节跳动) JVM诊断调优工具用过哪些? (京东) 怎么获取 Java 程序使用的内存?堆使用…...

飞天使-linux操作的一些技巧与知识点2
TCP 的三次握手 第一次,客户端与服务端建立链接,需要发送请求连接的消息 第二次,服务端接口到数据后,返回一个确认的操作*(至此客户端和服务端链路建立成功) 第三次,服务端还需要发送要与客户端…...

Android : 篮球记分器app _简单应用
示例图: 1.导包 在build.gradle 中 加入 // 使用androidx版本库implementation androidx.lifecycle:lifecycle-extensions:2.1.0-alpha03 2. 开启dataBinding android{...// 步骤1.开启data bindingdataBinding {enabled true}...} 3.写个类继承 ViewModel pac…...

音视频之旅 - 基础知识
图像基础知识 像素 像素是图像的基本单元,一个个像素就组成了图像。你可以认为像素就是图像中的一个点。在下面这张图中,你可以看到一个个方块,这些方块就是像素 分辨率 图像(或视频)的分辨率是指图像的大小或尺寸。…...

分类预测 | SSA-HKELM-Adaboost麻雀算法优化混合核极限学习机的数据分类预测
分类预测 | SSA-HKELM-Adaboost麻雀算法优化混合核极限学习机的数据分类预测 目录 分类预测 | SSA-HKELM-Adaboost麻雀算法优化混合核极限学习机的数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.SSA-HKELM-Adaboost麻雀算法优化混合核极限学习机的数据分类…...

如何使用 Zotero 导出所选条目的 PDF 文件
如何使用 Zotero 导出所选条目的 PDF 文件 Zotero 是一款强大的参考文献管理工具,但它并不直接提供将整个文件夹导出为 PDF 的选项。不过,您可以使用以下步骤来导出您所选的 Zotero 条目中的 PDF 文件,无需额外的插件。 选择所需的 Zotero 条…...

minio的k8s的单机部署
minio的k8s的单机部署 apiVersion: apps/v1 kind: Deployment metadata:name: minionamespace: itshare spec:replicas: 1selector:matchLabels:app: miniotemplate:metadata:labels:app: miniospec:containers:- name: minioimage: minio/minio:RELEASE.2022-10-15T19-57-03Z…...
Git 更改remote repo 地址
Git 更改remote repo 地址 我们想更换远程 repo 地址, 因为我们仓库更换了名称. git remote rename origin 查看现在的 romote 地址 # 查看 remote 地址 git remote -v origin gitgitee.com:changyubiao/attrdict.git (fetch) origin gitgitee.com:changyubiao/attrdict.gi…...

24、文件上传漏洞——Apache文件解析漏洞
文章目录 一、环境简介一、Apache与php三种结合方法二、Apache解析文件的方法三、Apache解析php的方法四、漏洞原理五、修复方法 一、环境简介 Apache文件解析漏洞与用户配置有密切关系。严格来说,属于用户配置问题,这里使用ubantu的docker来复现漏洞&am…...

使用Go快速开发TCP公共服务
使用Go快速开发TCP公共服务 文章目录 使用Go快速开发TCP公共服务一、前言二、实现思路三、源码四、测试使用五、最后 一、前言 之前使用的公共TCP服务无法使用了,想了一下整个实现原理不是很复杂,就利用Go快速开发了一个,利用公网服务器可以…...

QEMU环境调试方法
目录 1.如何查看makefile构建过程执行的命令? 2.如何使用GCC生成C程序的宏展开文件? 3.如何在qemu中执行特定的可执行程序? 4.如何在qemu中直接运行可执行程序? 5.如何在qemu中调试某个可执行程序? 本文从调试的角…...

京东数据运营(京东API接口):10月投影仪店铺数据分析
鲸参谋监测的京东平台10月份投影仪市场销售数据已出炉! 10月份,环同比来看,投影仪市场销售均上涨。鲸参谋数据显示,今年10月,京东平台投影仪的销量为16万,环比增长约22%,同比增长约8%࿱…...

Aloha 机械臂的学习记录2——AWE:AWE + ACT
继续下一个阶段: Train policy python act/imitate_episodes.py \ --task_name [TASK] \ --ckpt_dir data/outputs/act_ckpt/[TASK]_waypoint \ --policy_class ACT --kl_weight 10 --chunk_size 50 --hidden_dim 512 --batch_size 8 --dim_feedforward 3200 \ --n…...

Spring Boot 项目的创建、配置文件、日志
文章目录 Spring Boot 优点创建 Spring Boot 项目创建项目认识目录网页创建(了解) 约定大于配置Spring Boot 配置文件配置文件格式读取配置项properties 配置文件yml 配置文件基本语法进阶语法配置对象配置集合yml 设置不同环境的配置文件 Spring Boot 日…...
MySQL:drop、delete与truncate区别
一、用法不同 1、drop(丢弃数据): drop table 表名 ,直接将表都删除掉,在删除表的时候使用。 2、truncate (清空数据) : truncate table 表名 ,只删除表中的数据,再插入数据的时候自增长 id 又从 1 开始,在清空表中数…...

2024年顶级的9个 Android 数据恢复工具(免费和付费)
不同的事情可能会损坏您的Android手机并导致您丢失数据。但大多数时候,您可以使用取证工具恢复部分或全部文件。 问题可能来自手机的物理损坏、磁盘的逻辑故障、完整的系统擦除,或者只是简单的粗心大意。 但是,无论数据丢失的原因是什么&am…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...

376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...