Redisson详解

什么是Redisson?什么业务中用过Redis的分布式锁?在SpringBoot中怎么用分布式锁?用的是哪个工具类?怎么设这个分布式锁?

什么是Redisson?

Redisson 是一个用于 Java 的 Redis 客户端,它不仅提供了对 Redis 命令的访问,还实现了多种分布式对象、锁和同步工具。Redisson 的设计目标是简化在分布式系统中使用 Redis 的复杂度,并为开发者提供更高层次的抽象,以便更容易地实现诸如分布式锁、信号量、布隆过滤器等高级功能。

Redission 支持可重入锁,这意味着同一个线程可以在不释放之前持有的锁的情况下再次获取同一把锁。为了实现这一点,Redission 在内部维护了一个计数器来跟踪同一个客户端获取同一把锁的次数。每次获取锁时计数器增加,而每次解锁时计数器减少,直到计数器归零才真正释放锁

以下是 Redisson 的一些主要特点和提供的功能:

  1. 丰富的数据结构支持

Redisson 实现了几乎所有的 Redis 数据类型(如 String, Map, Set, List 等),并且将它们包装成 Java 对象的形式,使得操作这些数据类型就像操作本地 Java 集合一样简单。

  1. 分布式集合

提供了 RSet, RList, RMap 等接口,允许用户在多个 JVM 之间共享数据结构,保证数据的一致性和高可用性。

  1. 分布式锁与同步工具
  • 包含了多种类型的分布式锁,例如可重入锁 (RLock)、公平锁 (RFairLock)、读写锁 (RReadWriteLock) 和红锁 (RRedLock)。
  • 还有分布式信号量 (RSemaphore)、计数信号量 (RCountDownLatch) 和闭锁 (RPermitExpirableSemaphore) 等同步工具,帮助协调不同节点之间的并发访问。
  1. 消息队列

支持发布/订阅模式 (RTopic) 和阻塞队列 (RBlockingQueue),可以用来构建事件驱动架构或异步任务处理系统。

  1. 任务调度

内置的任务调度器 (RScheduledExecutorService) 可以安排一次性或周期性的任务执行,适用于需要定时触发的操作。

  1. 分布式集合框架

提供了 RBucket, RScoredSortedSet, RHyperLogLog 等高级数据结构的支持,满足更复杂的业务需求。

  1. 缓存解决方案

提供了基于 Redis 的缓存机制,包括本地缓存、近缓存和多级缓存策略,提高了数据读取效率并降低了主数据库的压力。

  1. 易于集成

Redisson 易于与其他 Java 应用程序和服务集成,可以通过 Spring Boot Starter 快速配置,也兼容其他常见的依赖注入容器。

  1. 性能优化

Redisson 使用 Netty 框架进行网络通信,并且内部做了很多优化以确保高效的命令执行和数据传输。

  1. 集群模式支持

全面支持 Redis 集群,能够自动发现和管理集群中的节点变化,保障服务的连续性和可靠性。

业务场景

