Redisson实现分布式锁示例
一、引入依赖
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.16.0</version></dependency>
二、配置类
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;/*** @Author ZGM* @DateTime 2023/8/15* @description*/
@Configuration
public class RedissonConfig {@Beanpublic RedissonClient redissonClient(){// 配置,Config config = new Config();//单例模式config.useSingleServer().setAddress("redis://127.0.0.1:6379");// .setPassword("123456");//修改看门狗的默认时间30s到60s//config.setLockWatchdogTimeout(60000);// 创建RedissonClient对象return Redisson.create(config);}//这个只针对转化为string类型@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate();template.setConnectionFactory(redisConnectionFactory);//默认是JDK序列化 发现key和value前面都多了一串特殊字符StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();template.setKeySerializer(stringRedisSerializer);template.setValueSerializer(stringRedisSerializer);return template;}
}
三、实现类
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;/*** @Author ZGM* @DateTime 2023/8/15* @description*/
@Service
@Slf4j
public class UserService {@Autowiredprivate RedissonClient redissonClient;@AutowiredRedisTemplate<String, Object> redisTemplate;public void test1() throws InterruptedException {//定义一个keyString key = UUID.randomUUID().toString();// 占锁 没有拿到锁的会自动阻塞// watchDog 机制 : 锁自动加了默认30秒过期// 如果业务代码耗时长,锁也会自动续期RLock lock = redissonClient.getLock(key);//只有lock()和tryLock(5000, TimeUnit.MILLISECONDS)会触发看门狗机制Boolean isLocked = lock.tryLock(5000, TimeUnit.MILLISECONDS);if(!isLocked) {log.info("获取锁失败");}long a = System.currentTimeMillis();try {Thread.sleep(60000);} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}long b = System.currentTimeMillis();System.out.println(b-a);}}
四、测试结果
可以下载redis desktop manager软件来查看redis里面存放的东西
红色框内的TTL值就是过期时间,默认-1,表示永不过期,指定过期时间后就变成你指定的值了。
上面的方法,我们让线程睡眠60S,代表我们的业务执行时间,在调用这个方法时,我们可以在
redis desktop manager软件上实时查看锁的过期时间,第一次过期时间为30S,10S后刷新过期时间为30S,也就是说,它每隔10S会检验这个锁是否释放,没有的话,会一直给你刷新锁的持有时间变为30S,直到任务完成。
五、看门狗机制
上面所说的自动刷新锁的持有时间,就是通过这个看门狗机制来实现的。它默认的锁的持有时间是30S,每隔30/3也就是10S会刷新锁的持有时间,我们也可以通过redisson的Config 类的config.setLockWatchdogTimeout(60000)来修改过期时间。实际上锁的持有时间就是lockWatchdogTimeout的值,只不过默认设置的30S而已,同样的,锁的刷新时间也是每隔lockWatchdogTimeout/3秒执行一次,如果设置的时间为60S,就是锁的过期时间为60S,每隔20S执行一次。
所谓的自动刷新,其实是在获取锁的时候,开了一个线程来监控这个锁,我们先按照默认的30S过期时间来计算,假设当前业务的执行时间在10S之内,在第10S时此线程监控到该锁已被正常释放,则不会刷新锁的过期时间,反之,在第10S时此线程监控到该锁仍被此线程持有,那也就是业务还未执行完,它就会帮你刷新过期时间。即使redis的服务器宕机了,也不会出现死锁,因为当它监控到异常时,也不会刷新过期时间,当redis的服务器恢复时,自动就把它删除了。
六、注意
注意:只有只有lock()和tryLock(waitTime, TimeUnit.MILLISECONDS)会触发看门狗机制,在这两个方法里我们都没有指定releaseTime,它默认值就是-1,然后才能自动触发看门狗机制,或者我们在调用获取锁的方法时直接指定releaseTime为-1,这样也可以触发看门狗机制,一定要注意这一点。
lock()会一直尝试获取锁,知道成功
tryLock(long time, TimeUnit unit),同样会一直尝试获取锁,但它有等待时间,超过这个时间就直接返回false,不在继续调用,我比较喜欢这个方法。
七、建议
看门狗机制虽然可以自动刷新锁的过期时间,用起来也非常方便,但并不是说,所有的方法,都应该开启此机制。因为启动此机制的同时,意味着会额外开启一个线程来监控它,那么就会占用CPU内存。少量线程的情况下,这部分内存占用可以忽略,当请求过多时,就占用比略高了,只能增加服务器,也就是增加成本了。
所以我建议是,在获取资源的方法里,不开启看门狗机制,比如,一个接口是返回个人信息的,那么我在调用时,由于某种原因导致锁已经释放,但业务还未执行完成,那么会报错,
信息如下:[Request processing failed; nested exception is java.lang.IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id: 62e61f35-6cd5-4fc2-849e-78ad649435e4 thread-id: 72] with root cause
,我们直接捕获此异常,返回系统繁忙即可。
在更新或者保存资源的方法里,是可以开启看门狗机制的,这样虽然执行时间会稍微长一些,但最终会完成任务,不至于让用户重复操作。
相关文章:

Redisson实现分布式锁示例
一、引入依赖 <dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.16.0</version></dependency>二、配置类 import org.redisson.Redisson; import org.redisson.api.RedissonClient;…...
使用Nginx作为一个普通代理服务器
使用Nginx作为一个普通代理服务器, 请不要用于违法用途哦 nginx作为一个反向代理工具,除了可以进行反向代理之外,还可以用来作为代理工具来使用,作为代理工具使用的步骤如下,这个配置目前支持80端口 Windows系统代理设置对应IP, …...

chatglm2-6b模型在9n-triton中部署并集成至langchain实践 | 京东云技术团队
一.前言 近期, ChatGLM-6B 的第二代版本ChatGLM2-6B已经正式发布,引入了如下新特性: ①. 基座模型升级,性能更强大,在中文C-Eval榜单中,以51.7分位列第6; ②. 支持8K-32k的上下文;…...

Shell编程之正则表达式(非常详细)
正则表达式 1.通配符和正则表达式的区别2.基本正则表达式2.1 元字符 (字符匹配)2.2 表示匹配次数2.4 位置锚定2.5 分组 和 或者 3.扩展正则表达式4.部分文本处理工具4.1 tr 命令4.2 cut命令4.3 sort命令4.4 uniq命令 1.通配符和正则表达式的区别 通配符一般用于文件…...

RNN模型简单理解和CNN区别
目录 神经网络:水平方向延伸,数据不具有关联性 RNN:在神经网络的基础上加上了时间顺序,语义理解 RNN: 训练中采用梯度下降,反向传播 长短期记忆模型 输出关系:1 toN,N to N 单入…...

【Axure高保真原型】JS日期选择器筛选中继器表格
今天和大家分享JS日期选择器筛选中继器表格的原型模板,通过调用浏览器的日期选择器,所以可以获取真实的日历效果,具体包括哪一年二月份有29天,几号对应星期几,都是真实的,获取日期值后,通过交互…...
android bp脚本
一。android大约从7.0开始引入 .bp文件代替以前的.mk文件,用于帮助android项目的编译配置文件。 二。mk文件转化为bp文件,可以使用下面命令转化,注意命令中>,这是写入文件。androidmk是android源码自带的工具,他可…...

Redis 数据库 NoSQL
目录 一、NoSQL 二、为什么会出现NoSQL技术 三、NoSQL的类别 键值(Key-Value)存储数据库 列存储数据库 文档型数据库 图形(Graph)数据库 四、NoSQL适应场景 五、在分布式数据库中CAP原理 1、CAP 2、BASE 一、NoSQL NoS…...
RN 项目异常问题整理
常见问题 无法找到 CardStackStyleInterpolator StackViewStyleInterpolator 这个方法集来代替 CardStackStyleInterpolator的,这个方法集的路径也需要注意一下,在2.12.1版本之前, 该文件在react-navigation/src/views/StackView/中…...

STM8编程[TIM1多路PWM输出选项字节(Option Byte)操作和IO复用]
TIM1多路PWM输出选项字节(Option Byte)操作和IO复用 本文摘录于:https://blog.csdn.net/freeape/article/details/47008033只是做学习备份之用,绝无抄袭之意,有疑惑请联系本人! 代码上要使用TIME1输出3路PWM,代码如下: void tim…...

Java算法_ 反转二叉树(LeetCode_Hot100)
题目描述:给你一棵二叉树的根节点 ,翻转这棵二叉树,并返回其根节点。root。 获得更多?算法思路:代码文档,算法解析的私得。 运行效果 完整代码 /*** 2 * Author: LJJ* 3 * Date: 2023/8/16 13:18* 4*/public class In…...
C/C++ 标准模版库STL(持续更新版)
标准模版库STL 目录 算法库 栈 队列 向量 映射 列表 双向链表 集合 Iterator 送代器 <algorithm> 算法库 max, min 用于找出一组值中的最大值和最小值 swap 用于交换两个变量的值 sort 用于对一个范围内的元素进行排序 lower_bound, upper_bound 用于在已排序的容器…...

ARM(实验二)
uart4.h #ifndef __H__ #define __H__#include "stm32mp1xx_rcc.h" #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_uart.h"//RCC/GPIO/UART4章节初始化 void hal_uart4_init();//发送一个字符函数 void hal_put_char(const char str);//发…...

由“美”出发 听艺术家林曦关于美育与智慧的探讨
不久前,林曦老师与我们的老朋友「十点读书」进行了一次线上直播,有关林曦老师十余年的书法教学,和传统美育的心得,以及因此诞生的新书《无用之美》。 这一次的直播,由“美”的主题出发,延伸出美育…...
Serial与Parallel GC之间的不同之处是什么?
Serial GC(串行垃圾回收器)和Parallel GC(并行垃圾回收器)都是Java虚拟机(JVM)中用于进行垃圾回收的两种基本算法。它们在性能、资源利用和回收效率等方面存在一些不同之处。下面是它们之间的详细比较: 1.工作方式 Serial GC:它是一种单线程的垃圾回收器…...

GB28181设备接入侧如何对接外部编码后音视频数据并实现预览播放
技术背景 我们在对接GB28181设备接入模块的时候,遇到这样的技术诉求,好多开发者期望能提供编码后(H.264/H.265、AAC/PCMA)数据对接,确保外部采集设备,比如无人机类似回调过来的数据,直接通过模…...

【java】为什么文件上传要转成Base64?
文章目录 1 前言2 multipart/form-data上传3 Base64上传3.1 Base64编码原理3.2 Base64编码的作用 4 总结 1 前言 最近在开发中遇到文件上传采用Base64的方式上传,记得以前刚开始学http上传文件的时候,都是通过content-type为multipart/form-data方式直接…...

SCSS 学习笔记 和 vscode下载live sass compiler插件配置
1、下载livelive sass compiler插件并配置 // 在 已有代码 下面 添加下面 代码,一般刚刚下载打开最后一行是:// "liveSassCompile.settings.autoprefix": [],// 所以直接 把下面复制进去保存就行"liveSassCompile.settings.autoprefix&qu…...

CSS中的字体属性有哪些值,并分别描述它们的作用。
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ font-style⭐ font-weight⭐ font-size⭐ font-family⭐ font-variant⭐ line-height⭐ letter-spacing⭐ word-spacing⭐ font⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专…...

机器学习笔记之优化算法(十五)Baillon Haddad Theorem简单认识
机器学习笔记之优化算法——Baillon Haddad Theorem简单认识 引言 Baillon Haddad Theorem \text{Baillon Haddad Theorem} Baillon Haddad Theorem简单认识证明过程证明:条件 1 ⇒ 1 \Rightarrow 1⇒ 条件 2 2 2证明:条件 3 ⇒ 3 \Rightarrow 3⇒条件 1…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...