springboot引入redisson分布式锁及原理

1.引入依赖

<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.13.6</version>
</dependency>

2.配置类创建bean

/*** @author qujingye* @Classname RedissonConfig* @Description TODO* @Date 2023/11/16 16:27*/
@Configuration
public class RedissonConfig {@Value("${spring.redis.host}")private String host;@Value("${spring.redis.port}")private String port;@Value("${spring.redis.password}")private String redisPassword;@Beanpublic RedissonClient redissonClient(){Config config = new Config();//单机模式  依次设置redis地址和密码config.useSingleServer().setAddress("redis://" + host + ":" + port).setPassword(redisPassword);return Redisson.create(config);}
}

3.yml配置

redis:database: 0host: localhostlettuce:pool:max-active: 8   #最大连接数据库连接数,设 0 为没有限制max-idle: 8     #最大等待连接中的数量,设 0 为没有限制max-wait: -1ms  #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。min-idle: 0     #最小等待连接中的数量,设 0 为没有限制shutdown-timeout: 100mspassword: 123456port: 6379

4.使用

@Resource
private RedissonClient redissonClient;// 创建锁对象
RLock redisLock = redissonClient.getLock("lock:xxxxx");
// 尝试获取锁
boolean isLock = redisLock.tryLock();
// 判断
if (!isLock) {// 获取锁失败,直接返回失败throw new CommonException(-1, "监测到文件" + originalFilename + ",正在导入请稍后在试!");
}
@Resource
private RedissonClient redissonClient;
@Test
void testRedisson() throws InterruptedException {// 获取锁(可重入),指定锁的名称RLock lock = redissonClient.getLock("anyLock"); // 尝试获取锁,参数分别是:获取锁的最大等待时间(期间会重试),锁自动释放时间,时间单位boolean isLock = lock.tryLock(1, 10, TimeUnit.SECONDS);// 判断释放获取成功if(isLock){try {System.out.println("执行业务");}finally {// 释放锁lock.unlock();}}
}

5.api方法简介

 //1. 普通的可重入锁RLock lock = redissonClient.getLock("generalLock");// 拿锁失败时会不停的重试// 具有Watch Dog 自动延期机制 默认续30s 每隔30/3=10 秒续到30slock.lock();// 尝试拿锁10s后停止重试,返回false// 具有Watch Dog 自动延期机制 默认续30sboolean res1 = lock.tryLock(10, TimeUnit.SECONDS);// 拿锁失败时会不停的重试// 没有Watch Dog ,10s后自动释放lock.lock(10, TimeUnit.SECONDS);// 尝试拿锁100s后停止重试,返回false// 没有Watch Dog ,10s后自动释放boolean res2 = lock.tryLock(100, 10, TimeUnit.SECONDS);//2. 公平锁 保证 Redisson 客户端线程将以其请求的顺序获得锁RLock fairLock = redissonClient.getFairLock("fairLock");

6.redisson原理

首先分布式锁要考虑
分布式锁需要考虑
互斥性 setnx
防死锁(过期,锁续命)
可重复性
高性能
而Redisson满足 实现了 锁续命 锁错删 可重入
[图片]

"if (redis.call('exists', KEYS[1]) == 0) then " +"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +"redis.call('pexpire', KEYS[1], ARGV[1]); " +"return nil; " +"end; " +"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +"redis.call('pexpire', KEYS[1], ARGV[1]); " +"return nil; " +"end; " +"return redis.call('pttl', KEYS[1]);",

客户端线程在底层是如何实现加锁的:
第一步,redisson.getLock(“mylock”);可以获得一个 Redisson 的分布式锁对象,可以使用该对象进行加锁、释放锁、判断锁状态等操作。
第二步加锁,加锁的底层逻辑是通过lua脚本实现的,如果客户端线程第一次去加锁的话,
执行 ‘hincrby’ 会在key对应的hash数据结构当中,添加线程标识。HashKey 是UUID:TreadID value

