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

Redisson 分布式锁的使用详解

一、分布式锁的概述

1.1 分布式锁的背景

在单机系统中,Java 提供了 synchronizedLock 等锁机制来确保并发情况下的线程安全。然而,在分布式系统中,多个服务实例运行在不同的物理或虚拟机上,无法直接使用这些本地的锁机制来控制对共享资源的访问。

为了在分布式环境中控制对共享资源的访问,就需要引入一种能够跨多台服务器实例的锁机制,这就是分布式锁。Redis 作为一种高性能的内存数据库,提供了基于 Redis 的分布式锁实现。Redisson 基于 Redis 对分布式锁进行了封装,提供了简洁易用的 API 来管理分布式锁。

1.2 分布式锁的特性

一个完整的分布式锁需要具备以下几个特性:

  1. 互斥性:同一时刻只能有一个客户端能获得锁,其他客户端必须等待锁被释放后才能继续操作。
  2. 容错性:如果持有锁的客户端因为网络或系统故障而没有主动释放锁,锁应当能够被安全地释放。
  3. 高可用性:锁的请求和释放过程应该是高效的,且在 Redis 节点出现故障时,系统依然能够正常工作。

二、Redisson 分布式锁的原理

Redisson 分布式锁基于 Redis 的 SETNX (set if not exists) 命令实现。基本的原理如下:

  1. 加锁:客户端请求加锁时,会向 Redis 发送一个 SETNX 命令,如果返回值为 1,表示加锁成功。如果返回 0,则说明锁已经被其他客户端持有,当前客户端需要等待。
  2. 自动过期:为了防止客户端因故障而无法释放锁,锁的持有是有过期时间的。通过 Redis 的 EXPIRE 命令,锁在加锁时同时设置过期时间,到期后锁将自动释放。
  3. 解锁:锁持有者执行完任务后,主动向 Redis 发送命令删除锁的 key,从而释放锁,其他等待的客户端才能继续加锁。

Redisson 通过封装 Redis 的这些基础命令,提供了 RLock 接口来方便地实现分布式锁。

三、Redisson 分布式锁的使用

3.1 引入 Redisson 依赖

在项目中使用 Redisson,首先需要在 pom.xml 文件中引入 Redisson 的依赖:

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

3.2 Redisson 配置

为了使用 Redisson 分布式锁,首先需要配置 Redisson 客户端。Redisson 支持单节点模式、主从模式、集群模式和哨兵模式等多种 Redis 部署模式。这里我们以单节点模式为例:

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;public class RedissonConfig {public RedissonClient redissonClient() {Config config = new Config();config.useSingleServer().setAddress("redis://127.0.0.1:6379");return Redisson.create(config);}
}

3.3 使用分布式锁

