Redisson分布式锁的概念和使用
Redisson分布式锁的概念和使用
- 一 简介
- 1.1 什么是分布式锁?
- 1.2 Redisson分布式锁的原理
- 1.3 Redisson分布式锁的优势
- 1.4 Redisson分布式锁的应用场景
- 二 案例
- 2.1 锁竞争案例
- 2.2 看门狗案例
- 2.3 参考文章
前言
这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。作者:神的孩子都在歌唱
一 简介
1.1 什么是分布式锁?
在分布式系统中,多个服务实例或进程可能会同时访问共享资源(例如数据库、文件等)。为了防止数据竞争或一致性问题,我们需要一种机制来确保在同一时间,只有一个进程能够访问这些资源。这种机制就是分布式锁。
Redisson 是一个支持 Redis 的 Java 客户端,它不仅能提供简单的 Redis 连接,还包括了许多高级功能,如分布式锁、异步任务执行、限流等。Redisson 基于 Redis 来实现分布式锁,具备高效、可靠的特性。
1.2 Redisson分布式锁的原理
Redisson 的分布式锁主要依赖 Redis 的 SETNX
和 EXPIRE
命令来实现。流程如下:
-
获取锁:客户端通过
SETNX
(SET if Not eXists)命令尝试在 Redis 中设置一个键。如果该键不存在,表示没有其他进程持有锁,当前进程即可成功获取锁。 -
锁过期时间:为了避免某个持有锁的进程崩溃而导致锁无法释放,通常会为锁设置一个过期时间(如10秒)。如果超过这个时间锁还没有被释放,Redis 将自动删除该锁,允许其他进程获取。
-
释放锁:当任务完成后,进程会通过
DEL
命令来释放锁,其他进程就可以重新获取锁。 -
可重入锁:Redisson 提供了可重入锁,即同一个线程可以多次获取锁,而不会被锁定阻塞。只有当线程完全释放锁后,其他线程才能获取该锁。
1.3 Redisson分布式锁的优势
- 高效:Redis 基于内存操作,具有极快的响应速度。Redisson 使用 Lua 脚本将获取和释放锁的操作进行原子化操作,避免并发问题。
- 可靠性:Redisson 通过 Redis 的过期机制和 Watchdog(看门狗)机制,确保锁可以自动释放,防止因进程异常退出导致的死锁问题。
- 可扩展性:Redisson 支持 Redis 集群、哨兵模式等多种模式,适用于不同规模的分布式系统。
1.4 Redisson分布式锁的应用场景
-
库存扣减:在电商系统中,当用户发起购买请求时,需要确保在多个并发请求中,库存只能被扣减一次,避免超卖现象。
-
任务调度:在分布式任务调度系统中,需要保证同一时间只有一个服务实例执行某个任务,防止重复执行。
-
分布式事务:在分布式事务中,确保在多个服务之间的一致性操作,分布式锁能够确保只有一个服务能修改某个共享资源。
二 案例
2.1 锁竞争案例
假设我有两个节点可以执行同一种业务,我需求是节点1执行的时候,节点2不能执行。那么就可以使用分布式锁实现,代码如下
引入redisson的依赖
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.35.0</version></dependency>
编一个redisson客户端
public class RedissonConfig {public RedissonClient redissonClient() {Config config = new Config();config.useSingleServer().setAddress("redis://192.168.1.47:6379").setPassword("xxxx");return Redisson.create(config);}
}
节点1
package org.example.demo;
import org.example.tool.RedissonConfig;
import org.redisson.api.RKeys;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/*** @Author chenyunzhi* @DATE 2024/9/3 10:01* @Description:*/
public class demo1 {public static void main(String[] args) throws InterruptedException {RedissonConfig redissonConfig = new RedissonConfig();RedissonClient redissonClient = redissonConfig.redissonClient();int i = 0;Thread.sleep(2000);while (i < 5) {try {Date currentDate = new Date();System.out.println("当前时间: " + currentDate);RLock testLock = redissonClient.getLock("testLock");//尝试获取锁 waitTime(重试等待时间),leaseTime(过期时间),TimeUnit(时间单位)boolean b = testLock.tryLock(1, 5, TimeUnit.SECONDS);i++;if (b) {try {Thread.sleep(2000);System.out.println("执行业务" + i + "次 节点1");} finally {testLock.unlock();}} else {System.out.println("获取锁失败 节点1");}} catch (Exception e) {System.out.println("锁中断 节点1" + e.getMessage());}}}
}
节点1完成业务的速度大约2秒钟,循环执行5次任务,如果获取锁失败就不执行,进入下一次执行
节点2
package org.example.demo;
import org.example.tool.RedissonConfig;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/*** @Author chenyunzhi* @DATE 2024/9/3 10:01* @Description:*/
public class demo2 {public static void main(String[] args) throws InterruptedException {RedissonConfig redissonConfig = new RedissonConfig();RedissonClient redissonClient = redissonConfig.redissonClient();int i = 0;while (i < 5) {try {Date currentDate = new Date();System.out.println("当前时间: " + currentDate);RLock testLock = redissonClient.getLock("testLock");//尝试获取锁 waitTime(重试等待时间),leaseTime(过期时间),TimeUnit(时间单位)boolean b = testLock.tryLock(1, 10, TimeUnit.SECONDS);i++;if (b) {try {Thread.sleep(1000);System.out.println("执行业务" + i + "次 节点2");} finally {testLock.unlock();}} else {System.out.println("获取锁失败 节点2");}} catch (Exception e) {System.out.println("锁中断 节点2" + e.getMessage());}}}
}
节点2完成业务的速度大约1秒钟,循环执行5次任务,如果获取锁失败就不执行,进入下一次执行
然后我们同时允许两个节点行测试
通过上面测试可以发现,在节点1执行业务的时候,节点2获取锁失败了,然后无法执行业务,反之也是如此
2.2 看门狗案例
上面的案例我们为了防止任务死锁,都会给锁都设定了有效时间,可是我们不确定这个任务要执行多久,就会导致任务还没执行完成,锁就先过期了。watchDog(看门狗)的作用是可以确保等待某个节点任务完全执行完成后才去释放锁。
redisson的看门狗底层使用的是setnx加lua脚本实现的,会定期给锁续约,默认是每隔10s续期一次,一次续约30s,其他线程在最大等待时间内自旋,不断尝试获取锁,超过最大等待时间则获取锁失败,设置默认加锁时间的参数是 lockWatchdogTimeout,会和主线程一起销毁。。
注意:
- 看门狗只会在锁没设定过期时间的时候才有效
- 如果任务一直阻塞,那么锁就会一直续期,得不到释放
package org.example.demo;import org.example.tool.RedissonConfig;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;import java.util.concurrent.TimeUnit;/*** @Author chenyunzhi* @DATE 2024/9/21 11:26* @Description:*/
public class demo3 {public static void main(String[] args) {RedissonConfig redissonConfig = new RedissonConfig();RedissonClient redissonClient = redissonConfig.redissonClient();RLock myLock = redissonClient.getLock("myLock");if (myLock.tryLock()) {try {// 模拟任务执行System.out.println("执行任务");Thread.sleep(50000); // 模拟50秒的任务System.out.println("任务完成");} catch (InterruptedException e) {e.printStackTrace();} finally {//判断当前线程是否持有锁 isHeldByCurrentThreadif (myLock.isHeldByCurrentThread()) {myLock.unlock();System.out.println("释放锁");}}}redissonClient.shutdown();}
}
使用myLock.tryLock()不设置过期时间,那么看门狗会默认启动,然后会默认设置30秒的过期时间,每10秒刷新一次过期时间。
2.3 参考文章
github: https://github.com/redisson/redisson/wiki/8.-distributed-locks-and-synchronizers
redisson中的看门狗机制总结
Redis的分布式锁
redisson watchdog 使用和原理
作者:神的孩子都在歌唱
本人博客:https://blog.csdn.net/weixin_46654114
转载说明:务必注明来源,附带本人博客连接。
相关文章:

Redisson分布式锁的概念和使用
Redisson分布式锁的概念和使用 一 简介1.1 什么是分布式锁?1.2 Redisson分布式锁的原理1.3 Redisson分布式锁的优势1.4 Redisson分布式锁的应用场景 二 案例2.1 锁竞争案例2.2 看门狗案例2.3 参考文章 前言 这是我在这个网站整理的笔记,有错误的地方请指出ÿ…...

uniapp小程序持续获取用户位置信息,后台位置获取
做一个小程序持续获取用户位置信息的功能,即使小程序切换到后台也能继续获取,getLocation这个api只有小程序在前台才能获取位置,所以不用这个 先申请一个腾讯地图key 在uniapp项目配置源码视图里加上这个代码 先获取权限,再开启…...
优化算法(五)—梯度下降算法(附MATLAB程序)
梯度下降算法(Gradient Descent)是一种常用的优化算法,用于寻找函数的局部最小值。它通过沿着函数梯度的反方向迭代地调整变量,以逐步找到最优解。梯度下降广泛应用于机器学习和深度学习中,特别是在训练模型时优化损失…...

TypeScript 设计模式之【单例模式】
文章目录 **单例模式**: 独一无二的特工我们为什么需要这样的特工?单例模式的秘密:如何培养这样的特工?特工的利与害代码实现单例模式的主要优点单例模式的主要缺点单例模式的适用场景总结 单例模式: 独一无二的特工 单例模式就像是一个秘密组织里的特殊特工。这…...
UDP与TCP那个传输更快
UDP(用户数据报协议)和 TCP(传输控制协议)是互联网协议栈中常用的两种传输层协议。它们在设计和应用上存在一些显著的差异,导致在传输速度和可靠性等方面表现不同。以下是它们之间的比较,特别是关于传输速度…...

如何把PDF样本册转换为网址链接
随着互联网的普及,将纸质或PDF格式的样本册转化为网址链接,以便于在线浏览和分享,变得越来越重要。本文将为您详细讲解如何将PDF样本册转换为网址链接,让您轻松实现线上展示和分享。 一、了解PDF样本册与网址链接 1. PDF样本册…...
centos7 semanage 离线安装 SELinux
centos7 semanage 离线安装 还是参考一下 换成阿里云的源 之后 ,在线更新不,不要用离线安装 centos7 更新 yum源 为 阿里云 LTS https://blog.csdn.net/wowocpp/article/details/142517908 CentOS7安装时使用"基础服务器"选项安装, 后发现没…...

磨具生产制造9人共用一台工作站
随着技术的不断进步与工业自动化的深入发展,如何优化生产流程、提高设备利用率成为了众多企业面临的重大课题。那么在磨具生产制造中实现9人共用一台工作站呢? 一、背景与挑战 在磨具制造行业,高精度、高效率的生产要求与复杂多变的工艺流程…...

Qt clicked()、clicked(bool)、toggled(bool)信号的区别和联系
clicked() 信号 所属控件:clicked()信号是QAbstractButton类(及其子类,如QPushButton、QRadioButton、QCheckBox等)的一个信号。clicked信号可以说是许多控件(特别是按钮类控件,如QPushButton)…...
nginx实现负载均衡的分发策略
文章目录 分发策略 分发策略 轮询策略 轮询策略是最简单的负载均衡策略之一。Nginx 默认采用轮询方式将请求分发到不同的后端服务器。它将请求按照顺序轮流分配给每个后端服务器,不论服务器当前的负载情况如何。这种策略适合后端服务器性能相近且无太大差异的场景。…...
【Python】用代码片段掌握Python核心功能
探索各种用户输入值 Python 是一种多才多艺的编程语言,广泛应用于从 Web 开发到数据分析的各种场景。这篇文章将通过实际的代码片段带你了解 Python 中的几个基本概念和操作。无论你是初学者还是想重温一下知识点,这些例子都会给你带来宝贵的见解。 输…...

JVM 内存模型
JVM 内存模型 对于 Java 程序员来说,在虚拟机自动内存管理机制下,不再需要像 C/C程序开发程序员这样为每一个 new 操作去写对应的 delete/free 操作,不容易出现内存泄漏和内存溢出问题。正是因为 Java程序把内存控制权利交给 JVM 虚拟机。一旦出现内存泄漏和溢出方面的问题,如果…...
Linux2.6* 内核默认支持的文件系统
Linux2.6* 内核默认支持的文件系统 Btrfs是一种具有先进特性的写时复制文件系统。支持多种高级功能,如快照、透明压缩、数据校验和自我修复等,适用于大规模存储系统和数据可靠性要求较高的场景。JFSJournaled File System日志文件系统,具有高…...

PMP--二模--解题--111-120
文章目录 7.成本管理111、 [单选] 你向项目出资人提供了项目的成本估算,他对估算不满意,因为他认为价格太高了。他要你削减项目估算的15%,你该怎么做? 8.质量管理112、 [单选] 在新建水处理厂的建设过程中,政府对处理厂…...

idea 创建多模块项目
一、新建项目,创建父工程 新建项目,选择 spring initializr 填写相关信息后提交 删除不相关的目录,如下 修改打包方式为 pom,在 pom.xml 文件中新增一行,如下 二、创建子模块 新增子模块 三、修改 pom 文件 修…...

redis Redis-Cluster常用命令与Redis性能监控
起因:随着项目的进一步推广,数据量的增大,直接访问mysql数据库获取数据所使用的时间越来越长,为解决当前主要矛盾,决定引入redis非关系型数据库作为缓存层,使得数据并不能直接命中数据库,减少访…...
《C++中的随机数生成器:探索随机之美》
在 C编程的世界里,随机数生成器是一个非常重要的工具,它在众多领域都有着广泛的应用,从游戏开发中的随机事件触发,到模拟实验中的随机数据生成,再到密码学中的安全随机数需求,随机数生成器都扮演着关键的角…...

为什么推荐使用英文版LabVIEW
在LabVIEW开发中,中文版和英文版主要在界面语言、功能习惯以及社区支持等方面存在差异。以下是两者的特点以及推荐使用英文版的原因: 中文版特点: 界面和帮助文档为中文:对于中文母语开发者来说,中文版LabVIEW的界面和…...
【Moveit2】move_group_interface_tutorial中文注释
move_group_interface_tutorial #include <moveit/move_group_interface/move_group_interface.h> // 包含MoveIt的移动组接口 #include <moveit/planning_scene_interface/planning_scene_interface.h> // 包含规划场景接口#include <moveit_msgs/msg/display…...
JavaScript window的open和close用法
在JavaScript中,window.open() 和 window.close() 方法分别用于打开和关闭浏览器窗口或标签页。以下是这两个方法的基本用法: window.open() window.open() 方法可以接受四个参数: URL:要打开的网页的地址。如果省略这个参…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...

【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...