Redisson 分布式锁的最佳实践
Redisson 分布式锁的最佳实践
- 第一、添加依赖
- 第二、添加redisson配置类
- 第三、添加测试类
- 测试结果
- 扩展知识
- redisson锁中lock方法和tryLock方法有什么区别
- 锁续约
- 注意事项
引言
在现代分布式系统中,处理并发问题是至关重要的。分布式锁是解决这类问题的关键工具之一。本文将介绍如何使用 Redisson,一个强大的 Redis 客户端库,来实现高性能、高可用性的分布式锁。
基本概念
分布式锁是多个进程或线程之间协调操作的一种机制。它通常包括三个基本操作:加锁、持有锁、释放锁。Redisson 提供了简单而强大的接口来管理这些操作。
Redisson 分布式锁的使用方法
第一、添加依赖
<!-- redisson分布式锁 -->
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.15.5</version>
</dependency>
第二、添加redisson配置类
package com.kingmouse.lock;import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** Created with IntelliJ IDEA** @author kingMouse* @date 2023/11/7 09:50* Description: redisson配置类 单机和集群自选*/@Configuration
public class RedissonConfig {/*** 单机模式* @return RedissonClient*/@Bean(destroyMethod = "shutdown")public RedissonClient redissonSingle() {// 1.创建配置Config config = new Config();// 单机模式config.useSingleServer()// 设置地址.setAddress("redis://127.0.0.1:6379")// 设置连接数.setConnectionPoolSize(10);return Redisson.create(config);}/*** 单机模式* @return RedissonClient*/// @Bean(destroyMethod = "shutdown")
// public RedissonClient redissonCluster() {
// // 1.创建配置
// Config config = new Config();
// // 集群模式-带密码
// config.useClusterServers()
// .addNodeAddress("127.0.0.1:7004", "127.0.0.1:7001")
// .setPassword("12356")
// // 设置master节点最小连接数
// .setMasterConnectionMinimumIdleSize(10)
// // 设置slave节点最小连接数
// .setSlaveConnectionMinimumIdleSize(10);
// return Redisson.create(config);
// }
第三、添加测试类
package com.kingmouse.lock;import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.util.concurrent.TimeUnit;/*** Created with IntelliJ IDEA** @author kingMouse* @date 2023/11/5 09:54* Description:*/@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedissonLockTest {@Autowiredprivate RedissonClient redissonClient;/*** 阻塞式*/@Testpublic void testRedissonBlock() {// 设置锁的名字,同一个名字为同一把锁,不同名字之间互不干扰String lockKey = "kingmouse-001";// 获取锁对象RLock lock = redissonClient.getLock(lockKey);// 加锁,尝试获取锁,5秒后获取不到则直接放弃lock.lock(5, TimeUnit.SECONDS);// 实际业务处理try {System.out.println("阻塞式--加锁成功,线程 ID:" + Thread.currentThread().getId());} catch (Exception e) {log.error("业务处理异常:{}", e.getMessage());} finally {// 解锁lock.unlock();System.out.println("阻塞式--解锁成功,线程 ID:" + Thread.currentThread().getId());}}@Testpublic void testRedissonNonBlock() throws Exception {// 设置锁的名字,同一个名字为同一把锁,不同名字之间互不干扰String lockKey = "kingmouse-002";// 获取锁对象RLock lock = redissonClient.getLock(lockKey);// 尝试获取锁,最长等待5秒,持有锁最长30秒boolean isLock = lock.tryLock(5, 30, TimeUnit.SECONDS);if (isLock) {// 实际业务处理try {System.out.println("非阻塞式--获取锁成功,线程 ID:" + Thread.currentThread().getId());} catch (Exception e) {log.error("业务处理异常:{}", e.getMessage());} finally {// 解锁lock.unlock();System.out.println("非阻塞式--解锁成功,线程 ID:" + Thread.currentThread().getId());}}}}
测试结果
阻塞式--加锁成功,线程 ID:1
阻塞式--解锁成功,线程 ID:1
非阻塞式--获取锁成功,线程 ID:1
非阻塞式--解锁成功,线程 ID:1
扩展知识
redisson锁中lock方法和tryLock方法有什么区别
在 Redisson 中,lock 方法和 tryLock 方法都是用来获取分布式锁的,但它们在获取锁的方式和行为上有一些区别:
在 Redisson 中,lock 方法和 tryLock 方法都是用来获取分布式锁的,但它们在获取锁的方式和行为上有一些区别:
-
lock方法:lock方法是阻塞的,即如果获取锁失败,调用该方法的线程会被阻塞,直到获取到锁为止。- 如果在获取锁时发生网络分区或其他异常,会一直重试获取锁,直到获取成功或者达到设置的超时时间为止。
- 使用
lock方法时,如果获取锁成功后,需要手动调用unlock方法来释放锁。
例如:
RLock lock = redisson.getLock("myLock");lock.lock();try {// 执行业务逻辑} finally {lock.unlock();}
-
tryLock方法:tryLock方法是非阻塞的,即如果获取锁失败,方法会立即返回,不会阻塞当前线程。tryLock方法可以设置超时时间,在指定的超时时间内尝试获取锁,如果超时仍未获取到锁,则返回false。- 使用
tryLock方法时,获取锁成功后不需要手动释放锁,因为锁会在超时时间后自动释放。(建议使用完自动释放锁)
例如:
RLock lock = redisson.getLock("myLock");boolean isLocked = lock.tryLock(10, TimeUnit.SECONDS);if (isLocked) {try {// 执行业务逻辑} finally {lock.unlock();}} else {// 获取锁失败的处理逻辑}
总结来说,lock 方法是阻塞的,会一直尝试获取锁直到成功,而 tryLock 方法是非阻塞的,在指定的超时时间内尝试获取锁,如果超时则返回失败。选择使用哪种方法取决于你的业务需求,以及是否能够容忍等待获取锁的阻塞时间。
锁续约
使用看门狗(Watchdog)可以实现锁的自动续约:
String permitId = lock.acquire(10, TimeUnit.SECONDS);
RScheduledExecutorService executorService = redisson.getExecutorService("myExecutorService");
executorService.schedulePermitExpiration(permitId, 5, TimeUnit.SECONDS);
在这个例子中,我们使用 schedulePermitExpiration 方法每隔5秒续约一次锁的持有时间。
注意事项
在使用分布式锁时,需要注意以下几点:
-
合理设置锁的持有时间:不要将锁的持有时间设置得过长,以免影响系统的并发性能。根据实际业务需求,选择一个合适的持有时间。
-
使用看门狗进行续约:在需要锁的持有时间较长的情况下,使用看门狗可以确保锁不会在持有时间内过期,避免了手动续约的繁琐操作。
-
异常处理:在加锁、续约、释放锁的过程中,需要考虑可能出现的异常情况,并进行适当的处理,以确保锁能够被正确释放,避免死锁等问题。
实际应用场景
在电商系统中,分布式锁可以用来避免商品超卖问题。在任务调度系统中,可以确保同一个任务在同一时刻只被一个节点执行,避免任务重复执行等问题。
总结
Redisson 提供了简单而强大的分布式锁解决方案,通过合理设置锁的持有时间和使用看门狗进行续约,可以确保系统在高并发环境下的稳定性和可靠性。在实际应用中,开发人员可以根据业务需求选择合适的锁策略,并进行必要的异常处理,以实现分布式系统的高效运行。
相关文章:
Redisson 分布式锁的最佳实践
Redisson 分布式锁的最佳实践 第一、添加依赖第二、添加redisson配置类第三、添加测试类测试结果扩展知识redisson锁中lock方法和tryLock方法有什么区别锁续约 注意事项 引言 在现代分布式系统中,处理并发问题是至关重要的。分布式锁是解决这类问题的关键工具之一。…...
ArkTS声明式开发范式
装饰器 用来装饰类、结构体、方法以及变量,赋予其特殊的含义,如上述示例中 Entry 、 Component 、 State 都是装饰器。 Component 表示这是个自定义组件; Entry 则表示这是个入口组件; State 表示组件中的状态变量,…...
史诗级云故障敲响警钟,应用保障不能没有“连续键”!
近日,知名云服务商出现一次史诗级的云故障:全球所有区域/所有服务同时异常,故障持续长达3小时之多,云上众多应用受到极大影响。 如今,在一个充满不确定性和复杂性的数字化时代,哪怕是顶级云服务商亦不能避…...
SSH连接远程服务器报错:WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED 解决方法
一.错误描述 报错信息里提示了路径信息/root/.ssh/known_hosts:20 二.解决方案 方法一 输入以下指令: ssh-keygen -R XXX(需要连接远程服务器的ip) 按照我的例子ip:10.165.7.136,会返回以下信息: 重新尝试连接: 输…...
数据库——查询连续的月份
一、GP或PGSQL with recursive t(n) as (select date(2023-01-01) union all select n1 from t where n < now()) select to_char(n, yyyy-mm) as ny from t group by ny order by ny 二、Hive select add_months(FROM_UNIXTIME(unix_timestamp(SUBSTR(start_date, 1, 7…...
git代码提交命令(如何提交代码)
# 提交暂存区到仓库区 $ git commit -m [message]# 提交暂存区的指定文件到仓库区 $ git commit [file1] [file2] ... -m [message]# 提交工作区自上次commit之后的变化,直接到仓库区 $ git commit -a# 提交时显示所有diff信息 $ git commit -v# 使用一次新的commit…...
jmeter中调用python代码
1、安装pyinstaller pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyinstaller 2、将py脚本打包 pyinstaller -F venv/get_image/OCR_jmeter_api.py 3、jmeter中添加OS Process Sampler并调用dist下的程序 4、执行jmeter...
当当网获得dangdang商品详情商品列表API 测试请求入口
item_get-获得dangdang商品详情 获取商品详情 item_search-按关键字搜索dangdang商品 获取商品列表 公共参数 名称类型必须描述keyString是调用key(必须以GET方式拼接在URL中)secretString是调用密钥api_nameString是API接口名称(包括在请…...
git如何查看配置,修改配置,设置配置
# 显示当前的Git配置 $ git config --list# 编辑Git配置文件 $ git config -e [--global]# 设置提交代码时的用户信息 $ git config [--global] user.name "[name]" $ git config [--global] user.email "[email address]"...
交通流合成数据生成原理及实现代码
移动数据是设备的地理位置,通过正常活动被动产生。 它具有从交通规划到迁移预测的重要应用。 由于移动数据稀有且难以收集,研究人员已开始探索综合生成移动数据的解决方案。 在本文中,我将讨论一种用于合成移动数据的简单解决方案。 该合成数…...
leetcode 240. 搜索二维矩阵 II
2023.11.22 本题最先想到的是暴力法和二分法,暴力法就不写了,写一下二分法的解法,java代码如下: class Solution {public boolean searchMatrix(int[][] matrix, int target) {for(int[] row : matrix){int left 0;int right r…...
a标签超链接 —— 实现点击前中后变色
浅浅记录下 <style type"text/css"> a:link {color: yellow; /*未访问链接颜色*/ }a:visited {color: red; /*已访问链接颜色*/ }a:hover {color: blue; /*鼠标移动到链接颜色*/text-decoration: underline; }a:active {color: orange; /*鼠标点击时颜色*/ }a…...
【好玩的开源项目】Linux系统之部署proxx扫清黑洞小游戏
【好玩的开源项目】Linux系统之部署proxx扫清黑洞小游戏 一、proxx小游戏介绍1.1 proxx小游戏简介1.2 开源地址 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、检查本地环境3.1 检查本地操作系统版本3.2 检查系统内核版本 四、部署Node.js环境4.1 下载Node.js安装包4.…...
IDEA-SVN合并分支到主干
IDEA-SVN合并branch分支到主干master 1.选择VCS的 Integrate Project 2.选择分支合并 Source1 是合并后的分支 , 主分支 master Source2 是被合并的分支 , 分支 branch Try merge 可以尝试是否可以能够被合并,并且无冲突 3.合并完成后当前项目会出现需要提交的内容,检查一…...
kettle如何写日志
var subject"自定义日志输出"; //实例化工厂类 var logFactory new org.pentaho.di.core.logging.LogChannelFactory(); //实例化日志channel对象 var log logFactory.create(subject); //日志输出 log.logMinimal("XXXXXXXXXXXXXXXXXXXXXXXX-preRows"acc…...
新能源车将突破2000万辆,汉威科技为电池安全保驾护航
近年来,我国新能源汽车销量持续突破新高。据中汽协数据,1~10月,国内新能源汽车销量达728万辆,同比增长37.8%,市场占有率达到30.4%。随着第四季度车市传统旺季的到来,新能源消费需求将进一步释放,…...
基于文心一言AI大模型,编写一段python3程序以获取华为分布式块存储REST接口的实时数据
本文尝试基于文心一言AI大模型,编写一段python3程序以获取华为分布式块存储REST接口的实时数据。 一、用文心一言AI大模型将需求转化为样例代码 1、第一次对话:“python3写一段从rest服务器获取数据的样例代码” 同时生成了以下注解 这段代码首先定义…...
2022-4-11 南科大现代控制与最优估计
CLEAR_LAB B站视频 矩阵的分块矩阵操作 diagonal 对角阵 identity matrix 单位矩阵 矩阵克罗内克积...
【注册Huggingface】获取token
Hugging Face是一家美国公司,专门开发用于构建机器学习应用的工具。该公司的代表产品是其为自然语言处理应用构建的transformers库,以及允许用户共享机器学习模型和数据集的平台。 Huggingface 是一个开源的cv、nlp框架,提供了超过100,000个…...
【蓝桥杯软件赛 零基础备赛20周】第4周——简单模拟1
文章目录 什么是简单模拟简单模拟和编程能力刷题 什么是简单模拟 正在学编程语言(C/C、Python、Java),或者刚学过语言,还没有开始学数据结构和算法的同学,有一些疑问:如何快速入门算法竞赛?如何…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