在实际应用中,可能会在以下场景中使用 Redis 分布式锁:

  1. 库存管理
  • 业务背景:电商平台在处理商品购买时,需要保证同一时间只能有一个请求更新库存数量,以防止超卖现象。
  • 实现方式:当用户提交订单时,服务器尝试获取该商品对应的分布式锁。如果成功,则进行库存扣减操作,并释放锁;否则等待一段时间后重试。
  1. 秒杀活动
  • 业务背景:在线促销活动中,如“双十一”或限时抢购,大量用户同时发起请求,可能导致数据库压力过大以及库存超卖问题。
  • 实现方式:通过 Redis 分布式锁限制同一时刻只能有一个进程处理用户的秒杀请求。一旦某个进程获得了锁,它会检查是否有足够的库存,并立即减少库存数,然后释放锁。其他进程必须等待直到前一个进程完成并释放锁。
  1. 账务处理
  • 业务背景:银行转账、支付网关等金融交易系统要求高度的一致性和准确性,不允许并发操作导致账户余额错误。
  • 实现方式:在处理转账或支付请求时,先尝试获取涉及账户的分布式锁。成功后执行账务变更逻辑(如扣除金额),最后释放锁。这可以确保即使在网络延迟或异常情况下也不会发生重复扣款等问题。
  1. 缓存更新
  • 业务背景:某些应用依赖缓存来加速数据读取速度,但当缓存失效时,所有客户端几乎同时去刷新缓存,可能会造成所谓的“缓存雪崩”效应。
  • 实现方式:引入 Redis 分布式锁控制缓存重建过程,使得每次只有单一客户端负责从原始数据源加载最新数据到缓存中,其余客户端则等待直至新缓存生成完毕。
  1. 任务调度
  • 业务背景:分布式环境中,定时任务或周期性作业可能由多台服务器共同承担,为了防止同一任务被多次执行,需要一种机制来同步这些任务。
  • 实现方式:利用 Redis 分布式锁作为任务锁,确保每次只有一个实例执行特定的任务。例如,在每天凌晨两点清理日志文件的任务中,只有获得锁的那个节点才能开始清理工作。
  1. 配置管理
  • 业务背景:微服务架构下的配置中心允许动态调整服务参数,但是为了避免不同服务实例之间相互覆盖配置信息,需要有锁定机制。
  • 实现方式:当某个服务实例想要修改全局配置时,它首先要尝试获取与该配置相关的分布式锁。成功后更新配置,并通知其他服务实例重新加载新的配置值。
  1. 批量导入/导出
  • 业务背景:企业级应用经常涉及到大量数据的批量导入或导出操作,这类操作通常是耗时且资源密集型的,不适合并发执行。
  • 实现方式:采用 Redis 分布式锁来确保同一时间内只有一项批量任务在运行。这样可以避免因并发执行而引起的性能瓶颈或数据一致性问题。
  1. 用户注册与激活
  • 业务背景:为了防止恶意注册行为,一些网站会在用户注册或激活过程中设置验证步骤,比如发送验证码短信。这里也需要确保每个手机号码仅能接收一次验证码。
  • 实现方式:使用 Redis 分布式锁控制验证码的发放,确保同一个手机号码的验证码请求不会同时存在两个或更多未完成的状态。

Spring Boot 中使用Redisson

在 Spring Boot 中使用 Redis 实现分布式锁有多种方式,常用的是通过 Redisson 或者 spring-boot-starter-data-redis 结合 Lettuce/Jedis 客户端库来实现。

使用 Redisson

Redisson 是一个流行的 Redis Java 客户端,它提供了许多高级功能,包括分布式锁。以下是设置和使用 Redisson 分布式锁的基本步骤:

添加依赖

pom.xml 文件中添加 Redisson 的依赖:

<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.20.0</version> <!-- 确保版本号是最新的 -->
</dependency>

配置 Redisson 连接

application.propertiesapplication.yml 文件中配置 Redisson 的连接信息。

获取锁对象并使用

使用 RedissonClient 来获取 RLock 对象,然后尝试加锁、解锁等操作。

