基于Redisson实现重入锁
一. 分布式锁基础
在分布式系统中,当多个客户端(应用实例)需要访问同一资源时,可以使用分布式锁来确保同一时刻只有一个客户端能访问该资源。Redis作为高性能的内存数据库,提供了基于键值对的分布式锁实现,通常采用SETNX命令(即SET if Not eXists)来设置锁。
Redis的分布式锁大致实现流程如下:
- 客户端请求获取锁:通过
SETNX命令设置一个锁键(如lock:<resource>)。 - 锁被设置成功时,客户端可以访问资源;否则,它会等待或返回获取失败的结果。
- 客户端在完成工作后,释放锁:通过
DEL命令删除锁键。
二. 可重入锁
在一个线程或进程中,如果该线程/进程已经获取了锁,那么它可以重复获取该锁,而不会发生死锁问题。也就是说,同一线程/进程可以多次获取锁,而每次释放锁时都需要释放一次,直到所有的锁请求都被释放。
对于分布式系统中的可重入锁,它确保:
- 当一个客户端(通常是线程或进程)已经持有锁时,它可以继续请求该锁而不会被阻塞或进入死锁。
- 锁的计数是线程级别的,客户端每次请求锁时都需要将锁的计数增加,释放锁时则减少计数,直到计数为零时才完全释放锁。
三. Redis实现可重入锁的步骤
1. 使用SET命令(或SETNX命令)来获取锁
- 锁是由一个特定的Redis键(例如,
lock:<resource>)表示的。 - 锁的值通常是一个标识符,例如,客户端的
UUID,或者一个线程标识符。这个值用于确保同一个客户端可以重复获取锁。
2. 记录锁的持有者
- 当客户端请求锁时,它不仅设置一个标识该锁的键(如
lock:<resource>),而且还设置该锁的值(如UUID)。这样,如果该锁已经存在且值不是当前客户端的标识符,则客户端无法获得锁。
3. 锁的可重入性
- 在可重入锁中,客户端获取锁时,如果该客户端的标识符(如
UUID)已经在锁值中,则客户端可以继续获取锁,并且需要将锁的“持有次数”增加。 - 可以通过键值对的计数来实现这一点。每次客户端请求锁时,Redis可以增加锁的计数。当客户端释放锁时,Redis会减少锁的计数。
4. 锁的过期时间
- 为了防止死锁,Redis的锁通常会设置一个过期时间,通常是
SET命令的EX选项(设置过期时间)。这样,如果客户端在持有锁的过程中发生故障,锁会在一定时间后自动释放。 - 可重入锁的一个实现方式是,客户端在每次获取锁时刷新过期时间,确保锁在可重入期间不会过期。
5. 释放锁
- 当客户端完成工作后,它会释放锁。每次释放锁时,它会检查当前的锁计数:
- 如果锁计数大于1,表示该客户端还需要继续持有锁,于是减少计数。
- 如果锁计数为1,则客户端完全释放锁,通过删除锁键(如
DEL)来释放该资源。
四 LUA 脚本实现简单重入锁

