Redission从入门到入门
1. Redisson简介
Redisson 是一个在 Java 环境中使用的 Redis 客户端库。它提供了丰富的功能,使得在 Java 应用中与 Redis 交互变得更加简单和高效。Redisson 不仅提供了基本的 Redis 操作,还提供了许多高级功能,使其成为在 Java 项目中实现分布式和可扩展解决方案的强大工具。以下是 Redisson 的一些主要特点和功能:
1. 易于使用的 Java 对象接口
Redisson 提供了一系列的 Java 集合和工具的接口实现,如 Map
、Set
、List
、Queue
等,这些接口都直接映射到 Redis 数据结构,使得使用 Redis 就像使用 Java 中的常规数据结构一样简单。
2. 分布式对象和服务
Redisson 实现了许多分布式对象(例如分布式锁、原子长整型、计数信号量、闭锁等),这些对象在分布式环境中非常有用。例如,它提供了一个可靠的分布式锁实现,这是在分布式系统中实现互斥操作的常见需求。
3. 发布/订阅机制
Redisson 充分利用了 Redis 的发布/订阅功能,提供了一个简单的 API 来实现消息的发布和订阅。
4. 高可用性和集群支持
Redisson 对 Redis 的主从复制和哨兵模式提供了良好的支持,也支持 Redis 集群模式,这有助于构建高可用的大规模分布式应用。
5. 易于集成
它可以轻松与框架如 Spring、Spring Boot 集成,提供了对多种序列化机制(例如 JSON、Avro、Smile、CBOR 等)的支持。
6. Redis 数据类型的高级功能
Redisson 扩展了 Redis 的基本数据类型,提供了如延迟队列、优先队列、双端队列、映射缓存、集合等更高级的结构和功能。
7. 实时地图缩减和分布式服务
Redisson 还提供了其他高级功能,比如实时地图缩减、分布式服务和任务执行等。
总之,Redisson 是一个功能丰富且高度专业化的库,适用于那些希望通过 Redis 解决复杂分布式数据处理和存储问题的 Java 应用程序。通过 Redisson,开发人员可以更容易地将 Redis 的强大功能集成到他们的 Java 应用中。
2. 使用Redisson加分布式锁
使用Redisson实现分布式锁通常涉及以下几个步骤:配置Redisson客户端、获取锁、执行业务逻辑,以及释放锁。下面是一个结合Spring Boot控制器(Controller)处理HTTP请求的示例:
1. 添加Redisson依赖
首先,在你的Spring Boot项目的pom.xml
中添加Redisson依赖:
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId>
</dependency>
2. 配置Redisson客户端
在你的Spring Boot应用中配置Redisson客户端。这可以在一个配置类中完成,例如:
@Configuration
public class RedissonConfig {@Beanpublic RedissonClient redissonClient() {Config config = new Config();config.useSingleServer().setAddress("redis://127.0.0.1:6379");return Redisson.create(config);}
}
3. 创建Controller
创建一个Controller,使用Redisson分布式锁来处理请求:
@RestController
@RequestMapping("/api")
public class MyController {private final RedissonClient redissonClient;public MyController(RedissonClient redissonClient) {this.redissonClient = redissonClient;}@GetMapping("/perform-task")public ResponseEntity<String> performTask() {RLock lock = redissonClient.getLock("myLock");try {// 尝试获取锁,最多等待100秒,锁定后100秒自动解锁boolean isLocked = lock.tryLock(100, 100, TimeUnit.SECONDS);if (isLocked) {// 执行业务逻辑try {// 业务逻辑return ResponseEntity.ok("任务执行成功");} finally {lock.unlock();}} else {return ResponseEntity.status(HttpStatus.CONFLICT).body("无法获取锁");}} catch (InterruptedException e) {Thread.currentThread().interrupt();return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("操作被中断");}}
}
在这个示例中,当HTTP GET请求发送到/api/perform-task
时,会尝试获取名为myLock
的锁。如果获取到锁,它会执行业务逻辑(在此示例中仅返回一个成功消息),然后释放锁。如果无法获取锁,则返回一个冲突状态的响应。
注意
- 锁的名称(在此例中为
myLock
)应该是唯一的,以区分不同的锁。 - 使用
tryLock
而不是lock
,因为tryLock
可以避免死锁的情况。它还允许你指定获取锁的最大等待时间和锁定时间。 - 确保在业务逻辑执行后释放锁,最好放在
finally
块中以确保锁一定会被释放。 - 锁的持有时间应该足够长,以确保业务逻辑能够执行完成。
这个过程确保了在分布式环境中,同一时间只有一个进程可以执行特定的代码块,有效地防止了并发执行引发的问题。
3. 加锁解锁流程
加锁
-
锁的唯一标识:Redisson 生成一个唯一的标识符(比如UUID),用于标识锁的持有者。
-
尝试获取锁:Redisson 向 Redis 发送一个
SET
命令,附带NX
(Not Exists,只有键不存在时才设置键)和PX
(设置键的过期时间,毫秒级)选项。键的名称对应于锁名,值为上述生成的唯一标识符。 -
判断锁的获取:如果
SET
命令成功(返回1),则表示当前线程成功获取了锁。如果命令失败(返回0),表示锁已被其他线程或进程持有。 -
重试机制:如果未能获取锁,Redisson 会等待一段时间后重试,直到超时或获取锁为止。
解锁
解锁操作通常包括以下步骤:
-
验证锁的所有权:Redisson 会首先验证当前线程是否持有该锁。这通常是通过比较 Redis 中锁对应的值(即前面提到的唯一标识符)来实现的。
-
释放锁:如果当前线程是锁的持有者,Redisson 会发送一个命令(比如
DEL
命令)来删除对应的键,从而释放锁。 -
Lua 脚本:为了保证操作的原子性,上述两个步骤(验证和删除)通常是通过执行一个 Lua 脚本在 Redis 服务器上完成的。
锁续期
锁的续期是为了防止长时间运行的进程因执行时间超过锁的过期时间而导致锁被意外释放。Redisson 的锁续期通常涉及以下几个步骤:
-
看门狗(Watchdog)机制:Redisson 内部有一个看门狗机制,它会在后台运行。
-
定期续期:当一个线程持有锁时,看门狗会定期(默认情况下每隔10秒)检查所有由当前Redisson实例持有的锁。
-
发送续期命令:如果锁即将到期,看门狗会向 Redis 发送命令(比如
PEXPIRE
),更新锁的过期时间,从而避免锁被意外释放。 -
续期失败处理:如果续期失败(例如因为 Redis 服务器不可用),看门狗会尝试重新获取锁或触发相应的错误处理逻辑。
相关文章:
Redission从入门到入门
1. Redisson简介 Redisson 是一个在 Java 环境中使用的 Redis 客户端库。它提供了丰富的功能,使得在 Java 应用中与 Redis 交互变得更加简单和高效。Redisson 不仅提供了基本的 Redis 操作,还提供了许多高级功能,使其成为在 Java 项目中实现…...

PHP对接企业微信
前言 最近在做项目中,要求在后台管理中有企业微信管理的相关功能。相关准备工作,需要准备好企业微信账号,添加自建应用,获得相应功能的权限,以及agentid、secre等。 参考文档: 企业微信开发文档 功能实现 因…...
【原创】录剪视频的折腾之路
制作视频的起因 本人为IT男,IT发展快,需要学习的东西又多。往往为了一个技术小问题,花好几天时间学习,接下来十来分钟把事情做完。下次遇到这个同样的问题的时候,可能是几个月后,甚至是几年以后了。这些技…...

【BI】FineBI功能学习路径-20231211
FineBI功能学习路径 https://help.fanruan.com/finebi/doc-view-1757.html 编辑数据概述 1.1 调整数据结构 1.2 简化数据 2.1上下合并 2.2其他表添加列 2.3左右合并 新增分析指标 函数参考 https://help.fanruan.com/finereport/doc-view-1897.html 数值函数 日期函数 文…...
pytorch之torch.utils.data学习
1、概述 PyTorch 数据加载利用的核心是torch.utils.data.DataLoader类 。它表示在数据集上 Python 可迭代,支持 map-style and iterable-style datasets(地图样式和可迭代样式数据集), customizing data loading orderÿ…...
Spring Boot 3中一套可以直接用于生产环境的Log4J2日志配置
文章目录 一 Log4J2 相关概念及基本特点二 Spring Boot3 中启用Log4J2的pom.xml配置三 application.properties 的配置四 完整配置 一 Log4J2 相关概念及基本特点 Log4J2是Apache Log4j的升级版,参考了logback的一些优秀的设计,并且修复了一些问题&…...

iOS按钮控件UIButton使用
1.在故事板中添加按钮控件,步聚如下: 同时按钮Shift+Commad+L在出现在控件库中选择Button并拖入View Controller Scene中 将控件与变量btnSelect关联 关联后空心变实心 如何关联?直接到属性窗口拖按钮变量到控件上,出现一条线,然后松开,这样就关联成功了 关联成功后属性窗口…...

小程序开发实战案例之三 | 小程序底部导航栏如何设置
小程序中最常见的功能就是底部导航栏了,今天就来看一下怎么设置一个好看的导航栏~这里我们使用的是支付宝官方小程序 IDE 做示范。 官方提供的底部导航栏 第一步:页面创建 一般的小程序会有四个 tab,我们这次也是配置四个 tab 的…...
Android : 序列化 JSON简单应用
1. JSON介绍 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和写入,同时也易于机器解析和生成。它基于JavaScript的子集,采用完全独立于语言的文本格式来存储和表示数据。JSON是纯文本&#x…...
Java小案例-RocketMQ的11种消息类型,你知道几种?(普通消息和批量消息)
前言 这篇给大家讲普通消息和批量消息,主要配合代码进行讲解,关于RocketMQ的基础知识已经在上篇给大家讲过需要回顾的点击下面这个链接去看 RocketMQ基础知识 普通消息 普通消息其实就很简单,是Apache RocketMQ中最基础的消息形式&#x…...
前端小技巧: 设计一个简版前端统计 SDK
统计 sdk 如何设计 1 ) 概述 客户端一个sdk ,把数据发送给服务端(第三方统计平台)服务端产生一个统计的报表 2 )需求点 访问量:pv自定义事件:用户的一切行为我们都可以自定义采集性能,错误 3 ) 代码实现 const P…...
DevOps搭建(十一)-Jenkins容器内部使用Docker详解
1、目的 配置的目的是使得Jenkins容器可以直接使用宿主机的Docker,从而可以直接使用Docker命令进行本地打包操作,然后推送到Harbor镜像仓库。 2、修改数据卷 如何在docker中执行宿主机的docker操作,我们管它叫docker in docker。 至于为什么要在docker中操作宿主机的doc…...

