基于Redisson实现重入锁

news2025/1/10 19:36:57

一. 分布式锁基础

在分布式系统中,当多个客户端(应用实例)需要访问同一资源时,可以使用分布式锁来确保同一时刻只有一个客户端能访问该资源。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
    -- 是自己,获取锁,重入次数+1
    redis.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) then
    return 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;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2274516.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

React中createRoot函数原理解读——Element对象与Fiber对象、FiberRootNode与HostRootNode

【2024最新版】React18 核心源码分析教程&#xff08;全61集&#xff09; Element对象与Fiber对象 在 React 中&#xff0c;Element 对象 和 Fiber 对象 是核心概念&#xff0c;用于实现 React 的高效渲染和更新机制。以下是它们的详细解读&#xff1a; 1. Element 对象 定…

急速了解什么是GPU服务器

GPU服务器是一种专门配置了高性能图形处理器&#xff08;GPU&#xff09;的服务器&#xff0c;旨在提供高性能计算、深度学习、科学计算等多种场景的计算服务。与传统的CPU服务器相比&#xff0c;GPU服务器在处理并行密集型计算任务时具有显著优势。本文将详细介绍GPU服务器的定…

一.MySQL程序简介

整体介绍 1.服务端mysqld(可执行文件) mysqld --verbose --help 2.客户端mysql(可执行文件) 3.其它工具包程序

腾讯云AI代码助手编程挑战赛-凯撒密码解码编码器

作品简介 在CTFer选手比赛做crypto的题目时&#xff0c;一些题目需要自己去解密&#xff0c;但是解密的工具大部分在线上&#xff0c;而在比赛过程中大部分又是无网环境&#xff0c;所以根据要求做了这个工具 技术架构 python语言的tk库来完成的GUI页面设计&#xff0c;通过…

深度学习第三弹:python入门与线性表示代码

一、python入门 1.熟悉基础数据结构——整型数据&#xff0c;浮点型数据&#xff0c;列表&#xff0c;字典&#xff0c;字符串&#xff1b;了解列表及字典的切片&#xff0c;插入&#xff0c;删除操作。 list1 [1, 2, 3, 4, 5] for each in list1:print(each) print(list1[1…

常见的端口号大全,2025年整理

端口号是网络通信的基础&#xff0c;它定义了不同服务的入口和出口。了解服务端口号不仅有助于网络配置&#xff0c;还能提升问题排查效率。在实际应用中&#xff0c;熟悉常见端口号可以帮助你快速定位网络故障、优化服务性能&#xff0c;并确保网络安全。 一、常见的网络服务…

Android adb shell GPU信息

Android adb shell GPU信息 先 adb shell 进入控制台。 然后&#xff1a; dumpsys | grep GLES Android adb shell命令捕获systemtrace_android 抓trace-CSDN博客文章浏览阅读2.5k次&#xff0c;点赞2次&#xff0c;收藏8次。本文介绍了如何使用adbshell命令配合perfetto工…

【LeetCode】力扣刷题热题100道(21-25题)附源码 接雨水 合并区间 字母异位词 滑动窗口 覆盖子串(C++)

目录 1.接雨水 2.合井区间 3.找到字符串中所有字母异位词 4.滑动窗口最大值 5.最小覆盖子串 1.接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 代码如下所示&#xff1a; class Solution {…

01-51单片机LED与独立按键

一、单片机概述 注意&#xff1a;个人学习笔记&#xff0c;里面涉及到的C语言和进程转换相关的知识在C语言部分已经写了&#xff0c;这里是默认都会的状态学习单片机。 1.什么是单片机 单片机&#xff0c;英文Micro Controller Unit&#xff0c;简称MCU。其内部集成了CPU、R…

Linux内核编程(二十一)USB应用及驱动开发

一、基础知识 1. USB接口是什么&#xff1f; USB接口&#xff08;Universal Serial Bus&#xff09;是一种通用串行总线&#xff0c;广泛使用的接口标准&#xff0c;主要用于连接计算机与外围设备&#xff08;如键盘、鼠标、打印机、存储设备等&#xff09;之间的数据传输和电…