获取锁的 Lua 脚本:
local key = KEYS[1]; -- 锁的key
local threadId = ARGV[1]; -- 线程唯一标识
local releaseTime = ARGV[2]; -- 锁的自动释放时间-- 判断是否存在
if (redis.call('EXISTS', key) == 0) then-- 不存在,获取锁redis.call('HSET', key, threadId, '1');-- 设置有效期redis.call('EXPIRE', key, releaseTime);return 1; -- 返回结果
end;-- 锁已经存在,判断threadId是否是自己
if (redis.call('HEXISTS', key, threadId) == 1) then-- 是自己,获取锁,重入次数+1redis.call('HINCRBY', key, threadId, '1');-- 设置有效期redis.call('EXPIRE', key, releaseTime);return 1; -- 返回结果
end;return 0; -- 代码走到这里,说明获取锁的不是自己,获取锁失败
释放锁的 Lua 脚本:
local key = KEYS[1]; -- 锁的key
local threadId = ARGV[1]; -- 线程唯一标识
local releaseTime = ARGV[2]; -- 锁的自动释放时间-- 判断当前锁是否还是被自己持有
if (redis.call('HEXISTS', key, threadId) == 0) thenreturn nil; -- 如果已经不是自己,则直接返回
end;-- 是自己的锁,则重入次数减1
local count = redis.call('HINCRBY', key, threadId, -1);-- 判断是否重入次数是否已经为0
if (count > 0) then-- 大于0说明不能释放锁,重置有效期然后返回redis.call('EXPIRE', key, releaseTime);return nil;
else-- 等于0说明可以释放锁,直接删除redis.call('DEL', key);return nil;
end;
相关文章:
基于Redisson实现重入锁
一. 分布式锁基础 在分布式系统中,当多个客户端(应用实例)需要访问同一资源时,可以使用分布式锁来确保同一时刻只有一个客户端能访问该资源。Redis作为高性能的内存数据库,提供了基于键值对的分布式锁实现,…...
Java文件操作的简单示例
使用原生库 创建空白文件 package com.company; import java.io.File; import java.io.IOException;public class Main {public static void main(String[] args) {File f new File("newfile.txt");try {boolean flag f.createNewFile();System.out.println(&quo…...
删除与增加特定行
1.删除特定行 new_df <- df[-c(4), ] #删除第4行 new_df <- df[-c(2:4), ] #去除第2-4行 new_df <- subset(df, col1 < 10 & col2 < 6) #删除特定第一列<10和第二列<6的行。按名字删除 无论行列,可以找出对应索引或构造相同长…...
动态规划六——两个数组的dp问题
目录 题目一——1143. 最长公共子序列 - 力扣(LeetCode) 题目二——1035. 不相交的线 - 力扣(LeetCode) 题目三——115. 不同的子序列 - 力扣(LeetCode) 题目四—— 44. 通配符匹配 - 力扣(…...
项目优化之策略模式
目录 策略模式基本概念 策略模式的应用场景 实际项目中具体应用 项目背景: 策略模式解决方案: 计费模块策略模式简要代码 策略模式基本概念 策略模式(Strategy Pattern) 是一种行为型设计模式,把算法的使用放到环境类中,而算…...
[读书日志]从零开始学习Chisel 第四篇:Scala面向对象编程——操作符即方法(敏捷硬件开发语言Chisel与数字系统设计)
3.2操作符即方法 3.2.1操作符在Scala中的解释 在其它语言中,定义了一些基本的类型,但这些类型并不是我们在面向对象中所说的类。比如说1,这是一个int类型常量,但不能说它是int类型的对象。针对这些数据类型,存在一些…...
三子棋游戏
目录 1.创建项目 2.主函数编写 3.菜单函数编写 4.宏定义棋盘行和列 5.棋盘初始化 6.打印棋盘 7.玩家下棋 8.电脑下棋 9.平局判断 10.输赢判断 11.game函数 三子棋游戏(通过改变宏定义可以变成五子棋),玩家与电脑下棋 1.创建项目…...
MyBatis执行一条sql语句的流程(源码解析)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 MyBatis执行一条sql语句的流程(源码解析) MyBatis执行sql语句的流程加载配置文件加载配置文件的流程 创建sqlsessionFactory对象解析Mapper创建sqlses…...
【电机控制】低通滤波器及系数配置
【电机控制】低通滤波器及系数配置 文章目录 [TOC](文章目录) 前言一、低通滤波器原理二、理论计算三、代码四、参考资料总结 前言 提示:以下是本篇文章正文内容,下面案例可供参考 一、低通滤波器原理 二、理论计算 三、代码 //低通滤波 pv->Ealpha…...
ArcgisServer过了元旦忽然用不了了?许可过期
昨天过完元旦之后上班发现好多ArcgisServer的站点运行出错了,点击日志发现,说是许可过去,也就是当时安装ArcgisServer时读取的ecp文件过期了,需要重新读取。 解决方法 1.临时方法,修改系统时间,早于2024年…...
如何在不丢失数据的情况下从 IOS 14 回滚到 IOS 13
您是否后悔在 iPhone、iPad 或 iPod touch 上安装 iOS 14?如果你这样做,你并不孤单。许多升级到 iOS 14 beta 的 iPhone、iPad 和 iPod touch 用户不再适应它。 如果您在正式发布日期之前升级到 iOS 14 以享受其功能,但您不再适应 iOS 14&am…...
【算法刷题】链表
文章目录 环形链表判断是否有环找出环的入口位置 双指针反转链表(Reverse a Linked List)移除链表中的指定元素(Remove Linked List Elements) 环形链表 判断是否有环 环形链表是指链表中的某些节点的 next 指针指向了链表中的某…...
计算机网络 —— 网络编程实操(1)(UDP)
计算机网络 —— 网络编程实操(UDP) 套接字端口套接字的定义为什么需要套接字? 套接字的分类1. 按照通信协议分类2. 按照地址族(Address Family)分类3. 按照通信模式分类 socket APIsockaddr结构 使用接口套接字初始化…...
selenium 确保页面完全加载
在使用Python和Selenium进行Web自动化时,确保页面完全加载是非常重要的。为了实现这一点,Selenium提供了两种主要类型的等待:显式等待(Explicit Waits)和隐式等待(Implicit Waits)。此外&#x…...
[极客大挑战 2019]HardSQL 1
看了大佬的wp,没用字典爆破,手动试出来的,屏蔽了常用的关键字,例如:order select union and 最搞的是,空格也有,这个空格后面让我看了好久,该在哪里加括号。 先传入1’ 1试试&#…...
vip与haproxy构建nginx高可用集群传递客户端真实ip
问题 系统使用了vip与haproxy实现高可用以及对nginx进行负载均衡,但是发现在上游的应用服务无法拿到客户端的请求ip地址,拿到的是主haproxy机器的ip,以下是nginx与haproxy的缩减配置: location ~* ^/(xx|xx) {proxy_pass http:/…...
Easticsearch介绍|实战?
Elasticsearch 是一个分布式的、RESTful 风格的搜索和数据分析引擎,适用于各种用例,如日志分析、全文搜索、实时应用监控等。它设计用来处理大量数据,并且可以快速地提供相关的搜索结果。以下是一些 Elasticsearch 的实战应用场景以及如何在这…...
Python图形界面(GUI)Tkinter笔记(二十一):Messagebox信息提示功能控件
messagebox 就像是 tkinter 库里的一个好帮手,它能帮你弹出各种各样的消息框给用户看。这些消息框可以告诉用户很多东西,比如提示、警告或者错误信息之类的。在 tkinter 库里,messagebox 这个模块有很多不同的函数,每个函数都能弹出一种特定的消息框。用这些函数,开发者可…...
vue3+ts+element-plus 表单el-form取消回车默认提交
问题描述:在表单el-form中的el-input中按回车后,页面会刷新,url也会改变, 回车前: 回车后: 相关代码: 解决方法1:在 el-form 上阻止默认的 submit 事件,增加 submit.pre…...
Web Services 简介
Web Services 简介 1. 引言 Web Services 是一种基于网络的软件服务,它允许不同的应用程序在互联网上相互通信和交互。这种技术是基于开放的互联网标准,如HTTP、XML、SOAP和WSDL,使得不同平台和编程语言的应用程序能够轻松地实现互操作性。Web Services 的出现,极大地推动…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
