Redis实现分布式锁

一、使用分布式锁的背景是什么

1、如果你公司的业务,各个应用都只部署了一台机器,那么完全用不着分布式锁,直接使用Java的锁即可

2、可是当你们的业务量大,多台机器并发情况下争夺一个资源的时候,就必须要保证业务的原子性了。

举例:

例子1、超卖问题:一共100个商品待抢购,当还有最后一个库存的时候,实例1,2,3.....10都查询到还有库存,用户同时都下单成功;那么就出现了超卖问题:你一共100的库存,哪来的110个商品发货?

怎么解决呢?将100个商品写入redis中,并加上分布式锁,必须一个实例,拿到锁,并完成交易,扣除库存后,释放锁,才能让下一个实例拿到锁;这样就保证了不会超卖

例子2、定时任务问题:多台分布式应用,要执行对账,如果多台机器同时执行,就有可能产生脏数据;如果使用分布式锁,使同时只有一个应用实例去执行一个任务,这样就实现了互斥,不会导致脏数据产生

二、Redis分布式锁,是如何实现的?

Redis实现分布式锁主要利用Redis的setnx命令。setnx是SET if not exists(如果不存在,则set)的简写

获取锁:

#添加锁,lock是锁的名称,value就是值(根据业务命名) NX代表互斥,EX是设置超时时间
SET lock value NX EX 10

释放锁:

# 释放锁,删除即可
DEL key

分布式锁必须加超时时间的原因是,如果应用获取到锁后,宕机了,那么就永远释放不了锁了

三、Redisson实现分布式锁,如何控制锁的有效时长?

如果应用使用了分布式锁,但是在锁的有效时间都超过了(锁失效了),那么应用的其他实例就会拿到锁,也去执行业务代码,就有可能会导致脏数据产生

那么如何合理控制锁的有效时长呢?

1、根据业务预估

根据业务代码评估后,觉得实例拿到锁之后,多久能跑完,就给锁设值多久过期

但是这样很不准确

2、动态地给锁续期

我只要拿到锁的线程还在跑,那我就一直给锁加有效时间(超时时间)即可,每次加10秒钟,诶,非常合理

 有以下两种方式:

1、自己代码里新开一个线程,每隔10秒或者多少秒,延长一下锁的有效时间(过期时间)

或者说,在数据库标记一个标识,新开一个线程记录当前线程id + 状态,根据状态判断是否需要延期

2、使用Redisson的看门狗机制

Redisson自带有一个watch dog(看门狗机制),

如图所示,

1、实例1在获取到锁后,在加锁后,Redisson会另外开一个线程(看门狗线程),监控持有锁的线程,会不断增加持有锁的线程的持有锁的时间(超时时间,默认10秒)

看门狗线程,每次续期(release / 3)的时间,其中release是锁的默认超时时间:30s,也就是说默认10秒钟续期一次,每次重新设置为30秒过期时间

当实例1释放锁的时候,需要通知一次看门狗,不需要再做监听了,因为key已经被删除了

2、在实例2,尝试加锁的过程中,如果加锁失败,会循环,尝试获取锁;

当然实例2也不会无限循环尝试获取,一段时间没有加锁成功就会报错,这就是Redisson新增的重试机制

public void redisLock() throws InterruptedException{// 获取锁(重入锁),执行锁的名称RLok lock = redissonClient.getLock("myLockName");// 尝试获取锁,参数分别是:1、获取锁的最大等待时间(就是未获取到锁循环尝试获取的时间)// 2、锁自动释放时间(过期时间),如果你设置了这个值,那么Watch dog(看门狗)就不会生效,因为他会认为你能控制锁的超时时间,不会定时给你续期// 3、第三个参数为 前两个时间参数的单位// boolean isLock = lock.tryLock(10, 30, TimeUnit.SECONDS);boolean isLock = lock.tryLock(10, TimeUnit.SECONDS);// 判断是否获取锁成功if(isLock) {try {System.out.prientln("执行你的业务逻辑");} finally {// 释放锁lock.unlock();}}
}

所有的加锁解锁,设置过期时间,看门狗续期等,都是根据lua脚本来实现的,保证执行的原子性

四、Redisson实现的分布式锁,可以重入吗?

为什么同一个线程要多次拿到锁呢?

