RedLock + Redisson
目录
- 2.9 RedLock
- 2.9.1 上述实现的分布式锁在集群状态下失效的原因
- 2.9.2 解决方式-RedLock
- 2.10 ==redisson中的分布式锁==
- 2.10.0 redisson简介以及简单使用
- 简单使用redisson中的锁
- Redisson常用配置
- 2.10.1 Redisson可重入锁实现原理
- 2.10.2 公平锁(Fair Lock)
- 2.10.3 联锁(MultiLock) (没用 !!!!)
- 2.10.4 红锁(RedLock)
- 2.10.5 读写锁(ReadWriteLock)
- 2.10.6 ==信号量(Semaphore)==
- 2.10.7 ==闭锁==(CountDownLatch)
2.9 RedLock
2.9.1 上述实现的分布式锁在集群状态下失效的原因
redis集群状态下的问题:
- 客户端A从master获取到锁
- 在master将锁同步到slave之前,master宕掉了。
- slave节点被晋级为master节点
- 客户端B取得了同一个资源被客户端A已经获取到的另外一个锁。
2.9.2 解决方式-RedLock
解决集群下锁失效,参照redis官方网站针对redlock文档:https://redis.io/topics/distlock
加锁算法

2.10 redisson中的分布式锁
2.10.0 redisson简介以及简单使用
Redisson提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service)
Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。

