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;



    @Bean
    public RedissonClient redissonClient(){
        Config config = new Config();
        //单机模式  依次设置redis地址和密码
        config.useSingleServer().
                setAddress("redis://" + host + ":" + port).
                setPassword(redisPassword);
        return Redisson.create(config);
    }
}

3.yml配置

redis:
  database: 0
  host: localhost
  lettuce:
      pool:
        max-active: 8   #最大连接数据库连接数,设 0 为没有限制
        max-idle: 8     #最大等待连接中的数量,设 0 为没有限制
        max-wait: -1ms  #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
        min-idle: 0     #最小等待连接中的数量,设 0 为没有限制
      shutdown-timeout: 100ms
    password: 123456
    port: 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 秒续到30s
    lock.lock();

    // 尝试拿锁10s后停止重试,返回false
    // 具有Watch Dog 自动延期机制 默认续30s
    boolean 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对应的锁相应的也就自动释放了

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构与集合源码

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 本…

java调用c函数

一、关于JNI JNI是Java Native Interface的缩写&#xff0c;JNI是JAVA平台专门用于和本地C代码进行相互操作的API&#xff0c;称为JAVA本地接口。 二、JNI开发流程 1.在JAVA中先声明一个native方法。2.通过javac -h或javah -jni命令导出JNI使用的C头头文件。3.使用C实现本地方…

跨国企业扎根中国市场,应该选择什么样的云服务?

众所周知&#xff0c;伴随着中国经济的高速发展&#xff0c;越来越多的跨国企业都将目光瞄向了中国市场。 然而&#xff0c;要想扎根中国市场&#xff0c;开展本地业务创新&#xff0c;什么样的云服务商才是这些跨国企业的最佳选择&#xff1f; 跨国企业转型创新的三大趋势 面对…

鸿蒙应用开发初尝试《创建项目》,之前那篇hello world作废

经过几年的迅速发展&#xff0c;鸿蒙抛弃了JAVA写应用的方式&#xff0c;几年前了解的鸿蒙显然就gg了。 这几年鸿蒙发布了方舟&#xff08;ArkUI Arkts&#xff09;&#xff0c;将TypeScript作为了推荐开发语言&#xff0c;你依然可以用FAJS,但华为推荐用StageArkTs!!!那么你还…

如何在工作外发展副业?主业和副业该如何权衡

有一句话说得好&#xff0c;不要把所有的鸡蛋放在一个篮子里。在面对繁忙的工作生活之外&#xff0c;想要拥有额外的收入来源那就是做一份不影响主业的副业。而副业的发展&#xff0c;不仅能够增加收入&#xff0c;更可以拓展个人的技能和兴趣。 主业跟副业该如何权衡呢&#x…

UI原型图

最近没啥项目&#xff0c;闲来无事&#xff0c;研究了一下原型图&#xff0c;万一以后年龄大了&#xff0c;代码敲不动还可以画画原型图&#xff0c;嘿嘿嘿 今天研究了两款画原型图的工具&#xff0c;即时设计-即时设计 - 可实时协作的专业 UI 设计工具 MODAO-墨刀 两款工具…

WordPress网站迁移实战经验

前几日,网站服务器到期,换了服务商,就把我的WordPress的网站迁移到本地电脑了。方便以后文章迁移。 本次迁移网站主要经历以下几个步骤。 1.域名转出。 2.备份数据库及网站文件下载。 3.重新搭建WordPress网站。 4.网站文件及数据库导入。 下面详细介绍下每个步骤的操作…

Gooxi亮相2023世界互联网大会 展现AI创新实力

■■ 11月7日&#xff0c;2023年世界互联网大会在中国乌镇正式拉开序幕&#xff0c;作为世界互联网一年一度的盛大集会&#xff0c;此次大会以“建设包容、普惠、有韧性的数字世界——携手构建网络空间命运共同体”为主题&#xff0c;涵盖5G与6G、IPv6、人工智能、大数据、网络…

【Linux】C文件系统详解(一)——C文件操作

