【Redis笔记】使用Redisson实现可重入锁

Redisson

官方github网站:https://github.com/redisson/redisson
Redisson官网:https://redisson.org/

依赖引入

pom.xml文件中写入

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

配置Redisson客户端

  1. 使用yml配置文件
  2. 导入Redisson起步依赖
  3. 自定义Redisson文件

以上方法根据需要选其一即可,此处采用方法三

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;@Configuration
public class RedissonConfig {@Beanpublic RedissonClient redissonClient() {// 配置类Config config = new Config();// 添加redis地址,这里添加了单点的地址,也可以使用config.useClusterServers()添加集群地址config.useSingleServer().setAddress("redis://192.168.88.66:6379").setPassword("123456");// 创建客户端return Redisson.create(config);}
}

业务中调用

		// 创建锁对象RLock lock = redissonClient.getLock("lock:order:" + userId);// 尝试获取锁boolean isLock = lock.tryLock();// 判断是否成功if (!isLock) {// 获取失败返回错误}try {// 执行对应的业务} finally {// 释放锁lock.unlock();}

其中trylock方法共有三个重载方法,如果使用无参的方法,则不会进行等待,锁失效时间使用默认值(应该是30s)。
trylock(long waitTime, long leaseTime, TimeUnit unit)可以去设置等待时间、锁失效时间、时间单位。
trylock(long time, TimeUnit unit) 设置等待时间,时间单位。

Redisson可重入分布式锁原理

可重入:利用hash结构记录线程id和重入次数
可重试:利用信号量和PubSub功能实现等待、唤醒,获取锁失败的重试机制
超时续约:利用watchDog,每隔一段时间(releaseTime/3),重置超时时间

获取锁

  1. 尝试获取锁
  2. 判断ttl是否为null
  • 如果为null,判断leaseTime是否为-1
  • leaseTime为-1,开启看门狗机制watchDog,返回true;不为-1,直接返回true,不开启看门狗。
  1. ttl不为null,判断剩余等待时间是否大于0,如果小于0,返回false
  2. 剩余等待时间大于0,则订阅并等待别的线程释放锁的信号;
  3. 判断等待时间是否超时,已经超时,则返回false
  4. 若未超时,则再去尝试获取锁,即步骤1

释放锁

