redis锁

news2024/11/15 1:43:59

一、redis锁的实现

加锁命令:

SETNX key value:
当键不存在时,对键进行设置操作并返回成功1,否则返回失败0。
Key是锁的唯一标识,一般按业务来决定命名;
Value 往往用来比较加锁的是哪一个线程或者哪一个消息,
一般使用UUID.randomUUID().toString()方法生成。
例如:setnx(key,1)

复制

解锁命令:

DEL key
通过删除键值对释放锁,以便其他线程可以通过 SETNX 命令来获取锁。
例如:del(key)

复制

锁超时:

EXPIRE key timeout
设置 key 的超时时间,以保证即使锁没有被显式释放,
锁也可以在一定时间后自动释放,避免资源被永远锁住。
例如:expire(key,30),表示30s超时释放锁。

复制

备注:

Redis 2.6.12以上版本为set指令增加了可选参数,伪代码如下:
set(key,1,30,NX),它将加锁和超时两个动作合并到了一起,利用原子性封装了起来。

复制

二、redis锁解决的具体场景

场景1: 为什么redis锁需要设置超时?

原因分析:
1.redis与业务进程之间通常是使用网络通讯的方式进行数据加锁的,而网络通讯就存在丢包的情况。
再加上加锁和解锁是两个操作,这样就会存在锁永远不能释放的问题。
2.除此之外业务进程在加锁之后,也可能panic掉,没有办法去释放掉这个锁,导致分布式锁被永远挂住。

基于上面的两个原因:
分布式锁就需要一个超时时间来主动释放这个锁,防止分布式锁一直被挂住。

复制

redis分布式锁的解决办法,
1.通过加锁和超时两步操作来解决,不过我们最好使用set(key,1,30,NX)这种原子操作。
2.使用setnx和expire两个操作的话,因为它们不是原子性操作,也会存在上面1和2的问题,
进而导致锁被永远锁住,不过也不是没有办法,
我们可以采用lua脚本在redis上面实现的方式来保证它们的原子性。

复制

场景2: 锁超时释放了之后,加锁的业务又过来释放锁怎么办?

具体场景,进程1在超时释放了锁之后,进程2获取到了锁,后来进程1又释放锁,如此以来就有可能导致进程2没有完成就被进程1释放了锁。如下所示:

解决上面问题的关键点,在于我们在释放锁的时候,能够判断出来是不是当前加锁的进程发起的解锁操作。

一般是将进程id作为vlaue放到setnx中,在解锁之前先去判断一把这个锁是不是同一个进程的,
是就允许释放,不是就不允许解锁。

备注:这种操作其实是两步操作,判断锁,释放锁,它们并不是一个原子操作,
如此以来就存在一步操作完成,另一步没有被操作的情况。解决办法是,利用lua脚本实现锁的原子性。

复制

场景3:锁超时释放之后,会不会存在两个业务同时处理加锁的代码的情况?

这个场景与场景2是一个问题的延伸,一旦我们在设置锁的超时时间过短,就会发生这个情况。

锁在被进程2拿走之后,进程1还没有执行代码结束,
如此以来就会存在进程1和进程2同时操作那段公共代码的情况,
这样就会出问题,也显然不是我们期望的场景。

复制

对于这个场景的解决办法,往往有两个:

1.调整超时时间,让业务进程在这段时间之内一定可以执行完毕。
2.启动守护进程,在业务进程没有执行完成的时候,主动的去调节这个超时时间,
让锁的超时时间变长。

复制

场景4:锁被使用之后,其他的业务如何才能获取这个分布式锁?

这个场景,是非常基本的场景,一旦锁被进程1获取之后,在释放锁之前,进程2是怎么知道何时才能够获取到锁呢?

这个解决办法有点像操作系统的轮询和信号量两种。

1.轮询的话,就需要进程2不停的去超时加锁,直到能够加锁成功位置,
不过这种实现比较耗费服务器资源。
2.类似信号量的方法,业务进程2将加锁消息进行订阅操作,
而订阅模块会维护一个消息队列,等到锁释放之后,
便从队列中取出进程2,告知锁已经释放的通知。
进程2收到通知以后,就可以进行加锁操作了。

