当前位置: 首页 > news >正文

学习Redisson实现分布式锁

官网:https://redisson.org/

官方文档:https://redisson.org/docs/getting-started/

官方中文文档:https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95

1、引入依赖

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

如果用下面这个依赖,后面则省去config这一步配置过程,如果用上面后面config则要配置

<!-- https://mvnrepository.com/artifact/org.redisson/redisson-spring-boot-starter -->
<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.27.2</version>
</dependency>

2、配置Redisson客户端

(1)程序化配置方法

参考官网:

@Configuration
public class RedissonConfig {@Beanpublic RedissonClient redissonClient(){// 配置Config config = new Config();// 如果是集群使用config.useClusterServers().setAddress()config.useSingleServer().setAddress("redis://192.168.75.101:6379").setPassword("123321");// 创建RedissonClient对象return Redisson.create(config);}
}
(2)文件方式配置

当然也可以如果yml的方式进行配置,参考官方文档如下:https://github.com/redisson/redisson/wiki/2.-%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95#22-%E6%96%87%E4%BB%B6%E6%96%B9%E5%BC%8F%E9%85%8D%E7%BD%AE

还有一些配置详细信息:

 这里我们使用程序化配置方式 !

3、简单使用Redisson的分布式锁

这里讲可重入锁

 参考:8. 分布式锁和同步器 · redisson/redisson Wiki · GitHub

@Resource
private RedissionClient redissonClient;@Test
void testRedisson() throws Exception{//获取锁(可重入),指定锁的名称RLock lock = redissonClient.getLock("myLock");//尝试获取锁,参数分别是:获取锁的最大等待时间(期间会重试),锁自动释放时间,时间单位boolean isLock = lock.tryLock(1,10,TimeUnit.SECONDS);//判断获取锁成功if(isLock){try{System.out.println("执行业务");          }finally{//释放锁lock.unlock();}}       
}

Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟

剩余其余锁可以参考官方文档。

4、分布式锁原理

Redisson分布式锁原理:

可重入:利用hash结构记录线程id和重入次数

可重试:利用信号量和PubSub功能实现等待、唤醒,获取锁失败的重试机制

超时续约:利用watchDog机制,开启一个定时任务,每隔一段时间(releaseTime / 3),重置超时时间

5、实战

在微信登录操作的时候加上分布式锁

首先需要:

@Resource
private RedissonClient redissonClient;
/*** 微信登录*/@Overridepublic User wxLogin(UserLoginDTO userLoginDTO) {//调用微信接口服务,获得当前微信用户的openidString openid = getOpenid(userLoginDTO.getCode());System.out.println("当前微信用户的openid"+openid);//判断openid是否为空,如果为空表示登录失败,抛出业务异常if (openid==null){throw new LoginFailedException(MessageConstant.LOGIN_FAILED);}//判断当前用户是否为新用户
//        User user = userMapper.getByOpenid(openid);QueryWrapper<User>wrapper=new QueryWrapper<>();wrapper.lambda().eq(User::getOpenid,openid);User user = userMapper.selectOne(wrapper);//如果为新用户,自动完成注册if (user==null){RLock lock = redissonClient.getLock(RedissonConstant.LOCK_USER_REGISTER_KEY + openid);if (!lock.tryLock()){throw new RegisterFailedException(MessageConstant.REGISTER_FAILED_USER_EXIST);}try {//获得当前用户表数据数量Long allUserNums = userMapper.selectCount(null);//构造用户编号id/*"%0" + 8 + "d":这是一个格式字符串,用于指定输出格式。"%0" 表示输出时,如果数字的长度不足指定的宽度,则在前面补0;8 是紧接着 %0 后面的数字,表示输出的数字至少要有8位;"d" 表示输出的是十进制整数。因此,整个格式字符串意味着输出一个至少8位的十进制整数,如果不足8位,则在前面补0*/String substring = String.valueOf(System.currentTimeMillis()).substring(5);String quickUserId = "QUICK" +substring+"_"+ String.format("%0" + 6 + "d", allUserNums + 1);log.info("注册新用户");user=User.builder().openid(openid).quickUserId(quickUserId).wallet(0L).follow(0L).fan(0L).briefIntroduction("").collectNumber(0L).markNumber(0L).useTime(0L).name("微信用户").phone("").sex("").avatar("https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0").createTime(LocalDateTime.now()).build();userMapper.insert(user);//发送mq异步消息修改es表 发送这两个数据后续获取用户信息 openidtry {rabbitTemplate.convertAndSend(EsUserDocListener.ADD_USER_DOC_EXCHANGE_NAME,EsUserDocListener.ADD_USER_DOC_ROUTING_KEY,user.getQuickUserId());} catch (AmqpException e) {log.error("发送新增userDoc消息失败", e);}}catch (DuplicateKeyException e){throw new RegisterFailedException(MessageConstant.REGISTER_FAILED_USER_EXIST);}finally {// 解锁lock.unlock();}}//返回这个用户的对象return user;}

相关文章:

学习Redisson实现分布式锁

官网&#xff1a;https://redisson.org/ 官方文档&#xff1a;https://redisson.org/docs/getting-started/ 官方中文文档&#xff1a;https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95 1、引入依赖 <!--redisson--> <dependency><groupId>or…...

2024CSP-J模拟赛9————S12678

一&#xff0c;赛中得分 T1100T2100T350T440总分290 二&#xff0c;赛中概括 T1T2较快过&#xff0c;T3T4骗了90分&#xff08;意料之中&#xff0c;这么好骗分&#xff01;&#xff01;&#xff01;&#xff09;。 三&#xff0c;题目解析 涂格子(paint) 问题描述 现在有…...

HarmonyOS中ArkUi框架中常用的装饰器

目录 1.装饰器 1&#xff09;Component 1--装饰内容 2&#xff09;Entry 1--装饰内容 2--使用说明 3&#xff09;Preview 1--装饰内容 2--使用说明 4&#xff09;CustomDialog 1--装饰内容 2--使用说明 5&#xff09;Observed 1--装饰内容 2--使用说明 6&#xff09;ObjectLin…...

服务攻防之Redis数据库安全

最近我将会把一些服务攻防方面的姿势在这里做一个简单总结。欢迎大家留言讨论。 首先我们先对这类安全问题做一个总体的概括&#xff01; 一、总概 1.服务判断: 端口扫描&#xff1a;利用服务开启后的目标端口开放判断 组合判断&#xff1a;利用搭建常见组合分析可能开放服务…...

随机森林算法的原理与实现

随机森林&#xff08;Random Forest&#xff09;是一种集成学习算法&#xff0c;它通过构建多个决策树并结合这些树的结果来进行分类或回归。与单一的决策树相比&#xff0c;随机森林通过集成多个树的结果&#xff0c;能够显著提高预测的准确性和稳定性&#xff0c;减少模型的过…...

模仿百度-基础版

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>百度案例</title><style>*{margin: 0;p…...

c++贴瓷砖

题目描述 有一块大小是 2 * n 的墙面&#xff0c;现在需要用2种规格的瓷砖铺满&#xff0c;瓷砖规格分别是 2 * 1 和 2 * 2&#xff0c;请计算一共有多少种铺设的方法。 输入 输入的第一行包含一个正整数T&#xff08;T<20&#xff09;&#xff0c;表示一共有T组数据&…...

用 Python 构建高级配对交易策略

作者&#xff1a;老余捞鱼 原创不易&#xff0c;转载请标明出处及原作者。 写在前面的话&#xff1a; 本文阐述通过分析加密货币和传统金融工具之间的相关性和协整性&#xff0c;以及实施 Z-score 方法来生成交易信号&#xff0c;然后介绍如何使用 Python 构建配对交易策…...

Java 引用数据类型详解、字符串的不可变性、如何处理字符串的内存管理、String Pool 及其优化

文章目录 1. 引用数据类型1.1 常见引用数据类型 2. 字符串的不可变性2.1 不可变性的优点2.2 不可变性示例 3. 如何处理字符串的内存管理3.1 String Pool3.2 String 内存优化 4. String Pool 及其优化4.1 String Pool的工作原理4.2 String Pool的优化4.3 使用 intern() 进一步优…...

Babel使用

初始化项目 npm init -y 创建文件 // 转码前 // 定义数据 let input [1, 2, 3] // 将数组的每个元素 1 input input.map(item > item 1) console.log(input)配置.babelrc Babel的配置文件是.babelrc&#xff0c;presets字段设定转码规则&#xff0c;将es2015规则加入…...

自动机器学习(AutoML)

utoML是PAI的提供的自动寻找超参组合的机器学习增强型服务。您在训练模型时&#xff0c;如果超参组合复杂度过高&#xff0c;需大量训练资源和手工调试工作&#xff0c;可以使用AutoML来节省模型调参时间&#xff0c;提升模型调优效率和模型质量。 基础概念 超参数&#xff1a;…...

Vivado时序报告六:Report Timing详解

目录 一、前言 二、配置选项概览图 三、配置选项详解 3.1 Targets 3.2 Options 3.1.1 Report 3.1.2 Path limits 3.1.3 Path display 3.2 Advanced 3.2.1 Report 3.2.2 File Output 3.2.3 miscellaneous 3.3 Timer Settings 3.4 共有部分 四、 设计示例 4.1 设…...

java基础:数据类型的总结

一、Java 常用数据类型 1.数据类型分为:(1)基本数据类型 &#xff08;2&#xff09;引用数据类型 2.基本数据类型分类&#xff1a;数值型&#xff0c;非数值型。 3.数值型:&#xff08;1&#xff09; 整数类型&#xff08;byte,short,int,long) &#xff08;2&#xff09; …...

【目标检测论文解读复现NO.39】基于改进 YOLOv8 的轻量级复杂环境苹果叶片病害检测方法

前言 此前出了目标改进算法专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读最新目标检测算法论文&#xff0c…...

python 基础笔记 2(函数, 类)

起因, 目的: 把很久以前,自己写的笔记发布出来。 现在粉丝多了,也不觉得丢人了。 为什么这些序号不连贯,因为有些很熟悉的东西,我都删了。 内建函数, 函数 zip()函数,利用 * 号操作符,可以将元组解压为列表。 我怀疑是zip的解包只能用一次。在内存中解开一次之后就销…...

LeetCode 2090.半径为K的子数组平均值

题目&#xff1a; 给你一个下标从 0 开始的数组 nums &#xff0c;数组中有 n 个整数&#xff0c;另给你一个整数 k 。 半径为 k 的子数组平均值 是指&#xff1a;nums 中一个以下标 i 为 中心 且 半径 为 k 的子数组中所有元素的平均值&#xff0c;即下标在 i - k 和 i k 范…...

Qt C++ 编程中定义了一个槽函数(slot)deleteLater的作用

这行代码是在 Qt C编程中定义了一个槽函数&#xff08;slot&#xff09;deleteLater。 在 Qt 框架中&#xff0c;Q_SLOTS关键字用于声明类中的槽函数。deleteLater是一个非常有用的函数&#xff0c;它会安排接收对象在事件循环返回后被删除。 通常在以下情况下会使用deleteLa…...

【Hive】8-Hive性能优化及Hive3新特性

Hive性能优化及Hive3新特性 Hive表设计优化 Hive查询基本原理 Hive的设计思想是通过元数据解析描述将HDFS上的文件映射成表 基本的查询原理是当用户通过HQL语句对Hive中的表进行复杂数据处理和计算时&#xff0c;默认将其转换为分布式计算 MapReduce程序对HDFS中的数据进行…...

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-18

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-18 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-18目录1. On the Reliability of Large Language Models to Misinformed and Demographically-Informed Prompts2. SafeLLM: Dom…...

CTF(四)

导言&#xff1a; 本文主要讲述在CTF竞赛中&#xff0c;web类题目file_include。 靶场链接&#xff1a;攻防世界 (xctf.org.cn) 一&#xff0c;观察页面。 可以看到一段php代码。从则段代码中我们可以知道&#xff1a; 1&#xff0c;使用include引入check.php文件&#xff…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测

uniapp 中配置 配置manifest 文档&#xff1a;manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号&#xff1a;4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

32单片机——基本定时器

STM32F103有众多的定时器&#xff0c;其中包括2个基本定时器&#xff08;TIM6和TIM7&#xff09;、4个通用定时器&#xff08;TIM2~TIM5&#xff09;、2个高级控制定时器&#xff08;TIM1和TIM8&#xff09;&#xff0c;这些定时器彼此完全独立&#xff0c;不共享任何资源 1、定…...

aardio 自动识别验证码输入

技术尝试 上周在发学习日志时有网友提议“在网页上识别验证码”&#xff0c;于是尝试整合图像识别与网页自动化技术&#xff0c;完成了这套模拟登录流程。核心思路是&#xff1a;截图验证码→OCR识别→自动填充表单→提交并验证结果。 代码在这里 import soImage; import we…...