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

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 的 SETNXEXPIRE 命令来实现。流程如下:

  1. 获取锁:客户端通过 SETNX(SET if Not eXists)命令尝试在 Redis 中设置一个键。如果该键不存在,表示没有其他进程持有锁,当前进程即可成功获取锁。

  2. 锁过期时间:为了避免某个持有锁的进程崩溃而导致锁无法释放,通常会为锁设置一个过期时间(如10秒)。如果超过这个时间锁还没有被释放,Redis 将自动删除该锁,允许其他进程获取。

  3. 释放锁:当任务完成后,进程会通过 DEL 命令来释放锁,其他进程就可以重新获取锁。

  4. 可重入锁:Redisson 提供了可重入锁,即同一个线程可以多次获取锁,而不会被锁定阻塞。只有当线程完全释放锁后,其他线程才能获取该锁。

1.3 Redisson分布式锁的优势

  • 高效:Redis 基于内存操作,具有极快的响应速度。Redisson 使用 Lua 脚本将获取和释放锁的操作进行原子化操作,避免并发问题。
  • 可靠性:Redisson 通过 Redis 的过期机制和 Watchdog(看门狗)机制,确保锁可以自动释放,防止因进程异常退出导致的死锁问题。
  • 可扩展性:Redisson 支持 Redis 集群、哨兵模式等多种模式,适用于不同规模的分布式系统。

1.4 Redisson分布式锁的应用场景

  1. 库存扣减:在电商系统中,当用户发起购买请求时,需要确保在多个并发请求中,库存只能被扣减一次,避免超卖现象。

  2. 任务调度:在分布式任务调度系统中,需要保证同一时间只有一个服务实例执行某个任务,防止重复执行。

  3. 分布式事务:在分布式事务中,确保在多个服务之间的一致性操作,分布式锁能够确保只有一个服务能修改某个共享资源。

二 案例

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次任务,如果获取锁失败就不执行,进入下一次执行

然后我们同时允许两个节点行测试

image-20240921112219730

image-20240921112248761

通过上面测试可以发现,在节点1执行业务的时候,节点2获取锁失败了,然后无法执行业务,反之也是如此

2.2 看门狗案例

上面的案例我们为了防止任务死锁,都会给锁都设定了有效时间,可是我们不确定这个任务要执行多久,就会导致任务还没执行完成,锁就先过期了。watchDog(看门狗)的作用是可以确保等待某个节点任务完全执行完成后才去释放锁。

redisson的看门狗底层使用的是setnx加lua脚本实现的,会定期给锁续约,默认是每隔10s续期一次,一次续约30s,其他线程在最大等待时间内自旋,不断尝试获取锁,超过最大等待时间则获取锁失败,设置默认加锁时间的参数是 lockWatchdogTimeout,会和主线程一起销毁。。

注意

  1. 看门狗只会在锁没设定过期时间的时候才有效
  2. 如果任务一直阻塞,那么锁就会一直续期,得不到释放

image-20240921155226569

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

转载说明:务必注明来源,附带本人博客连接。

http://www.lryc.cn/news/446558.html

相关文章:

  • uniapp小程序持续获取用户位置信息,后台位置获取
  • 优化算法(五)—梯度下降算法(附MATLAB程序)
  • TypeScript 设计模式之【单例模式】
  • UDP与TCP那个传输更快
  • 如何把PDF样本册转换为网址链接
  • centos7 semanage 离线安装 SELinux
  • 磨具生产制造9人共用一台工作站
  • Qt clicked()、clicked(bool)、toggled(bool)信号的区别和联系
  • nginx实现负载均衡的分发策略
  • 【Python】用代码片段掌握Python核心功能
  • JVM 内存模型
  • Linux2.6* 内核默认支持的文件系统
  • PMP--二模--解题--111-120
  • idea 创建多模块项目
  • redis Redis-Cluster常用命令与Redis性能监控
  • 《C++中的随机数生成器:探索随机之美》
  • 为什么推荐使用英文版LabVIEW
  • 【Moveit2】move_group_interface_tutorial中文注释
  • JavaScript window的open和close用法
  • 经典sql题(十四)炸裂函数的恢复
  • 【vue2】组件写法
  • 5G 扬帆新质跃,技术蝶变开新篇-第七届“绽放杯”5G应用征集大赛 5G应用融合技术专题赛圆满收官
  • 3d gaussian splatting公式推导
  • 金属增材制造咋突破?纳米纹理粉末如何助力金属增材制造?
  • openpnp - 为了防止物料操作混乱,做一张物料分布位置图清晰一些
  • 懒人帮美食系统小程序的设计
  • David律所代理Jose Martin幽默水果版权首发维权,尚未TRO
  • 读构建可扩展分布式系统:方法与实践15可扩展系统的基本要素
  • 解决VisualStudio msvsmon.exe远程调试器未启动问题
  • 如果淘汰是注定的,那么读书还有意义吗?