因为如果一个任务,根据不同的传参,可能有不同的判断,要调用不同的方法,调用不同的方法耗时可能不同,那么就可以使用重入机制,调一个方法就延长一下锁的有效时长;

所以问题的答案是:Redisson实现的分布式锁可以重入,redission中可以记录线程id,使同一线程的不同方法,都可以重复拿到锁

如图:add1方法获取锁后,Redis会使用hash结果记录锁的key,获取到锁的线程id、以及重入次数

当add1方法调用add2方法后,add2方法也可以获取到锁,这时Redis会把重入次数加一;

当add2释放锁之后,重入次数会减一

当add1释放锁之后,重入次数也会减一,当重入次数value=0时,Redis就会把这个锁删除

五、Redission可以解决Redis主从不一致的问题吗?

什么叫主从不一致的问题?

如果说,你的应用实例1在主节点写入了一个分布式锁,这时候其他实例2,3,4是拿不到分布式锁的;

而如果在你实例1还在执行的时候,Redis主节点挂了(宕机了)!这时候呢,Redis的一个从节点会自动升级为主节点,但是这个新的从节点,里面是没有这个分布式锁的,那么实例2,3,4就又可以获得一个锁,来进行代码的执行,这就有可能导致脏数据问题

所以:Redisson分布式锁,是不能解决主从一致性问题的。

但是,Redis中有另一种解决方案,叫做红锁(redlock)机制,就是把分布式锁的信息保存在X台(X = Redis节点数 / 2  + 1,即超过半数)Redis的节点上;每次加锁,都必须拿到这X台(超过半数)机器的锁,才算真正获得锁

红锁:

但是红锁,一般是不会使用的,因为这样性能太低了,如果硬是要保持数据强一致性,还可以使用zookeeper实现的分布式锁,或者其他机制

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

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

相关文章

变化检测相关论文可读list

一些用得上的: 遥感变化检测常见数据集https://github.com/rsdler/Remote-Sensing-Change-Detection-Dataset/ 代码解读:代码解读 | 极简代码遥感语义分割,结合GDAL从零实现,以U-Net和建筑物提取为例 对本list的说明:…

docker 逃逸突破边界

免责声明 本博客文章仅供教育和研究目的使用。本文中提到的所有信息和技术均基于公开来源和合法获取的知识。本文不鼓励或支持任何非法活动,包括但不限于未经授权访问计算机系统、网络或数据。 作者对于读者使用本文中的信息所导致的任何直接或间接后果不承担任何…

cv2.Sobel

1. Sobel 算子简介 Sobel 算子是一种 边缘检测算子,通过对图像做梯度计算,可以突出边缘。 Sobel X 方向卷积核: 用于计算 水平方向(x 方向) 的梯度。 2. 输入图像示例 假设我们有一个 55 的灰度图像,像素…

网络编程 day3

思维导图 以select函数模型为例 思维导图2 对应 epoll模型 应使用的函数 题目 使用epoll函数实现 两个客户端 通过服务器 实现聊天 思路 在原先代码基础上 实现 服务器 发向 客户端 使用客户端在服务器上的 套接字描述符 实现 客户端 接收 服务器…

Java 同步锁性能的最佳实践:从理论到实践的完整指南

目录 一、同步锁性能分析 (一)性能验证说明 1. 使用同步锁的代码示例 2. 不使用同步锁的代码示例 3. 结果与讨论 (二)案例初步优化分析说明 1. 使用AtomicInteger原子类尝试优化分析 2. 对AtomicInteger原子类进一步优化 …

Mac之JDK安装

Mac之JDK安装 一.安装 jdk 打开终端输入命令:java -version 查看是否已安装 JDK Oracle 官方下载地址 根据自己Mac 系统安装 查看 Mac 系统,打开中断命令,输入: uname -a Compressed Archive 是压缩文档,下载的是一个 .tar.gz 压缩包 D…

[MySQL]5-MySQL扩展(分片)

随着数据量和用户量增加,MySQL会有读写负载限制。以下是部分解决方案 目录 功能拆分 使用读池拓展读(较复杂) 排队机制 🌟分片拓展写 按业务或职责划分节点或集群 大数据集切分 分片键的选择 多个分片键 跨分片查询 资料…

芯盾时代数据安全产品体系,筑牢数据安全防线