文章目录 文件操作总结预备知识结论: C文件操作回顾语言方案w写入方式a写入方式r只读方式 系统方案但是这个**没有设置权限**,需要这样改: 文件操作总结 1.文件描述符,重定向,缓冲区,语言和系统关于文件的不同的视角的理解 – 都是要让我们深刻理解文件 2.文件系统 3.动静态库 …

【腾讯云云上实验室-向量数据库】TAI时代的数据枢纽-向量数据库 VectorDB

一、向量数据库的发展历程和时代机遇 回顾向量数据库的发展历程&#xff1a; 2012年开始&#xff0c;深度神经网络的发展催生了向量数据库的发展&#xff1b;2015年至2016年&#xff0c;Google和微软发布了标志性的论文&#xff1b;2017年&#xff0c;Facebook开源了Faiss框架…

牛客——OR36 链表的回文结构(C语言,配图,快慢指针)

本题是没有对C的支持的&#xff0c;但因为Cpp支持C&#xff0c;所以这里就用C写了&#xff0c;可以面向更多用户 链表的回文结构_牛客题霸_牛客网 (nowcoder.com) 思路一&#xff1a;链表翻转 简单的想想整形我们怎么比较&#xff0c;就是将整形A 依次取尾&#xff0c;放到整形…

html-网站菜单-点击显示导航栏

一、效果图 1.点击显示菜单栏&#xff0c;点击x号关闭&#xff1b; 2.点击一级菜单&#xff0c;展开显示二级&#xff0c;并且加号变为减号&#xff1b; 3.点击其他一级导航&#xff0c;自动收起展开的导航。 二、代码实现 <!DOCTYPE html> <html><head>&…

AE(2)_tuning时AE的一些策略

1、设置帧率&#xff1a; 修改帧率可以通过修改V_Blank 或者frame length。配置在寄存器中生效。 一帧图像的曝光时间 帧长 * 一行时间。提高帧长&#xff0c;1帧图像的曝光时间就变大了&#xff0c;单位时间内可曝光的帧数就少了&#xff0c;也就是帧率就下降了。这就是项目…

贪吃蛇游戏

package com.snake.controller;import javax.swing.JFrame; import javax.swing.JOptionPane;import com.snake.view.SnakeJPanel;public class SnakeStart {public static void main(String[] args) {int speed 0;String showInputDialog null;//初始化时间//得到速度while(…

2023年11月11日~11月17日周报(基于matlab生成模拟数据、批量修改文件名、重写dataset)

目录 一、前言 二、基于matlab生成模拟数据 二、批量修改文件名 三、代码调试 四、重写dataset 一、前言 上周完成了FCNVMB的训练与测试&#xff0c;但是由于数据量较少&#xff0c;训练效果不明显。工作站运行forward.py代码生成模拟数据的时候出现错误&#xff0c;未解决…

二次元商业计划书PPT模版

二次元商业计划书PPT模版 共&#xff1a;9页 PPT模版&#xff1a; 百度网盘 请输入提取码&#xff1a;ax48

opencv(3):控制鼠标,创建 tackbar控件

文章目录 控制鼠标相关APIsetMouseCallbackcallback TrackBar 控件cv2.createTrackbarcv2.getTrackbarPos&#xff1a; 控制鼠标相关API setMouseCallback(winname, callback, userdata)callback(event, x, y, flags, userdata) setMouseCallback 在 OpenCV 中&#xff0c;s…

深度学习中文汉字识别 计算机竞赛

文章目录 0 前言1 数据集合2 网络构建3 模型训练4 模型性能评估5 文字预测6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习中文汉字识别 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xf…

TSINGSEE青犀视频平台EasyCVR如何搭建自然保护区视频监控系统

随着经济的发展与城市化进程&#xff0c;很多国家自然保护区不断被破坏&#xff0c;为了对国家自然保护区进行全面管理&#xff0c;加大保护区的防护管理力度&#xff0c;人工管理工作量十分繁重&#xff0c;并会存在一些漏洞。因此在国家自然保护区建立一套完整的视频监控系统…