复制

场景5:redis是集群的话,使用redis分布式锁会不会有问题?

为了保证redis的可用性,往往redis服务器会设置主从,主从服务器中的从服务器在检测到主服务器挂掉之后,就会重新选举一个作为主服务器,而redis锁是操作在主服务器上的。

一旦,发生下面的现象:

1.主服务器刚刚被进程1加锁完成,还没有来得及同步数据到从服务器就挂掉了。
2.从服务器经过选举,选出了新的主服务器。
3.进程2在新的主服务器上加锁成功。
4.如此以来进程1和进程2都会同时操作那段公共代码,这样就会存在问题,算是加锁失败。

复制

针对这种问题,我们其实没有太好的办法,不过还好这种数据的概率比较低。

Redis 分布式锁只能作为一种缓解并发的手段,要完全解决并发问题,仍需要数据库的防并发手段配合使用。

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

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

相关文章

Linux [工具]

工具 补充yumyum的位置yum的使用yum的本质 vimvim的多模式vim多个模式的细节命令模式底行模式 vim的配置 补充 Linux系统中文件名后缀没有直接的意义 但是不代表Linux上的软件不需要后缀, 比如gcc yum yum的位置 我们在手机或者Windows上, 一般都有一个东西 应用商店. 这个东…

简要介绍 | 单目深度估计

注1:本文系“简要介绍”系列之一,仅从概念上对单目深度估计进行非常简要的介绍,不适合用于深入和详细的了解。 注2:"简要介绍"系列的所有创作均使用了AIGC工具辅助 探索视觉世界的无限可能:单目深度估计介绍…

CANopen SDO下载