@Autowired
private RedissonClient redissonClient;public void someServiceMethod() {RLock lock = redissonClient.getLock("myLock");try {// 尝试加锁,等待时间10秒,锁自动释放时间为30秒boolean isLocked = lock.tryLock(10, 30, TimeUnit.SECONDS);if (isLocked) {// 执行需要互斥执行的代码块}} catch (InterruptedException e) {Thread.currentThread().interrupt();// 处理异常} finally {if (lock.isHeldByCurrentThread()) {lock.unlock(); // 确保在finally块中解锁}}
}

注意事项

  • 锁的超时设置:设置合理的锁超时时间,以防止出现死锁的情况。
  • 锁的唯一性:确保每个客户端持有的锁是唯一的,以便正确解锁。
  • 异常处理:在发生异常时,确保锁被正确释放,否则可能导致其他客户端无法获取锁。

分布式锁实现原理

加锁(tryLock()

Redisson 使用 Redis 的 SETNX(SET if Not eXists)命令来尝试获取锁。SETNX 是一种原子操作,只有在键不存在时才会设置成功。这意味着如果多个客户端同时尝试获取同一个锁,只有一个会成功。使用 SETNX 设置锁时,通常会结合 EXPIRE 或者直接使用 SETEX 命令为锁设置一个过期时间。这是为了防止死锁的发生,即如果持有锁的进程崩溃而没有主动释放锁,那么经过一定时间后锁也会自动释放。

骚戴理解:简单来说就是通过SETNX+PEXPIRE + Lua 脚本实现分布式锁, Lua 脚本会在 Redis 中执行,它首先尝试使用 SETNX 设置键,如果成功,则通过 PEXPIRE 设置键的过期时间。Lua 脚本是为了保证这些操作的原子性

删除锁(unlock()

为了安全地删除锁,Redission 使用 Lua 脚本来检查当前锁是否由当前客户端持有( Redisson 在加锁的时候会关联一个唯一的标识符(lockId),解锁时会检查这个标识符是否匹配,避免了误删其他客户端持有的锁的问题)。如果是,则删除该锁;否则拒绝解锁请求。

锁续期与看门狗机制

Redission 提供了一种称为“看门狗”(Watchdog)的机制,用来自动延长锁的有效期。当客户端成功获取到锁后,看门狗会启动一个后台任务,周期性地检查锁的状态并在必要时更新其过期时间。这样即使处理时间超过了最初设定的锁有效期,只要任务还在进行中,锁就不会被其他客户端抢走,通过看门狗机制确保长时间运行的任务不会意外失去锁

  • 续期逻辑:每当看门狗发现锁即将过期时,它会自动调用 expire 或者 pexpire 命令延长锁的生存时间。续期的时间间隔通常是锁原始有效时间的一半左右。
  • 看门狗触发条件:看门狗会在锁被获取后的第一次续期时启动,并在锁释放时停止。此外,如果锁已经因为某些原因提前释放,则看门狗也会随之终止。

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

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

相关文章

全程Kali linux---CTFshow misc入门(25-37)

第二十五题&#xff1a; 提示&#xff1a;flag在图片下面。 直接检查CRC&#xff0c;检测到错误&#xff0c;就直接暴力破解。 暴力破解CRC的python代码。 import binascii import struct def brute_force_ihdr_crc(filename): # 读取文件二进制数据 with open(filen…

MySQL数据库(二)- SQL

目录 ​编辑 一 DDL (一 数据库操作 1 查询-数据库&#xff08;所有/当前&#xff09; 2 创建-数据库 3 删除-数据库 4 使用-数据库 (二 表操作 1 创建-表结构 2 查询-所有表结构名称 3 查询-表结构内容 4 查询-建表语句 5 添加-字段名数据类型 6 修改-字段数据类…

Android记事本App设计开发项目实战教程2025最新版Android Studio

平时上课录了个视频&#xff0c;从新建工程到打包Apk&#xff0c;从头做到尾&#xff0c;没有遗漏任何实现细节&#xff0c;欢迎学过Android基础的同学参加&#xff0c;如果你做过其他终端软件开发&#xff0c;也可以学习&#xff0c;快速上手Android基础开发。 Android记事本课…

STM32调试手段:重定向printf串口

引言 C语言中经常使用printf来输出调试信息&#xff0c;打印到屏幕。由于在单片机中没有屏幕&#xff0c;但是我们可以重定向printf&#xff0c;把数据打印到串口&#xff0c;从而在电脑端接收调试信息。这是除了debug外&#xff0c;另外一个非常有效的调试手段。 一、什么是pr…

如何使用 ChatBox AI 简化本地模型对话操作

部署模型请看上一篇帖子&#xff1a;本地部署DeepSeek教程&#xff08;Mac版本&#xff09;-CSDN博客 使用 ChatBox AI 简化本地模型对话操作&#xff1a; 打开 ChatBox AI 官网&#xff1a;Chatbox AI官网&#xff1a;办公学习的AI好助手&#xff0c;全平台AI客户端&#xf…

C++ Primer 自定义数据结构

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…

鸿蒙物流项目之基础结构

目录&#xff1a; 1、项目结构2、三种包的区别和使用场景3、静态资源的导入4、颜色样式设置5、修改项目名称和图标6、静态包基础目录7、组件的抽离8、在功能模块包里面引用静态资源包的组件 1、项目结构 2、三种包的区别和使用场景 3、静态资源的导入 放在har包中&#xff0c;那…

RK3568使用QT搭建TCP服务器和客户端

文章目录 一、让RK3568开发板先连接上wifi二、客户端代码1. `widget.h` 文件2. `widget.cpp` 文件**详细讲解**1. **`Widget` 类构造函数 (`Widget::Widget`)**2. **UI 布局 (`setupUI`)**3. **连接按钮的槽函数 (`onConnectClicked`)**4. **发送消息按钮的槽函数 (`onSendMess…

Redis|前言

文章目录 什么是 Redis&#xff1f;Redis 主流功能与应用 什么是 Redis&#xff1f; Redis&#xff0c;Remote Dictionary Server&#xff08;远程字典服务器&#xff09;。Redis 是完全开源的&#xff0c;使用 ANSIC 语言编写&#xff0c;遵守 BSD 协议&#xff0c;是一个高性…

【算法设计与分析】实验8:分支限界—TSP问题

目录 一、实验目的 二、实验环境 三、实验内容 四、核心代码 五、记录与处理 六、思考与总结 七、完整报告和成果文件提取链接 一、实验目的 掌握分支界限求解问题的思想&#xff1b;针对不同的问题&#xff0c;能够利用分支界限法进行问题拆分和求解以及时间复杂度分析…

2025年大年初一篇,C#调用GPU并行计算推荐

C#调用GPU库的主要目的是利用GPU的并行计算能力&#xff0c;加速计算密集型任务&#xff0c;提高程序性能&#xff0c;支持大规模数据处理&#xff0c;优化资源利用&#xff0c;满足特定应用场景的需求&#xff0c;并提升用户体验。在需要处理大量并行数据或进行复杂计算的场景…

2025:影刀RPA使用新实践--CSDN博客下载

文章目录 一键CSDN博客下载器程序说明指导说明使用步骤 获取方法 一键CSDN博客下载器 程序说明 配置信息&#xff1a;CSDN账号&#xff08;手机号/邮箱/用户名&#xff09;、密码、博客文件类型支持markdown格式、html格式&#xff08;默认值markdown格式&#xff09;、博客保…

游戏引擎 Unity - Unity 启动(下载 Unity Editor、生成 Unity Personal Edition 许可证)

Unity Unity 首次发布于 2005 年&#xff0c;属于 Unity Technologies Unity 使用的开发技术有&#xff1a;C# Unity 的适用平台&#xff1a;PC、主机、移动设备、VR / AR、Web 等 Unity 的适用领域&#xff1a;开发中等画质中小型项目 Unity 适合初学者或需要快速上手的开…

【Postman接口测试】Postman的安装和使用

在软件测试领域&#xff0c;接口测试是保障软件质量的关键环节之一&#xff0c;而Postman作为一款功能强大且广受欢迎的接口测试工具&#xff0c;能够帮助测试人员高效地进行接口测试工作。本文将详细介绍Postman的安装和使用方法&#xff0c;让你快速上手这款工具。 一、Pos…

边缘检测算法(candy)

人工智能例子汇总&#xff1a;AI常见的算法和例子-CSDN博客 Canny 边缘检测的步骤 1. 灰度转换 如果输入的是彩色图像&#xff0c;则需要先转换为 灰度图像&#xff0c;因为边缘检测通常在单通道图像上进行。 2. 高斯滤波&#xff08;Gaussian Blur&#xff09; 由于边缘…

WinDBG查找C++句柄泄露

C代码&#xff08;频繁点击About按钮导致Mutex句柄泄露&#xff09; HANDLE _mutexHandle;LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {switch (message){case WM_COMMAND:{int wmId LOWORD(wParam);// 分析菜单选择:switch (wmId){c…

基于微信小程序的酒店管理系统设计与实现(源码+数据库+文档)

酒店管理小程序目录 目录 基于微信小程序的酒店管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员模块的实现 (1) 用户信息管理 (2) 酒店管理员管理 (3) 房间信息管理 2、小程序序会员模块的实现 &#xff08;1&#xff09;系统首页 &#xff…

大白话讲清楚embedding原理

Embedding&#xff08;嵌入&#xff09;是一种将高维数据&#xff08;如单词、句子、图像等&#xff09;映射到低维连续向量的技术&#xff0c;其核心目的是通过向量表示捕捉数据之间的语义或特征关系。以下从原理、方法和应用三个方面详细解释Embedding的工作原理。 一、Embe…

mysql中in和exists的区别?

大家好&#xff0c;我是锋哥。今天分享关于【mysql中in和exists的区别&#xff1f;】面试题。希望对大家有帮助&#xff1b; mysql中in和exists的区别&#xff1f; 在 MySQL 中&#xff0c;IN 和 EXISTS 都是用于子查询的操作符&#xff0c;但它们在执行原理和适用场景上有所不…

MySQL高可用

一、mysql路由 1.利用路由器的连接路由特性&#xff0c;用户可以编写应用程序来连接到路由器&#xff0c;并令路由器使用响应的路由策略来处理连接来使其连接到正确的mysql数据库服务器 2.mysql route的部署方式 需要在所有数据库主机之外再打开一台主机mysql-router 配置mysql…