在配置好 Redisson 客户端后,可以通过 RedissonClient 来获取 RLock 对象,进行分布式加锁和解锁操作。下面是一个简单的使用示例:

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;public class DistributedLockExample {private final RedissonClient redissonClient;public DistributedLockExample(RedissonClient redissonClient) {this.redissonClient = redissonClient;}public void executeWithLock() {// 获取锁对象RLock lock = redissonClient.getLock("myLock");try {// 加锁lock.lock();System.out.println("获得锁,执行临界区代码");// 模拟业务逻辑Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();} finally {// 解锁lock.unlock();System.out.println("释放锁");}}
}

在上面的示例中,我们通过 redissonClient.getLock("myLock") 获取一个名为 myLock 的锁对象,并在执行完任务后通过 lock.unlock() 主动释放锁。

3.4 设置锁的超时时间

为了防止因异常情况导致锁无法释放,Redisson 提供了设置锁超时时间的功能。在获取锁时,可以通过 lock.lock(long leaseTime, TimeUnit unit) 方法指定锁的持有时间。例如,下面的代码将设置锁的持有时间为 10 秒:

public void executeWithTimeoutLock() {RLock lock = redissonClient.getLock("myLock");try {// 加锁并设置超时时间为10秒lock.lock(10, TimeUnit.SECONDS);System.out.println("获得锁,执行临界区代码");// 模拟业务逻辑Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();} finally {// 无需主动解锁,锁会在10秒后自动释放if (lock.isHeldByCurrentThread()) {lock.unlock();}System.out.println("释放锁");}
}

四、Redisson 分布式锁的应用场景

4.1 控制并发访问

在电商、抢购等高并发场景中,多个用户同时发起对同一商品的抢购请求,此时需要使用分布式锁来控制对库存资源的并发访问,防止超卖或重复购买。

public void purchase(String productId) {RLock lock = redissonClient.getLock("product:" + productId);try {// 尝试获取锁if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {// 执行购买逻辑System.out.println("购买成功");} else {System.out.println("获取锁失败,购买失败");}} catch (InterruptedException e) {e.printStackTrace();} finally {if (lock.isHeldByCurrentThread()) {lock.unlock();}}
}

4.2 分布式任务调度

在分布式系统中,任务调度器往往有多个实例在同时运行。如果多个实例同时执行相同的任务,可能会导致数据重复处理或任务冲突。此时可以通过 Redisson 分布式锁确保同一时刻只有一个实例能够执行任务。

public void scheduleTask() {RLock lock = redissonClient.getLock("taskLock");try {if (lock.tryLock(1, TimeUnit.MINUTES)) {System.out.println("获得锁,执行调度任务");// 执行定时任务}} catch (InterruptedException e) {e.printStackTrace();} finally {if (lock.isHeldByCurrentThread()) {lock.unlock();}}
}

4.3 分布式事务

在分布式系统中,为了确保多个数据库或服务之间的数据一致性,可以使用 Redisson 分布式锁来控制对共享资源的访问,从而实现分布式事务的控制。

五、Redisson 分布式锁的优缺点

5.1 优点

  1. 实现简单:Redisson 提供了简洁的 API,开发者可以轻松地实现分布式锁功能。
  2. 丰富的分布式工具:除了分布式锁,Redisson 还提供了其他分布式工具,如分布式集合、队列、布隆过滤器等,适用于多种场景。
  3. 自动续期:Redisson 提供了自动续期功能,防止因任务执行时间过长导致锁意外释放。

5.2 缺点

  1. 依赖 Redis:Redisson 是基于 Redis 实现的分布式锁,依赖于 Redis 的可用性和性能。
  2. **锁的粒度

问题**:在使用分布式锁时,需要合理设计锁的粒度。锁粒度过大会导致性能瓶颈,锁粒度过小则可能导致竞争加剧。

六、总结

Redisson 作为 Redis 的高级客户端,提供了简单易用的分布式锁实现,能够很好地解决分布式系统中的并发控制问题。通过 Redisson,开发者可以快速实现分布式锁,并应用到电商、任务调度、分布式事务等场景中。

在使用 Redisson 分布式锁时,除了基本的加锁和解锁操作外,还需要合理设计锁的粒度,确保锁的可用性和系统性能的平衡。

相关文章:

Redisson 分布式锁的使用详解

一、分布式锁的概述 1.1 分布式锁的背景 在单机系统中&#xff0c;Java 提供了 synchronized 和 Lock 等锁机制来确保并发情况下的线程安全。然而&#xff0c;在分布式系统中&#xff0c;多个服务实例运行在不同的物理或虚拟机上&#xff0c;无法直接使用这些本地的锁机制来控…...

计算机网络:物理层 --- 基本概念、编码与调制

目录 一. 物理层的基本概念 二. 数据通信系统的模型 三. 编码 3.1 基本概念 3.2 不归零制编码 3.3 归零制编码 3.4 曼切斯特编码 3.5 差分曼切斯特编码 ​编辑 四. 调制 4.1 调幅 4.2 调频 4.3 调相 4.4 混合调制 今天我们讲的是物理…...

使用Maven创建一个Java项目并在repository中使用

JDK环境&#xff1a;1.8.0_371 Maven环境 &#xff1a;Apache Maven 3.6.3 配置完成jdk和mvn后&#xff0c;进入到指定文件夹下执行如下语句&#xff1a; mvn archetype:generate -DgroupIdtop.chengrongyu -DartifactIdCyberSpace -DarchetypeArtifactIdmaven-archetype-quic…...

如何使用IIC外设(硬件IIC)

本文重点叙述如何使用芯片自带的 IIC 外设&#xff0c;即硬件 IIC&#xff0c;实现 IIC 通信。文章《IIC通信基础_cpu的iic通信-CSDN博客》 中&#xff0c;叙述了软件 IIC 通信和硬件 IIC 通信的区别&#xff0c; 并且重点叙述了 IIC 的通信协议。在使用软件进行 IIC 通信时&am…...

使用 Vue 3、Vite 和 TypeScript 的环境变量配置

使用 Vue 3、Vite 和 TypeScript 的环境变量配置 在开发现代前端应用时&#xff0c;环境变量是一个非常重要的概念。它可以帮助我们根据不同的环境&#xff08;开发、测试、生产&#xff09;配置不同的行为&#xff0c;比如 API 请求地址、调试选项等。在 Vue 3、Vite 和 Type…...

F28335 的串行外设接口(以下简称 SPI)

1 SPI 介绍 1.1 SPI 简介 1.2 F28335 的 SPI模块介绍 (1)F28335 的 SPI 特点...

科技引领未来生活——“光影漫游者”展览馆应用—轻空间

随着科技的快速发展&#xff0c;展览馆作为展示文化、科技和艺术的场所&#xff0c;正逐渐从传统的静态展示向高科技互动体验转变。由轻空间打造的“光影漫游者”展览馆&#xff0c;凭借其前沿的气承式结构和智能化系统&#xff0c;将参观者带入了一个未来感十足、充满科技魅力…...

ego-planner开源代码之启动参数介绍分析

ego-planner开源代码之启动参数介绍&分析 1. 源由2. 逻辑分析3. 启动参数section 1 三维地图尺寸section 2 里程计话题映射section 3 advanced_param.xml配置section 3.1section 3.2section 3.3section 3.4section 3.5section 3.6section 3.7section 3.8 section 4 轨迹服务…...

828 华为云征文|华为 Flexus 云服务器打造 Laverna 在线笔记应用

一、引言 在当今数字化时代&#xff0c;高效的笔记管理工具对于学习、工作和生活都至关重要。Laverna 作为一款功能强大的开源在线笔记应用&#xff0c;提供了 Markdown 编辑、加密支持等特性&#xff0c;是替代 Evernote 的绝佳选择。在 2024 年 9 月 14 日这个充满创新的日子…...

数据结构与算法-Trie树添加与搜索

trie树的使用场景 我们若需要制作一个通讯录的软件&#xff0c;使用常规树结构查询的复杂度为O(logn),但trie树的复杂度确与数据多少无关&#xff0c;与单词长度有关&#xff0c;这就大大缩减的查询的时间复杂度。 trie树的基本实现 基础结构 package com.study.trieDemo;i…...

AIGC专栏15——CogVideoX-Fun详解 支持图文生视频 拓展CogVideoX到256~1024任意分辨率生成

AIGC专栏15——CogVideoX-Fun详解 支持图&文生视频 拓展CogVideoX到256&#xff5e;1024任意分辨率生成 学习前言项目特点生成效果相关地址汇总源码下载地址 CogVideoX-Fun详解技术储备Diffusion Transformer (DiT)Stable Diffusion 3EasyAnimate-I2V 算法细节算法组成InPa…...

BFS 解决多源最短路问题

文章目录 多源BFS542. 01 矩阵题目解析算法原理代码实现 1020. 飞地的数量题目解析算法原理 1765. 地图中的最高点题目解析算法原理代码实现 1162. 地图分析题目解析算法原理代码实现 多源BFS 单源最短路&#xff1a; 一个起点、一个终点 多源最短路&#xff1a; 可以多个起点…...

论文笔记:交替单模态适应的多模态表征学习

整理了CVPR2024 Multimodal Representation Learning by Alternating Unimodal Adaptation&#xff09;论文的阅读笔记 背景MLA框架实验Q1 与之前的方法相比&#xff0c;MLA能否克服模态懒惰并提高多模态学习性能?Q2 MLA在面临模式缺失的挑战时表现如何?Q3 所有模块是否可以有…...

鸿蒙OS 线程间通信

鸿蒙OS 线程间通信概述 在开发过程中&#xff0c;开发者经常需要在当前线程中处理下载任务等较为耗时的操作&#xff0c;但是又不希望当前的线程受到阻塞。此时&#xff0c;就可以使用 EventHandler 机制。EventHandler 是 HarmonyOS 用于处理线程间通信的一种机制&#xff0c…...

执行 npm报错 Cannot find module ‘../lib/cli.js‘

报错 /usr/local/node/node-v18.20.4-linux-x64/bin/npm node:internal/modules/cjs/loader:1143 throw err; ^ Error: Cannot find module ../lib/cli.js Require stack: - /usr/local/node/node-v18.20.4-linux-x64/bin/npm at Module._resolveFilename (node:inter…...

基于SpringBoot+Vue+MySQL的国产动漫网站

系统展示 用户前台界面 管理员后台界面 系统背景 随着国内动漫产业的蓬勃发展和互联网技术的快速进步&#xff0c;动漫爱好者们对高质量、个性化的国产动漫内容需求日益增长。然而&#xff0c;市场上现有的动漫平台大多以国外动漫为主&#xff0c;对国产动漫的推广和展示存在不…...

AUTOSAR汽车电子嵌入式编程精讲300篇-基于CAN总线的气动控制

目录 前言 知识储备 什么是气动控制: 气动控制基础知识 一、气动元件 二、气路设计 三、气动控制系统 气动控制系统构成图 气动控制系统基本组成功能图 几种常见的气动执行元件实物图 常用气动压力控制阀实物图 常用气动流动控制阀实物图 电磁控制换向发实物图 部…...

Ubuntu 20.04 内核升级后网络丢失问题的解决过程

在 Ubuntu 系统中&#xff0c;内核升级是一个常见的操作&#xff0c;旨在提升系统性能、安全性和兼容性。然而&#xff0c;有时这一操作可能会带来一些意外的副作用&#xff0c;比如导致网络功能的丧失。 本人本来是想更新 Nvidia 显卡的驱动&#xff0c;使用 ubuntu-drivers …...

论文解读《LaMP: When Large Language Models Meet Personalization》

引言&#xff1a;因为导师喊我围绕 “大语言模型的个性化、风格化生成” 展开研究&#xff0c;所以我就找相关论文&#xff0c;最后通过 ACL 官网找到这篇&#xff0c;感觉还不错&#xff0c;就开始解读吧&#xff01; “说是解读&#xff0c;其实大部分都是翻译哈哈哈&#x…...

Excel VLOOKUP函数怎么用?vlookup函数的使用方法及案例

大家好&#xff0c;这里是效率办公指南&#xff01; &#x1f50e; 在Excel的世界里&#xff0c;VLOOKUP函数无疑是查询和数据分析中的明星。无论是从庞大的数据表中提取特定信息&#xff0c;还是进行数据的快速匹配&#xff0c;VLOOKUP都能大显身手。今天&#xff0c;我们将深…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

WPF八大法则:告别模态窗口卡顿

⚙️ 核心问题&#xff1a;阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程&#xff0c;导致后续逻辑无法执行&#xff1a; var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题&#xff1a…...

【WebSocket】SpringBoot项目中使用WebSocket

1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖&#xff0c;添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...