官方文档地址:https://github.com/redisson/redisson/wiki
简单使用redisson中的锁
注入 RedissonClient 客户端
@Configuration
public class RedissonConfig {@Beanpublic RedissonClient redissonClient() {// 默认连接地址 127.0.0.1:6379Config config = new Config();config.useSingleServer().setAddress("redis://121.40.182.123:6379").setPassword("houchen");RedissonClient redisson = Redisson.create(config);return redisson;}
}
使用 RedisClient的锁。StockService 代码片段如下
public void deduct() {RLock lock = redissonClient.getLock("lock");lock.lock();try {String stockStr = redisTemplate.opsForValue().get("stock:" + "1001");// 2. 判断库存是否充足if (stockStr != null && stockStr.length() != 0) {Long stock = Long.parseLong(stockStr);if (stock > 0) {redisTemplate.opsForValue().set("stock:" + "1001", String.valueOf(stock - 1));}}} finally {lock.unlock();}}
使用 Jmeter并发压测后,查看redis的库存确实减为0,表明redisson锁是确实是可用的

Redisson常用配置

2.10.1 Redisson可重入锁实现原理
之后进行补充
可重入锁演示测试
public void deduct() {RLock lock = redissonClient.getLock("lock");lock.lock();try {String stockStr = redisTemplate.opsForValue().get("stock:" + "1001");// 2. 判断库存是否充足if (stockStr != null && stockStr.length() != 0) {Long stock = Long.parseLong(stockStr);if (stock > 0) {redisTemplate.opsForValue().set("stock:" + "1001", String.valueOf(stock - 1));}}this.test1();} finally {lock.unlock();}}private void test1() {RLock lock = redissonClient.getLock("lock");lock.lock();System.out.println("获取到可重入锁");System.out.println("执行其他业务代码......");lock.unlock();}
由演示结果可以得出结论,RLock 是可重入锁!!

2.10.2 公平锁(Fair Lock)
基于Redis的Redisson分布式可重入公平锁也是实现了java.util.concurrent.locks.Lock接口的一种RLock对象。它保证了当多个Redisson客户端线程同时请求加锁时,优先分配给先发出请求的线程。所有请求线程会在一个队列中排队,当某个线程出现宕机时,Redisson会等待5秒后继续下一个线程,也就是说如果前面有5个线程都处于等待状态,那么后面的线程会等待至少25秒。
RLock fairLock = redisson.getFairLock("anyLock");
// 最常见的使用方法
fairLock.lock();// 10秒钟以后自动解锁
// 无需调用unlock方法手动解锁
fairLock.lock(10, TimeUnit.SECONDS);// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = fairLock.tryLock(100, 10, TimeUnit.SECONDS);
fairLock.unlock();
2.10.3 联锁(MultiLock) (没用 !!!!)
基于Redis的Redisson分布式联锁RedissonMultiLock对象可以将多个RLock对象关联为一个联锁,每个RLock对象实例可以来自于不同的Redisson实例。
RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
// 同时加锁:lock1 lock2 lock3
// 所有的锁都上锁成功才算成功。
lock.lock();
...
lock.unlock();
2.10.4 红锁(RedLock)
基于Redis的Redisson红锁RedissonRedLock对象实现了 2.9 RedLock 介绍的加锁算法。该对象也可以用来将多个RLock对象关联为一个红锁,每个RLock对象实例可以来自于不同的Redisson实例。
RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
// 同时加锁:lock1 lock2 lock3
// 红锁在大部分节点上加锁成功就算成功。
lock.lock();
...
lock.unlock();
2.10.5 读写锁(ReadWriteLock)
基于Redis的Redisson分布式可重入读写锁RReadWriteLock Java对象实现了java.util.concurrent.locks.ReadWriteLock接口。其中读锁和写锁都继承了RLock接口。
分布式可重入读写锁允许同时有多个读锁和一个写锁处于加锁状态。
RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock");
// 最常见的使用方法
rwlock.readLock().lock();
// 或
rwlock.writeLock().lock();// 10秒钟以后自动解锁
// 无需调用unlock方法手动解锁
rwlock.readLock().lock(10, TimeUnit.SECONDS);
// 或
rwlock.writeLock().lock(10, TimeUnit.SECONDS);// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = rwlock.readLock().tryLock(100, 10, TimeUnit.SECONDS);
// 或
boolean res = rwlock.writeLock().tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();
添加StockController方法:
@GetMapping("test/read")
public String testRead(){String msg = stockService.testRead();return "测试读";
}@GetMapping("test/write")
public String testWrite(){String msg = stockService.testWrite();return "测试写";
}
添加StockService方法:
public String testRead() {RReadWriteLock rwLock = this.redissonClient.getReadWriteLock("rwLock");rwLock.readLock().lock(10, TimeUnit.SECONDS);System.out.println("测试读锁。。。。");// rwLock.readLock().unlock();return null;
}public String testWrite() {RReadWriteLock rwLock = this.redissonClient.getReadWriteLock("rwLock");rwLock.writeLock().lock(10, TimeUnit.SECONDS);System.out.println("测试写锁。。。。");// rwLock.writeLock().unlock();return null;
}
- 同时访问写:一个写完之后,等待一会儿(约10s),另一个写开始
- 同时访问读:不用等待
- 先写后读:读要等待(约10s)写完成
- 先读后写:写要等待(约10s)读完成
2.10.6 信号量(Semaphore)
JUC Semaphore的小小演示:
public static void main(String[] args) {Semaphore semaphore = new Semaphore(3);for (int i = 0; i < 5; i++) {new Thread(() -> {try {semaphore.acquire(1);System.out.println(Thread.currentThread().getName() + "获取到停车位");TimeUnit.SECONDS.sleep(new Random().nextInt(10));System.out.println(Thread.currentThread().getName() + "将车开走了!!!");semaphore.release();} catch (InterruptedException e) {throw new RuntimeException(e);}}, i + "号车").start();}}
可以看到任意一个时刻,最多只有三辆车能获取到停车位

基于Redis的Redisson的分布式信号量(Semaphore)Java对象RSemaphore采用了与java.util.concurrent.Semaphore相似的接口和用法。同时还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。
在StockController添加方法:
@GetMapping("test/semaphore")
public String testSemaphore(){this.stockService.testSemaphore();return "测试信号量";
}
在StockService添加方法:
public void testSemaphore() {RSemaphore semaphore = this.redissonClient.getSemaphore("semaphore");semaphore.trySetPermits(3);try {semaphore.acquire();System.out.println(Thread.currentThread().getName() + "获取了信号量资源,开始执行业务逻辑,----------> start");TimeUnit.SECONDS.sleep(new Random().nextInt(10));System.out.println(Thread.currentThread().getName() + "获取执行完了业务逻辑,释放信号量资源,----------> end");semaphore.release();} catch (InterruptedException e) {e.printStackTrace();}}

2.10.7 闭锁(CountDownLatch)
JUC CountDownLatch使用demo
CountDownLatch 适用于一个线程等待一组线程的执行完成!!!!
public static void main(String[] args) throws InterruptedException {CountDownLatch countDownLatch= new CountDownLatch(5);for (int i = 0; i < 5; i++) {new Thread(() -> {try {System.out.println(Thread.currentThread().getName() + "---> 准备出门了");TimeUnit.SECONDS.sleep(new Random().nextInt(10));System.out.println(Thread.currentThread().getName() + "---> 真真切切出门了.....");countDownLatch.countDown();} catch (InterruptedException e) {throw new RuntimeException(e);}}, i + "同学").start();}countDownLatch.await();System.out.println("班长关门了...");

基于Redisson的Redisson分布式闭锁CountDownLatch对象RCountDownLatch采用了与java.util.concurrent.CountDownLatch相似的接口和用法。
RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch");
latch.trySetCount(1);
latch.await();// 在其他线程或其他JVM里
RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch");
latch.countDown();
需要两个方法:一个等待,一个计数countDown
给StockController添加测试方法:
@GetMapping("test/latch")
public String testLatch(){this.stockService.testLatch();return "班长锁门。。。";
}@GetMapping("test/countdown")
public String testCountDown(){this.stockService.testCountDown();return "出来了一位同学";
}
给StockService添加测试方法:
public void testLatch() {RCountDownLatch latch = this.redissonClient.getCountDownLatch("latch");latch.trySetCount(6);try {latch.await();} catch (InterruptedException e) {e.printStackTrace();}
}public void testCountDown() {RCountDownLatch latch = this.redissonClient.getCountDownLatch("latch");latch.trySetCount(6);latch.countDown();
}
重启测试,打开两个页面:当第二个请求执行6次之后,第一个请求才会执行。
相关文章:
RedLock + Redisson
目录 2.9 RedLock2.9.1 上述实现的分布式锁在集群状态下失效的原因2.9.2 解决方式-RedLock 2.10 redisson中的分布式锁2.10.0 redisson简介以及简单使用简单使用redisson中的锁Redisson常用配置 2.10.1 Redisson可重入锁实现原理2.10.2 公平锁(Fair Lock)…...
计算机视觉:卷积层的参数量是多少?
本文重点 卷积核的参数量是卷积神经网络中一个重要的概念,它决定了网络的复杂度和计算量。在深度学习中,卷积操作是一种常用的操作,用于提取图像、语音等数据中的特征。卷积神经网络的优势点在于稀疏连接和权值共享,这使得卷积核的参数相较于传统的神经网络要少很多。 举例…...
Docker 容器基础操作
Docker容器基础操作 容器(container)是Docker镜像的运行实例,类似于可执行文件与进程的关系,Docker是容器引擎,相当于系统平台。 容器的生命周期 容器的基础操作(以 tomcat8.0 为例) # 拉取tomcat8.0镜像 [root@tudou tudou]# docker pull tomcat:8.0 8.0: Pulling f…...
【Vue3+Ts+Vite】配置滚动条样式
一、先看效果 二、直接上代码 <template><div class"main-container"><h1 v-for"index in 50" :key"index">这是home页面</h1></div> </template> <style lang"scss" scoped> .main-conta…...
react map使用方法详解
在React中,map()方法是用于数组的常见方法之一,它可以用于处理数组并返回一个新的数组。在React中,经常使用map()方法来遍历数组,生成对应的组件列表或进行数据转换操作。 下面是map()方法在React中的使用方法详解: …...
PoseiSwap:通过 RWA 的全新叙事,反哺 Nautilus Chain 生态
PoseiSwap 是 Nautilus Chain 上的首个 DEX,作为目前行业内模块化区块链叙事的早期奉行者,PoseiSwap 也得到了较高的市场关注。基于 Nautilus Chain,PoseiSwap 打造了一个全新的 Rollup 应用层,并通过零知识证明来建立全新的订单簿…...
PHP8的常量-PHP8知识详解
常量和变量是构成PHP程序的基础,在PHP8中常量的这一节中,主要讲到了定义常量和预定义常量两大知识点。 一、定义常量 定义常量也叫声明常量。在PHP8中,常量就是一个标识符(名字),一旦定义(声明&…...
印花税的本质和底层逻辑是什么?印花税降低是利好股市吗?
内容由LLM协助生成: 印花税是一种对特定交易或证券交易征收的税费,由政府机构收取。其本质和底层逻辑可以归结为以下几点: 资金来源:印花税是国家财政收入的一部分,用于满足政府的财政需求和公共支出。政府通过征收印花…...
pytorch+GPU跑模型时 nvrtc: error: failed to open nvrtc-builtins64_117.dll
1.先检查自己cuda版本: print(torch.version.cuda) #查看cuda版本 print(torch.cuda.is_available()) # 查看cuda是否可用 print(torch.cuda.device_count()) # 查看可行的cuda数目如果版本高于11建议先降版本,然后再试下。 2.重新安装nvrtc-builtin…...
SQL-每日一题【626.换座位】
题目 表: Seat 编写SQL查询来交换每两个连续的学生的座位号。如果学生的数量是奇数,则最后一个学生的id不交换。 按 id 升序 返回结果表。 查询结果格式如下所示。 示例 1: 解题思路 前置知识 MySQL 的 MOD() 函数是取模运算的函数,它返回两个数相除…...
Swagger之Hello World !
目录 ■1.前言・Swagger介绍 ■2.例子,如果基于Spring Boot项目,实现Swagger---非常简单 2.1.已有的SpringBoot项目 2.2.修改POM文件 2.3.添加Config文件…...
VSCode SSH远程连接与删除
1.ubuntu设置 安装SSH服务并获取远程访问的IP地址 在Ubuntu系统中,“CtrlAltT”打开终端工具,执行如下命令安装SSH服务。 sudo apt-get install openssh-server如果安装失败则先安装依赖项。 2.VS Code 设置 2.1安装与设置Remote SSH 打开Windows系…...
面试典中典之线程池的七大参数
文章目录 一、七大元素解释1.corePoolSize(核心线程数):2.maximumPoolSize(最大线程数):3.keepAliveTime(线程空闲时间):4.unit(时间单位)&#x…...
Maven如何创建Java web项目(纯干货版)!!!
1.创建Maven项目。 2.创建完成后会来到这个界面。 3.在src/main目录下,建立webapp / WEB-INF/web.xml文件,并在web.xml文件中写入以下内容: <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns"http…...
linux进程间通信的方式及特点
1:信号 描述: 信号是linux上的一种软中断通信机制,可以向指定进程发送通知,总共有64种信号; 特点: 信号只能作为通知使用,没办法传递数据; 2:socket套接字 描述&#…...
京东的成功秘诀:找到自己独特而有效的商业模式
你知道京东为什么能够从一个卖电器的小网站发展成为中国最大的电商平台吗?如果京东一开始靠卖电器赚钱,不可能有今天,在十几年刘强东刚创业的时候,如果京东靠卖电器赚钱,你知道想当年的国美黄光裕和想当年的苏宁的张近…...
全局ip代理安全吗? 手机设置全局代理方法详解
全局IP代理并不一定是安全的,因为全局IP代理会将所有网络流量都通过代理服务器进行转发,包括敏感信息和隐私数据。如果代理服务器受到黑客攻击或存在安全漏洞,可能会导致数据泄露和其他安全问题。因此,在使用全局IP代理时…...
Clion开发Stm32之温湿度传感器(DHT11)驱动编写
前言 涵盖之前文章: Clion开发STM32之HAL库GPIO宏定义封装(最新版)Clion开发stm32之微妙延迟(采用nop指令实现)Clion开发STM32之日志模块(参考RT-Thread) DHT11驱动文件 头文件 /*******************************************************************************Copyrig…...
位操作相关的函数(C++)
目录 popcount函数 bitset类模板 __builtin_popcount函数 popcount函数 在C中,std::popcount函数是用来计算一个整数二进制表示中包含的1的个数。不过要注意,这个函数是C20标准引入的,因此在使用之前,要先确保编译器支持C20标…...
arm 函数栈回溯
大概意思就是arm每个函数开始都会将PC、LR、SP以及FP四个寄存器入栈。 下面我们看一下这四个寄存器里面保存的是什么内存 arm-linux-gnueabi-gcc unwind.c -mapcs -w -g -o unwind(需要加上-mapcs才会严格按照上面说的入栈) #include <stdio.h> …...
终极指南:如何使用qmc-decoder快速解密QMC音频文件 [特殊字符]
终极指南:如何使用qmc-decoder快速解密QMC音频文件 🎵 【免费下载链接】qmc-decoder Fastest & best convert qmc 2 mp3 | flac tools 项目地址: https://gitcode.com/gh_mirrors/qm/qmc-decoder qmc-decoder是一款专为QQ音乐用户设计的QMC音…...
【测试】一文读懂软件测试:新手真正需要的测试认知
📌 相关专栏 【Linux专栏】【C语言专栏】【测试专栏】 📌 相关文章推荐 【Linux】网络基础2---Socket编程预备【Linux 】网络基础1 哈喽~欢迎来到千余的小天地 ❤ 我会分享很多干货/日常,点个关注不迷路哦~ 👍 点赞 ⭐ 收藏 &…...
从游戏主机到云端:如何用Sunshine打造你的私人游戏串流服务器
从游戏主机到云端:如何用Sunshine打造你的私人游戏串流服务器 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 你是否曾经想过,在客厅的电视上玩电脑游戏&am…...
PTFE材料在多领域的创新应用与发展分析
PTFE材料在生活领域的独特贡献不粘锅技术的演变与PTFE应用不粘锅的问世大大推动了厨房烹饪的便利性,而PTFE材料在其中扮演了关键角色。随着科技的发展,我们见证了PTFE涂层技术的不断创新,早期的传统不粘锅被更为耐磨、不易脱落的新型PTFE涂层…...
TikTok广告账号被封怎么解决?2026年防封号完整攻略
做TikTok广告投放,最让人头疼的事情是什么?账号被封。前一秒还在跑量,后一秒突然提示账号异常,所有广告计划全部暂停,预算打水漂,客户推广计划全乱。这种经历,做过TikTok广告投放的卖家应该都不…...
基于RA4M2的便携GPS定位器开发:从硬件选型到低功耗优化全解析
1. 项目概述与核心价值最近在做一个挺有意思的小玩意儿,用瑞萨的RA4M2-SENSOR开发板,折腾出了一个巴掌大小的便携式GPS定位器。这玩意儿听起来好像没啥新鲜的,市面上成品一大堆,但自己从头到尾搭一遍,从选型、画板、写…...
25款经典老芯片回顾:从运放、逻辑门到MCU,重温电子工程基石
1. 引言:一场跨越时代的芯片“认亲大会”最近在整理工作室的旧物料箱,翻出了一堆尘封已久的芯片,从布满灰尘的DIP封装到早已停产的早期逻辑门,每一片都像一张泛黄的老照片,记录着电子工业发展的一个脚印。我随手拍了几…...
LEFT JOIN 中 ON 与 WHERE 过滤的差异
在 MySQL 数据库开发中,LEFT JOIN(左外连接)是一个最常被误用的语法。许多开发者往往习惯性地将所有过滤条件一股脑地往 ON 后面塞,或者为了排版好看将条件全部扔到 WREHRE 里面。 这种模糊的逻辑在普通内连接(INNER J…...
CANN-ATB多卡推理-昇腾NPU上Llama70B怎么切到8张卡
CANN-ATB多卡推理-昇腾NPU上Llama70B怎么切到8张卡 Llama2-70B 的权重 140GB,单张 Atlas 800I A2 的 64GB 显存放不下。ATB 的多卡推理用 Tensor Parallel 把模型切到多张 NPU 上,每张卡只存 1/N 的权重和 KV Cache。 Tensor Parallel 的切法 Llama2-70B…...
Rust技术周刊 2026年第16周
阅读原文: https://mp.weixin.qq.com/s/9en-gxsNB544aG6hgkwJVQ 本周 Rust 生态亮点:GPU 计算突破(KAIO 达 cuBLAS 92.5%、flodl 多 GPU 训练),Tokio 异步优化实战频出,扩展标准库路线图发布,Rust 进入 Pix…...