  1. 尝试释放锁
  2. 判断是否成功
  3. 如果失败,可能已经超时释放,记录异常,并结束
  4. 如果释放成功,发送释放锁消息(对应获取锁的步骤4)给订阅的线程,取消watchDog。

可重入的Lua脚本

Redisson实现也是使用的Lua脚本,具体Redisson实现方法,大家可以去写一个model看下解码的Redisson源码。以下Lua脚本是和Redisson源码思路一样的,但不完全一致,可以帮助理解原理。

获取锁的Lua脚本

-- Redisson 可重入锁获取锁的原理
local key = KEYS[1]; -- 锁的key
local threadId = ARGV[1]; -- 线程唯一标识
local releaseTime = ARGV[2]; -- 锁的自动释放时间
-- 判断是否存在
if(redis.call('exists', key) == 0) then-- 不存在, 获取锁redis.call('hset', key, threadId, '1');-- 设置有效期redis.call('expire', key, releaseTime);return 1; -- 返回结果
end;
-- 锁已经存在,判断threadId是否是自己
if(redis.call('hexists', key, threadId) == 1) then-- 存在, 获取锁,重入次数+1redis.call('hincrby', key, threadId, '1');-- 设置有效期redis.call('expire', key, releaseTime);return 1; -- 返回结果
end;
return 0; -- 代码走到这里,说明获取锁的不是自己,获取锁失败

释放锁的Lua脚本

-- Redisson可重入锁的删除锁原理
local key = KEYS[1]; -- 锁的key
local threadId = ARGV[1]; -- 线程唯一标识
local releaseTime = ARGV[2]; -- 锁的自动释放时间
-- 判断当前锁是否还是被自己持有
if (redis.call('HEXISTS', key, threadId) == 0) thenreturn nil; -- 如果已经不是自己,则直接返回
end;
-- 是自己的锁,则重入次数-1
local count = redis.call('HINCRBY', key, threadId, -1);
-- 判断是否重入次数是否已经为0
if (count > 0) then
-- 大于0说明不能释放锁,重置有效期然后返回redis.call('EXPIRE', key, releaseTime);return nil;
else  -- 等于0说明可以释放锁,直接删除redis.call('DEL', key);return nil;
end;

Redisson主从一致性

主从一致性:设置连锁multiLock,多个独立的Redis节点,必须在所有节点都获取重入锁,才算获取锁成功

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

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

相关文章

2024.1.29力扣每日一题——自由之路

2024.1.29 题目来源我的题解方法一 动态规划 题目来源 力扣每日一题&#xff1b;题序&#xff1a;514 我的题解 方法一 动态规划 定义 dp[i][j] 表示从前往后拼写出 key的第 i个字符&#xff0c; ring 的第 j个字符与 12:00 方向对齐的最少步数&#xff08;下标均从 0 开始&…

2024.2.6

1.现有无序序列数组为23,24,12,5,33,5347&#xff0c;请使用以下排序实现编程 函数1:请使用冒泡排序实现升序排序 函数2:请使用简单选择排序实现升序排序 函数3:请使用快速排序实现升序排序 函数4:请使用插入排序实现升序排序 #include<stdio.h> #include<string.h&g…

简化版SpringMVC

简化版SpringMVC web.xml xml version"1.0" encoding"UTF-8"?> <web-app version"2.5" xmlns"http://java.sun.com/xml/ns/javaee" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation&quo…

C#面:什么是ASP.NET中的用户控件

在 ASP.NET 中&#xff0c;用户控件是一种可重用的自定义控件&#xff0c;它允许开发人员将一组相关的 HTML 和服务器控件封装在一个单独的组件中。用户控件可以像其他内置控件一样在页面上使用&#xff0c;并且可以通过添加自定义属性和事件来扩展其功能。 用户控件通常由一个…

【制作100个unity游戏之24】unity制作一个3D动物AI生态系统游戏2(附项目源码)

最终效果 文章目录 最终效果系列目录前言添加捕食者动画控制源码完结 系列目录 前言 欢迎来到【制作100个Unity游戏】系列&#xff01;本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第24篇中&#xff0c;我们将探索如何用unity制作一个3D动物AI生态系统游戏…

如何在 emacs 上开始使用 Tree-Sitter (archlinux)

文章目录 如何在emacs上开始使用Tree-Sitter&#xff08;archlinux&#xff09; 如何在emacs上开始使用Tree-Sitter&#xff08;archlinux&#xff09; 在archlinux上使用比windows上不知道要方便多少倍&#xff01; $ sudo pacman -S emacs $ sudo pacman -S tree-sitter这里…

第6章——深度学习入门(鱼书)

第6章 与学习相关的技巧 本章将介绍神经网络的学习中的一些重要观点&#xff0c;主题涉及 寻找最优权重参数的最优化方法、权重参数的初始值、超参数的设定方法 等。此外&#xff0c;为了应对过拟合&#xff0c;本章还将介绍 权值衰减、Dropout等正则化方法&#xff0c;并进行实…

Redis(02)——事务管理

事务概念 Redis事务的本质是一组命令的集合。事务支持一次执行多个命令&#xff0c;一个事务中所有命令都会被序列化&#xff0c;在事务执行过程中&#xff0c;会按照顺序串行化执行队列中的命令&#xff0c;其他客户端提交的命令请求不会插入到事务执行命令序列中 Redis事务…

Windows权限维持

注册表类&#xff1a; 普通注册表后门 在一般用户权限下&#xff0c;通常是将要执行的后门程序或脚本路径填写到如下注册表的键值中HKCU\Software\Microsoft\Windows\CurrentVersion\Run&#xff0c;键名任意。普通权限即可运行 cmd下操作&#xff1a; reg add "HKEY_…

我差一点就中了Magniber勒索病毒

前言 勒索攻击已经成为了全球最大的网络威胁&#xff0c;越来越多的黑客组织开始加入到勒索病毒攻击活动&#xff0c;目前勒索病毒黑客组织大致可以分为两类&#xff0c;一类攻击目标主要以TO C(个人)为主&#xff0c;一类攻击目标主要以TO B(企业)为主&#xff0c;前者的勒索…

C# CAD交互界面-自定义面板集(四)

运行环境 vs2022 c# cad2016 调试成功 一、引用 using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.Windows; using System.Windows.Forms; 二、程序说明 创建自定义面板集&#xff08;PaletteSet&#xff09;的C#命令方法实现。该方法名为CreatePalette&#xff…

Redis篇之持久化

一、为什么要进行持久化 Redis是一个基于内存的键值存储系统&#xff0c;但为了保证数据在服务器重启、故障等情况下不丢失。 二、应该怎么持久化 1.RDB持久化 &#xff08;1&#xff09;RDB是什么 RDB全称Redis Database Backup file&#xff08;Redis数据备份文件&#xff…

macOS虚拟机在VMware Workstation/Player上的详细安装与配置教程

一、准备工作 1. 确认兼容性 确保你的宿主机满足运行macOS虚拟机的要求&#xff1a; 操作系统&#xff1a;支持Windows或Linux&#xff08;宿主机需64位操作系统&#xff09;。硬件配置&#xff1a;足够的RAM&#xff08;至少8GB推荐&#xff0c;安装Big Sur或更高版本建议1…

流程引擎activiti、flowable、camunda简单介绍

市场上比较有名的开源流程引擎有osworkflow、jbpm、activiti、flowable、camunda。 其中&#xff1a;Jbpm4、Activiti、Flowable、camunda四个框架同宗同源&#xff0c;祖先都是Jbpm4&#xff0c;开发者只要用过其中一个框架&#xff0c;基本上就会用其它三个。 推荐使用camu…

什么是集群服务器

近一段时间来&#xff0c;集群服务器被广大站长热议&#xff0c;所谓集群服务器就是指很多台服务器把它们集中在一起来进行同一种服务。集群服务器也可以由很多个的计算机并行去计算&#xff0c;这样可以获得非常高的计算速度&#xff0c;提升服务器整体的工作效. 其实我们都知…

【原创】MQTT开发笔记(四)- 压力测试

一、前言 Jmeter 是 apache 公司基于 java 开发的一款开源压力测试工具&#xff0c;体积小&#xff0c;功能全&#xff0c;使用方便&#xff0c;是一个比较轻量级的测试工具&#xff0c;使用起来非常简 单。因为 jmeter 是 java 开发的&#xff0c;所以运行的时候必须先要安装 …

2.7通过select、多进程、多线程实现一个并发服务器

select #include <myhead.h>#define PORT 8888 //端口号 #define IP "192.168.250.100" //IP地址int main(int argc, const char *argv[]) {//1、创建用于接受连接的套接字int sfd socket(AF_INET, SOCK_STREAM, 0);if(sfd -1){perror(&…

C语言带颜色输出

我们在做函数API功能测试时或其他数据解析时&#xff0c;为了区分信息内容&#xff0c;可以给不同级别的输出加上不同的颜色&#xff0c;以方便查看。 如&#xff0c;我自己的一个项目中的显示效果&#xff1a; 这样做可以更加清晰的反应数据信息&#xff01; 实现原理&#x…

07:Kubectl 命令详解|K8S资源对象管理|K8S集群管理(重难点)

Kubectl 命令详解&#xff5c;K8S资源对象管理&#xff5c;K8S集群管理 kubectl管理命令kubectl get 查询资源常用的排错命令kubectl run 创建容器 POD原理pod的生命周期 k8s资源对象管理资源文件使用资源文件管理对象Pod资源文件deploy资源文件 集群调度的规则扩容与缩减集群更…

网络分析仪的防护技巧

VNA的一些使用防护技巧&#xff0c;虽不全面&#xff0c;但非常实用&#xff1a; [1] 一定要使用正规接地的三相交流电源线缆进行供电&#xff0c;地线不可悬浮&#xff0c;并且&#xff0c;火线和零线不可反接&#xff1b; [2] 交流供电必须稳定&#xff0c;如220V供电&#x…