芯盾时代数据安全治理(DSG)框架,以国家法律法规、行业监管标准、行业最佳实践为依据,从数据安全战略出发,以数据分类分级为支撑,构数据安全管理体系、数据安全技术体系、数据安全运营体系与数据安全监督评价…

腾讯大数据基于 StarRocks 的向量检索探索

作者:赵裕隆,腾讯大数据研发工程师 本文整理自腾讯大数据工程师在 StarRocks 年度峰会上的分享,深入探讨了向量检索技术的原理与应用。此功能已应用到腾讯内部多个场景,引入 StarRocks 后,业务不仅不需要维护多套数据库…

STM32 RTC 实时时钟说明

目录 背景 RTC(实时时钟)和后备寄存器 32.768HZ 如何产生1S定时 RTC配置程序 第一次上电RTC配置 第1步、启用备用寄存器外设时钟和PWR外设时钟 第2步、使能RTC和备份寄存器访问 第3步、备份寄存器初始化 第4步、开启LSE 第5步、等待LSE启动后稳定状态 第6步、配置LSE为…

android studio在gradle的build时kaptDebugKotlin这个task需要执行很久

只修改了一点java代码,kaptDebugKotlin这个任务却执行了3~5分钟。。。

机器学习(李宏毅)——self-Attention

一、前言 本文章作为学习2023年《李宏毅机器学习课程》的笔记,感谢台湾大学李宏毅教授的课程,respect!!! 二、大纲 何为self-Attention?原理剖析self-Attention VS CNN、RNN、GNN 三、何为self-Attenti…

【Java使用Geotools对shp文件进行读取,读取完成之后shp、dbf、shx文件总是被占用,无法删除,如何解决呢?】

Java使用Geotools对shp文件进行读取,读取完成之后shp、dbf、shx文件总是被占用,无法删除,如何解决呢? 问题描述原因分析与问题解决1.直接原因2.解决方案 问题描述 Java使用Geotools对shp文件进行读取,读取完成之后.sh…

lvs的DR模式

基于Linux的负载均衡集群软件 LVS 全称为Linux Virtual Server,是一款开源的四层(传输层)负载均衡软件 Nginx 支持四层和七层(应用层)负载均衡 HAProxy 和Nginx一样,也可同时支持四层和七层(应用层)负载均衡 基于Linux的高可用集群软件 Keepalived Keepalived是Linux…

基于进化式大语言模型的下一代漏洞挖掘范式:智能对抗与自适应攻防体系

摘要 本文提出了一种基于进化式大语言模型(Evolutionary LLM)的智能漏洞挖掘框架,突破了传统静态分析的局限,构建了具备对抗性思维的动态攻防体系。通过引入深度强化学习与多模态感知机制,实现了漏洞挖掘过程的自适应进化,在RCE、SQLi、XXE等关键漏洞类型的检测中达到97…

java项目之基于SSM会议管理系统的设计与实现源码(ssm+mysql)

项目简介 基于SSM会议管理系统的设计与实现实现了以下功能: 基于SSM会议管理系统的设计与实现的主要使用者分为:管理员登录后修改个人的密码。用户管理中,对公司内的用户进行管理,包括会议管理员和员工,管理部门信息…

Linux第106步_Linux内核RTC驱动实验

1、了解rtc_device结构体 1)、打开“include/linux/rtc.h” rtc_class_ops是需要用户根据所使用的RTC设备编写的,其结构体如下: struct rtc_class_ops { int (*ioctl)(struct device *, unsigned int, unsigned long);/*函数指针ioctl*/ int (*read_time)(struct device *,…

java项目之基于推荐算法的图书购物网站源码(ssm+mybatis+mysql)

风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的基于推荐算法的图书购物网站项目。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 基于推荐算法的…

【Antv G2 5.x】饼图添加点击事件,获取当前坐标数据

// 监听 tooltip:show 事件this.chart.on(tooltip:show, (event) => {this.currentShowTooltipName = event.data.items[0].name})// 监听绘图区plot的点击事件this.chart.on(interval:click, ev => {this.$emit(chartClick, this.currentShowTooltipName);})// 监听绘图…

称呼计算器:智能科技,简化您的计算生活

一款手机应用程序,安卓设备上使用。这款计算器应用以其简洁的界面、实用的功能和良好的用户体验而受到用户的喜爱。 计算器的主要特点包括: 基本计算功能:支持加、减、乘、除等基本运算。 科学计算器模式:提供更高级的数学运算功…