ModelScope创空间使用

文章目录 前言 一、ModelScope是什么&#xff1f; 二、使用步骤 1.注册ModelScope 2.新建创空间 3.创空间基本说明 4.部署创空间 5.访问创空间 三、其他补充说明 总结 前言 随着AI大模型的应用越来越广泛&#xff0c;模型应用部署的需求也越来越多&#xff0c;包括h…

记1(监督学习+一元线性回归

目录 1、基础概念2、一元线性回归 1、基础概念 机器学习&#xff08;Machine Learning&#xff09;&#xff1a;通过学习算法从数据中学习模型的过程 例如从“房价y~面积x”的关系中学习&#xff1a; 建立模型&#xff1a;ywxb 学习模型&#xff1a;确定w&#xff0c;b&#x…

服务器双网卡NCCL通过交换机通信

1、NCCL变量设置 export CUDA_DEVICE_MAX_CONNECTIONS1 export NCCL_SOCKET_IFNAMEeno2 export NCCL_IB_DISABLE0 #export NCCL_NETIB export NCCL_IB_HCAmlx5_0,mlx5_1 export NCCL_IB_GID_INDEX3 export NCCL_DEBUGINFOGPUS_PER_NODE4MASTER_ADDR192.168.1.2 MASTER_PORT600…

PySide6 Qt for Python Qt Quick参考网址

Qt QML BOOK&#xff1a; 《Qt for Python》 -Building an Application https://www.qt.io/product/qt6/qml-book/ch19-python-build-app#signals-and-slots Qt for Python&#xff1a;与C版本的差异即BUG处理&#xff08;常见的DLL文件确实的问题等&#xff09; Qt for Pyt…

NineData云原生智能数据管理平台新功能发布|2024年12月版

本月发布 7 项更新&#xff0c;其中重点发布 2 项、功能优化 5 项。 重点发布 数据库 Devops - Oracle 非表对象支持可视化创建与管理 Oracle 非表对象&#xff0c;包括视图&#xff08;View&#xff09;、包&#xff08;Package&#xff09;、存储过程&#xff08;Procedur…

【Elasticsearch7.11】postman批量导入少量数据

JSON 文件内的数据格式&#xff0c;json文件数据条数不要过多&#xff0c;会请求参数过大&#xff0c;最好控制再10000以内。 {"index":{"_id":"baec07466732902d22a24ba01ff09751"}} {"uuid":"baec07466732902d22a24ba01ff0975…

用Kimi做研究:准实验设计的智能解决方案

目录 1.研究策略设计 2.过程框架设计 3.背景变量 4.细节设计 准实验设计是一种介于实验与观察研究之间的研究方法&#xff0c;准实验设计是在无法完全控制实验条件的情况下进行因果关系的探索。与传统实验设计相比&#xff0c;准实验设计不具备随机分配实验对象到各处理组的…

零基础入门Erlang

1.Erlang介绍 Index - Erlang/OTP Erlang是一种通用的面向并发的编程语言 Erlang是一个结构化&#xff0c;动态类型编程语言&#xff0c;内建并行计算支持 使用Erlang来编写分布式应用要简单的多&#xff0c;因为它的分布式机制是透明的 1.1 为什么选择Erlang 需要处理大量…

JavaWeb开发(九)JSP技术

1. JavaWeb JSP技术 1.1. JSP简介 1.1.1. 什么是JSP JSP全名为Java Server Page 是为了简化servlet的工作而出现的替代品。在JSP中java代码与HTML共同存在&#xff0c;其中HTML代码用于展示静态的内容&#xff0c;java代码用来展示动态的内容。 1.1.2. 为什么出现JSP技术 19…

鸿蒙UI开发——Toast即时提示框的使用

1、概 述 Toast提示又称即时反馈&#xff0c;是一种临时性的消息提示框&#xff0c;用于向用户显示简短的操作反馈或状态信息。它通常在屏幕的底部或顶部短暂弹出&#xff0c;随后在一段时间后自动消失。即时反馈的主要目的是提供简洁、不打扰的信息反馈&#xff0c;避免干扰用…