用户访问认证
注解 Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) Documented public interface Login { }自定义拦截器 Component public class AuthInterceptor implements HandlerInterceptor {ResourceJwtUtils jwtUtils;Overridepublic boolean preHandle(HttpServ…...
前端知识(七)———HTTPS:保护网络通信安全的关键
当谈到网络通信和数据传输时,安全性是一个至关重要的问题。在互联网上,有许多敏感信息需要通过网络进行传输,例如个人身份信息、银行账户信息和商业机密等。为了保护这些信息不被未经授权的人访问和篡改,HTTPS(超文本传…...
element-ui按钮el-button,点击之后恢复之前的颜色
在开发过程中, 使用el-button 按钮点击之后, 没有恢复到之前的颜色, 还是保持点击之后的颜色,需要解决这个问题, <template><div><el-button size"mini" type"primary" plain click"onClick($event)">按钮</el-button>…...

Excel: Python 如何干掉 VBA 系列 乙
以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/k2XtfXS3GUt4r2QhizMOVg 创建工作表格 创建表格 xlwings 就可以协助创建插入了宏的 excel 表格。 先找到一个心满意足的目录,一般我…...

算法笔记—链表、队列和栈
链表、队列和栈 1. 链表1.1 单链表反转1.2 双链表反转1.3 合并两个有序链表1.4 链表相加1.5 划分链表 2. 队列和栈2.1 循环队列2.2 栈实现队列2.3 队列实现栈2.4 最小栈2.2 双端队列 1. 链表 1.1 单链表反转 力扣 反转链表 // 反转单链表public ListNode reverseList(ListNod…...

MySQL中的时间函数整理汇总
1.获取当前时间 -- 获取当前时间 SELECT NOW(); -- 获取当前日期 SELECT CURDATE(); -- 获取当前时分秒 SELECT CURTIME(); 2.获取对应日期对应的年/月/日/月份名/星期数 -- 返回对应日期对应的年/月/日/月份名/星期数 select year(now())as 年,month(now())as 月,day(now())…...

stu06-VSCode里的常用快捷键
Alt Z:文字自动换行。当一行的文字太长时,可以使用。或者查看→自动换行Alt Shift ↓ :快速复制当前行到下一行Alt Shift ↑ :快速复制当前行到上一行Alt B:在默认浏览器中打开当前.html文件Ctrl Enter…...

Bypass open_basedir
讲解 open_basedir是php.ini中的一个配置选项,可用于将用户访问文件的活动范围限制在指定的区域。 假设open_basedir/var/www/html/web1/:/tmp/,那么通过web1访问服务器的用户就无法获取服务器上除了/var/www/html/web1/和/tmp/这两个目录以外的文件。…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...

WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...