当前位置: 首页 > 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;我们将深…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...