  1. 来指定该线程当前对这个key已经加锁一次了,并且设置锁的过期时间为30秒
  2. 客户端线程是如何维持加锁的,当加锁成功后,此时会对加锁的结果设置一个监听器,如果监听到加锁成功了,也就是返回的结果时null,此时就会在后台通过watchdog 看门狗机制,
    启动一个后台的定时任务,每隔10秒执行一次,检查当前key依旧存在,就会重置key的存活时间为30秒,维持加锁,底层就是通过后台这样一个,线程定时刷新存活时间维系的(renewExpiration自己掉自己)
  3. 相同的客户端线程是如何实现可重入加锁的
    第一次加锁时 会往key对应的hash数据结构中 设置 UUID:ThreadID 1 表示当前线程对key 加锁一次
    如果相同线程再来对这个key加锁,只需要将UUID:ThreadID 持有锁的次数加1 即可 就为
    UUID:ThreadID 2 了,redisson底层就是通过这样的数据结构 来表示重入锁的
  4. 其他线程加锁失败时,底层是如何实现阻塞的
    通过key对应的hash结构当中的UUID:ThreadID 判断是否为当前线程id 如果不是则线程加锁失败
    如果没有获取锁的超时时间 此时就会进入一个 while 的死循环中 一直尝试加锁 直到加锁成功才会返回
  5. 客户端宕机了 锁如何释放的
    客户端宕机后 相应的watchdog 后台定时任务 当然已经没了 此时就无法对key 进行定时续期 那么当指定存活时间过后 key就会自动失效 锁就当然自动释放了
  6. 客户端如何主动释放持有的锁
"if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then " +"return nil;" +"end; " +"local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); " +"if (counter > 0) then " +"redis.call('pexpire', KEYS[1], ARGV[2]); " +"return 0; " +"else " +"redis.call('del', KEYS[1]); " +"redis.call('publish', KEYS[2], ARGV[1]); " +"return 1; " +"end; " +"return nil;",

客户端主动释放底层,也是通过执行lua脚本的方式来实现的
如果判断当前释放的key存在,并且在key的hash结构当中,存在当前线程的加锁信息,那么此时就会减扣当前线程,对这个key的重入锁次数,减扣线程的重入锁次数之后,如果当前线程在这个key的重入次数为0,此时就会直接释放锁,如果当前线程,在这个key中重入锁次数依然大于0。此时就直接重置一下,key的续期时间为30秒
7. 客户端尝试获取锁超时时间的机制底层是如何实现的

boolean isLock2 = redisLock.tryLock(1,TimeUnit.MINUTES);

如果在加锁时就指定 尝试获取锁的超时时间 如果获取锁失败 此时就不会永无止境的在while循环里面一直等待 ,而是根据你指定的锁超时时间,在这段时间范围获取不到锁,那么就会标记为获取锁失败,直接返回false
8. 客户端锁超时自动释放锁机制底层是怎么实现的

redisLock.lock(1, TimeUnit.MINUTES);

如果在加锁的时候指定了锁的超时时间,那么就算你获取锁成功了,也不会开启watch dog的定时任务,此时就将当前持有的这把锁的过期时间,设置为你指定的超时时间,那么你指定的时间到了之后,key失效被删除了,key对应的锁相应的也就自动释放了

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

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

相关文章

HDFS入门--学习笔记

1&#xff0c;大数据介绍 定义 数据指的是&#xff1a;一种可以被鉴别的、对客观事件进行记录的符号&#xff0c;除了可以是最简单的 数字外&#xff0c;也可以是各类符号、文字、图像、声音等。 通俗地说&#xff0c;数据就是对人类的行为及发生事件的一种记录。 存在的价值…

2023超详细的软件测试八股文(入门篇)

今天给大家分享软件测试面试题入门篇&#xff0c;看看大家能答对几题 一、请你说一说测试用例的边界 参考回答&#xff1a; 边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法。通常边界值分析法是作为对等价类划分法的补充&#xff0c;这种情况下&#xff0…

本地私域线上线下 线上和线下的小程序

私域商城是一种新型的零售模式&#xff0c;它将传统的线下实体店与线上渠道相结合&#xff0c;通过会员、营销、效率等方式&#xff0c;为消费者提供更加便利和高效的购物体验。私域商城的发展趋势表明&#xff0c;它将成为未来零售业的重要模式&#xff0c;引领零售业的创新和…

【开源】基于Vue.js的音乐偏好度推荐系统的设计和实现

项目编号&#xff1a; S 012 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S012&#xff0c;文末获取源码。} 项目编号&#xff1a;S012&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、系统设计2.1 功能模块设计2.1.1 音乐档案模块2.1…

【数据库】你听说过矢量数据库吗?

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️其他领域】 文章目录 前言什么是向量/矢量数据库嵌入模型使用向量数据库的优势与传统数据库的对比其他方面 AWS 如何支持您的矢量数据库需求&#xff1f;Amazon OpenSearch ServiceAmazon Aurora Pos…

Python loglog()函数

常用坐标下的图像显示 import matplotlib.pyplot as plt import numpy as np import mathplt.figure() x_input np.linspace(1, 10, 50) y_input x_input**2plt.plot(x_input, y_input,r-,linewidth2) plt.show()在loglog函数尺度下的曲线 plt.loglog(x_input, y_input,r-,…

机器人走迷宫问题

题目 1.房间有XY的方格组成&#xff0c;例如下图为64的大小。每一个方格以坐标(x,y) 描述。 2.机器人固定从方格(0, 0)出发&#xff0c;只能向东或者向北前进&#xff0c;出口固定为房间的最东北角&#xff0c;如下图的 方格(5,3)。用例保证机器人可以从入口走到出口。 3.房间…

[JDK工具-2] javap 类文件解析工具-帮助理解class文件,了解Java编译器机制

文章目录 1. javap -version 版本信息2. javap -verbose 输出附加信息3. javap -l 显示行号和局部变量列表4. javap -c 对代码进行反汇编&#xff08;或叫反编译生成汇编代码&#xff0c;一般说反编译是生成java代码&#xff09;&#xff0c;分解方法代码&#xff0c;也就是显示…

想要成为CSS大师?这些技巧是你必须知道的!

前言 CSS 是网页设计中不可或缺的一部分&#xff0c;掌握一些实用的 CSS 技巧&#xff0c;可以让你在设计中展现出更多的创意和个性。本文将介绍一些 CSS 技巧&#xff0c;帮助你提升自己的技能&#xff0c;成为一个真正的 CSS 大师。 1. 改变 input 自动填充的背景颜色 这段 …

高精度算法【Java】(待更新中~)

高进度加法 在Java中可以使用BigInteger进行高精度计算&#xff0c;除此也可以仿照竖式相加的计算原理进行计算。 BigInteger 提供所有 Java 的基本整数操作符的对应物&#xff0c;并提供 java.lang.Math 的所有相关方法。另外&#xff0c;BigInteger 还提供以下运算&#xff1…

网上被吹爆的Spring Event事件订阅有缺陷,不要用

Spring Event事件订阅框架&#xff0c;被网上一些人快吹上天了&#xff0c;然而我们在新项目中引入后发现&#xff0c;这个框架缺陷很多&#xff0c;玩玩可以&#xff0c;千万不要再公司项目中使用。还不如自己手写一个监听者设计模式&#xff0c;那样更稳定、可靠。 之前我已…

ARM CoreLink CCN 互连总线介绍

NIC NOC CCI CMN CNN NI cmn-700 nic-700 ni-700 MLGB这都是啥玩意? 后期博文或视频将会更新这一系列。今天先温习一下CNN的概念,这是来自2014年的文章,然后稍微整理总结一番。 以下是正文… 现代主流和优质 ARM 片上系统 (SoC) 产品使用 CoreLink 缓存一致性网络 (CCN) 504…

SpringBoot-过滤器Filter+JWT令牌实现登录验证

登录校验-Filter 分析 过滤器Filter的快速入门以及使用细节我们已经介绍完了&#xff0c;接下来最后一步&#xff0c;我们需要使用过滤器Filter来完成案例当中的登录校验功能。 我们先来回顾下前面分析过的登录校验的基本流程&#xff1a; 要进入到后台管理系统&#xff0c;我…

IDEA运行thymeleaf的html文件打开端口为63342且连不上数据库

这边贴apple.html代码 <!DOCTYPE html> <html xmlns:th"http://www.thymeleaf.org"> <head><meta charset"UTF-8"><title>User List</title> </head> <body> <h1>User List</h1> <table&…

elementui表格自定义指令控制显示哪些列可以拖动

Vue.directive(tableBorder, function (el, {value}) {// value允许传字符串数字和数组el.classList.add(z_table_hasBorder)let hasStyle el.querySelector(style)if(hasStyle){hasStyle.remove()}let style document.createElement(style)let str .z_table_hasBorder .el…

【数据结构与算法】Kadane‘s算法(动态规划、最大子数组和)

文章目录 一、算法原理二、例题2.1 最大子数组和2.2 环形子数组的最大和 一、算法原理 Kadanes算法是一种用于解决最大子数组和问题的动态规划算法。这类问题的目标是在给定整数数组中找到一个连续的子数组&#xff0c;使其元素之和最大&#xff08;数组含有负数&#xff09;。…

IObit Unlocker丨解除占用程序软件

更多内容请收藏&#xff1a;https://rwx.tza-3.xyz 官网&#xff1a;IObit Unlocker “永远不用担心电脑上无法删除的文件。” 界面简单&#xff0c;支持简体中文&#xff0c;一看就会&#xff0c;只需要把无法删除/移动的文件或整个U盘拖到框里就行。 解锁率很高&#xff0c;…

elasticsearch 概述

初识elasticsearch 了解ES elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎&#xff0c;具备非常多强大功能&#xff0c;可以帮助我们从海量数据中快速找到需要的内容 例如&#xff1a; 在GitHub搜索代码 在电商网站搜索商品 ELK技术栈 elasticsearc…

我叫:插入排序【JAVA】

1.自我介绍 插入式排序属于内部排序法,是对于欲排序的元素以插入的方式找寻该元素的适当位置&#xff0c;以达到排序的目的。 2.继承我的思想 插入排序(Insertion Sorting)的基本思想是:把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包…

设计模式—结构型模式之外观模式(门面模式)

设计模式—结构型模式之外观模式&#xff08;门面模式&#xff09; 外观&#xff08;Facade&#xff09;模式又叫作门面模式&#xff0c;是一种通过为多个复杂的子系统提供一个一致的接口&#xff0c;而使这些子系统更加容易被访问的模式。 例子 我们的电脑会有很多 组件&am…