文章目录 CANopen SDO 下载SDO下载协议SDO下载启动协议SDO分段下载协议参考 CANopen SDO 下载 CANopen SDO下载分为快速(expedited)和正常(normal)两种,平时我们写对象字典基本都在用SDO快速下载(适用于写…

网络安全竞赛——Windows服务漏洞扫描与利用

1.通过渗透机Kali Linux对靶机场景Windows 7进行系统服务及版本扫描渗透测试,并将该操作显示结果中3389端口对应的服务状态信息作为Flag值提交; 进入kali命令控制台中使用如下命令 Flag:open 2.在msfconsole中用search命令搜索 MS12020 RDP拒…

ETCD简介

为什么使用ETCD ETCD简介ETCD发展史ETCD架构etcd数据通道具体交互 ETCD使用场景概念词汇 ETCD简介 现代键值(Key - Value)存储系统,ZooKeeper是历史最悠久的项目,起源于Hadoop。这里ETCD与Zk对比。 ETCD相比与ZK,更加…

【力扣】3、无重复字符的最长子串

3、无重复字符的最长子串 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 //维护左指针,循环右指针 //new map是新建一个哈希表 var lengthOfLongeSubstring function (s){const map new Map();let l 0;let num 0;for(let i …

【微服务架构设计和实现】4.4 数据库和数据存储的分离和服务化

往期回顾: 第一章:【云原生概念和技术】 第二章:【容器化应用程序设计和开发】 第三章:【基于容器的部署、管理和扩展】 第四章:【4.1 微服务架构概述和设计原则】 第四章:【4.2 服务边界的定义和划分…

下载较老版本或最新版本的ARM Linux gcc 交叉编译工具链

前言 如果开发的 ARM 平台比较的多,需要多个版本的 arm gcc 交叉编译工具链,那么如何获取较新版本的 arm gcc 交叉编译工具链呢? 下载现成的 arm gcc 交叉编译工具链 速度较快的,也比较新的,就到 ARM 官方网站下载 …

突破 Python 爬虫的瓶颈:WebKit 在线模拟技术与环境搭建

部分数据来源:ChatGPT 引言 在使用 Python 进行爬虫开发的时候,很多情况下我们需要利用一些浏览器内核来模拟浏览器行为。而目前最为常用的两种浏览器内核是基于 WebKit 和基于 Chromium 的内核。那么在 Windows 10 操作系统中,我们可以使用 Anaconda 作为 Python 的发行版…

mysql的一些使用语句写法

记录一下,方便自己以后查看,以后会随时添加 1,查询重复数据 select project_id,house_location,count(*) from house_price group by house_location having count(house_location)>1; 2,删除重复的数据,并保留一条…

MySQL(六):基本的SELECT语句

基本的SELECT语句 前言一、SELECT...二、SELECT ... FROM三、列的别名四、去除重复行五、空值参与运算六、着重号七、查询常数八、显示表结构九、过滤数据 前言 本博主将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识,有兴趣的小伙伴可以关注博主&#…

串口协议说明

文章目录 关系波特率概念波特率相对误差UART误差保证 协议常见的串行接口协议之间的比较USB 转串口PL2303USB 转串口CP2102USB转232终端电阻 串口电平TTL电平485电平 帧奇偶校验 关系 两个半双工,一发一收,就是Uart 在一根线的基础上,多加一…

【Git原理与使用】

🎉实战项目:Git原理与使用 博主主页:桑榆非晚ᴷ 博主能力有限,如果有出错的地方希望大家不吝赐教 给自己打气:成功没有快车道,幸福没有高速路。所有的成功,都来自不倦地努力和奔跑&#xff0c…

人机交互学习-10 评估的基础知识

评估的基础知识 背景评估目标和原则评估目标评估的优点评估的目标 评估原则 评估范型和技术“范型”与“技术”评估范型快速评估可用性测试实地研究预测性评估评估范型比较 评估技术评估范型和技术的关系 评估方法的选择区分评估技术的因素评估技术的分类评估方法组合 评估步骤…

CTFshow-pwn入门-Test_your_nc

pwn0 靶场环境启动开,显示ssh连接。 直接打开ctfshow的pwn专用虚拟机来使用ssh连接。密码是123456。 连接之后,他会出现这样的一大堆的介绍性文字,不用管他,然他输出完就行。 中间还用各种语言说了一下“消灭人类暴政&#xff…

Python+Qt桌面端与网页端人工客服沟通工具

程序示例精选 PythonQt桌面端与网页端人工客服沟通工具 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<PythonQt桌面端与网页端人工客服沟通工具>>编写代码&#xff0c;代码整洁…

java swing 购物系统 简要文档 idea eclipse双版本

java swing 购物系统 简要文档 idea eclipse双版本 安装包等资源项目源码项目安装包部署教程 图片演示添加商品类别界面添加商品界面查询商品界面未登录主界面管理员登录界面注册会员界面购买商品界面商品类别管理界面 核心代码CustomerAddInterFrm.javaMainFrm.javaManagerLog…

单片机基于 Linux 环境下的Makefile 工程管理和工具链配置

一、开发环境 开发板&#xff1a;stm32f407 编译环境&#xff1a;18.04.6 LTS 工具链&#xff1a;gcc-arm-none-eabi, gcc-arm-none-objcopy 二、工具链下载和安装 下载地址&#xff1a;&#xff08;下载64位linux版&#xff09; https://launchpad.net/gcc-arm-embedded/downl…

从零开始Vue项目中使用MapboxGL开发三维地图教程(五)加载点、线、面图层以及三维面图层(白模)

目录 1、加载点图层2、加载线和面图层3、加载三维面图层&#xff08;白模&#xff09; 1、加载点图层 开发地图应用时&#xff0c;加载POI等点状数据&#xff0c;显示文字或者图标信息&#xff0c;mapbox-gl对应使用的是符号图层&#xff08;symbol&#xff09;&#xff0c;下面…

Modbus通信介绍 网络高级工具使用

目录 Modbus简介 ModbusTCP协议格式 》1.报文头&#xff08;共7字节&#xff09; 》2.功能码 》3.数据 练习&#xff1a;读传感器数据&#xff0c;读1个寄存器数据&#xff0c;写出主从数据收发协议。 练习&#xff1a;写出控制IO设备开关的协议数据&#xff0c;操作1个…