redis面试(十九)读写锁ReadLock

读写锁ReadLock

简单来说就是互斥锁和非互斥锁。多个客户端可以同事加的锁叫读锁,只能有一个客户端加的锁叫写锁。这个理论应该是从数据库中来的,放在这里也是同样的解释。

  • 多个客户端同时加读锁,是不会互斥的,多个客户端可以同时加这个读锁,读锁和读锁是不互斥的
  • 如果有人加了读锁,此时就不能加写锁,任何人都不能加写锁了,读锁和写锁是互斥的
  • 如果有人加了写锁,此时任何人都不能加写锁和读锁了,写锁和写锁也是互斥的

实现

RedissonReadLock是RedissonLock的子类
关注要几块东西,第一个是加读锁的lua脚本的逻辑;第二个是读锁的释放的lua脚本的逻辑;第三个是读锁的wathdog刷新锁key的生存时间的逻辑

RReadWriteLock rwLock = redisson.getReadWriteLock("anyLock");
rwLock.readLock().lock();
rwLock.readLock().unlock();
rwLock.writeLock().lock();
rwLock.writeLock().unlock();

加锁代码

加锁的方法入口都是在RedissonLock类里面,只是在真正加锁的地方用子类来处理。
在这里插入图片描述

点进来就可以看到ReadLcok的lua脚本逻辑,下面就来分析一下
在这里插入图片描述
假设
客户端A(UUID_01:threadId_01)来加读锁
这几个参数拼接之后是下面的形式
KEYS[1] = anyLock
KEYS[2] = {anyLock}:UUID_01:threadId_01:rwlock_timeout

ARGV[1] = 30000毫秒
ARGV[2] = UUID_01:threadId_01
ARGV[3] = UUID_01:threadId_01:write

前两行的的意思就是要从一个名为anyLock的hash结构中,获取一个key为mode的对应的value值
这是第一个线程第一次进来,肯定是空的,条件成立。
local mode = redis.call(‘hget’, KEYS[1], ‘mode’);
if (mode == false) then

新建一个名为anyLock的hash结构,里面有一个键值对mode:read
redis.call(‘hset’, KEYS[1], ‘mode’, ‘read’);

anyLock的hash结构再来个键值对key=UUID_01:threadId_01 value=1
‘hset’, KEYS[1], ARGV[2], 1

set一个键值对,这两个…的意思是拼接字符串KEYS[2] 原本等于{anyLock}:UUID_01:threadId_01:rwlock_timeout
那KEYS[2] … ‘:1’ = {anyLock}:UUID_01:threadId_01:rwlock_timeout:1
所以这里的键值对就是 key={anyLock}:UUID_01:threadId_01:rwlock_timeout:1
value=1
‘set’, KEYS[2] … ‘:1’, 1

是给上面一个hash数据anyLock,一个普通数据{anyLock}:UUID_01:threadId_01:rwlock_timeout:1
设置过期时间 30000毫秒也就是30s
pexpire

现在加完锁返回为空

看门狗

scheduleExpirationRenewal(),这个方法是通用的RedissonLock里面的实现逻辑,但是其中的延时方法renewExpirationAsync() , RedissonReadLock有个自己的实现

在这里插入图片描述

看门狗

lua脚本逻辑
之前我们也分析过普通锁的lua脚本,逻辑是一样的。
简单来说就是只要锁还存在,就不断的延长锁的过期时间避免持有锁的过程中失效。
在这里插入图片描述

假如说刚才已经成功加了读锁,我们来看一下这里的参数
KEYS[1] = anyLock
KEYS[2] = {anyLock}

ARGV[1] = 30000毫秒
ARGV[2] = UUID_01:threadId_01

hget anyLock UUID_01:threadId_01,获取一下当前这个线程是否对这个锁加了一个读锁,这里返回的应该是1,此时可以判定是当前这个线程加的读锁
pexpire anyLock 30000,刷新一下anyLock锁key的生存时间为30000毫秒

hlen anyLock = 2 > 1,就是说,如果你的读锁,anyLock hash内部的key-value对超过了1个,这里肯定是成立的,拿到anyLock所有的key
开始进入循环
这里说是,拿到key对应得值,如果是数字的话,进入下面的循环中,如果不是的话不管他
counter = tonumber(redis.call(‘hget’, KEYS[1], key));
if type(counter) == ‘number’ then
此时counter = 1
for i = counter, 1, -1 do
所以
for i = 1, 1, -1 do

加锁的时候我们知道,anyLock里面有个键值对吗,这里的值也是可重入的,同一个线程每重入一次锁,这里的value就+1,
key=UUID_01:threadId_01 value=1
所以延长锁有效期的时候就要根据这个重入的次数来循环延长。

刚才名为anyLock这个hash结构已经延长过了,现在要延长的就是
key={anyLock}:UUID_01:threadId_01:rwlock_timeout
value=1
这个普通类型的键值对,有一次重入,这个时间就要多延长30s。

pexpire’, KEYS[2] … ‘:’ … key … ‘:rwlock_timeout:’ … i, ARGV[1]

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

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

相关文章

YOLOv8_det/seg/pose/obb推理流程

本章将介绍目标检测、实例分割、关键点检测和旋转目标检测的推理原理,基于onnx模型推理,那么首先就需要了解onnx模型的输入和输出,对输入的图片需要进行预处理的操作,对输出的结果需要进行后处理的操作,这部分内容在我的另一个专栏《YOLOv8深度剖析》中也有介绍,如果对YO…

canal数据同步工具介绍与应用

canal服务 canal介绍canal版本与环境canal 服务集canal应用场景: canal常见问题xml配置问题连接认证问题jar版本问题连接问题 canal介绍 ‌1、Canal是‌阿里巴巴开源的‌MySQL增量数据订阅和消费工具,通过模拟MySQL的‌slave与‌master交互,捕…

一文搞懂微服务架构之降级

前置知识 比如双十一之类的大促高峰,平台是会关闭一些服务的,比如退款服务。这就是降级的典型应用,不过它是一种手动的跨服务降级,对于整个系统来说,提供了一部分服务,但是没有提供另外一部分服务&#xf…

InternLM2_PracticalCamp_L2_task3_LMDeploy量化部署进阶实践

1 配置LMDeploy环境 1.1 InternStudio开发机创建与环境搭建 点选开发机,自拟一个开发机名称,选择Cuda12.2-conda镜像。 我们要运行参数量为7B的InternLM2.5,由InternLM2.5的码仓查询InternLM2.5-7b-chat的config.json文件可知,…

数据库多表设计:深入理解一对多、一对一、多对多关系 【后端 12】

数据库多表设计:深入理解一对多、一对一、多对多关系 在数据库设计中,表之间的关系决定了如何组织和存储数据。常见的表关系包括一对多、一对一和多对多。在不同的业务场景下,我们会选择不同的关系模式进行数据库设计。本文将通过具体案例介绍…

企业高性能web服务器

目录 一、web服务介绍 1.1 Web 服务访问流程 1.2 Web 服务器类型 1.3 Apache常用工作模式 1.3.1 Apache prefork 模型 1.3.2 Apache worker 模型 1.3.3 Apache event 模型 【补充】 子进程角色主要负责以下: 二、Nginx 架构和安装 2.1 Nginx 编译安装示例…

Maven的依赖范围

依赖的jar包,默认情况下,可以在任何地方使用,可以通过scope来设置作用范围 作用范围: 主程序范围有效(main文件夹范围内)测试程序范围有效(test文件夹范围内)是否参与打包运行&…

投资伦敦银一般看什么点位做单?

伦敦银的价格走势不断变化,无论投资者选择做多还是做空,进场的点位都不是一成不变的, 如果投资者想找到胜率比较高的进场点位,可以尝试在走势图中找出银价的支撑与压力位所在,然后在压力位附近布局空单,在…

fastadmin 安装

环境要求,大家可以参考官方文档的,我这里使用的是phpstudy,很多已经集成了。 注意一点,PHP 版本:PHP 7.4 。 第二步:下载 下载地址:https://www.fastadmin.net/download.html 进入下载地址后…

SpringBoot依赖之Spring Data Redis 实现地理坐标(Geospatial)

Spring Boot 项目中使用 Spring Data Redis 实现地理坐标(Geospatial) 概念 Spring Data Redis (AccessDriver) 依赖名称: Spring Data Redis (AccessDriver)功能描述: Advanced and thread-safe Java Redis client for synchronous, asynchronous, and reactive usage. Sup…

如何制作统信UOS启动盘?

如何制作统信UOS启动盘? 一、下载UOS系统安装镜像二、在UOS系统环境下制作启动盘步骤一:准备U盘步骤二:打开启动盘制作工具步骤三:选择ISO镜像文件步骤四:选择安装介质并格式化步骤五:等待制作完成 三、在W…

Redis 技术详解

一、Redis 基础 (一)为什么使用 Redis 速度快,因为数据存在内存中,类似于 HashMap,查找和操作的时间复杂度都是 O(1)。支持丰富数据类型,支持 string、list、set、Zset、hash 等。支持事务,操…

AScript 的UI asui模板的导入

两种方案: 第一种直接在web端,右击UI文件夹 第二种在pycharm,也是右击UI文件夹 调用UI,在init类中直接调用即可

Transformer微调实战:通过低秩分解(LoRA)对T5模型进行微调(LoRA Fine Tune)

scient scient一个用python实现科学计算相关算法的包,包括自然语言、图像、神经网络、优化算法、机器学习、图计算等模块。 scient源码和编译安装包可以在Python package index获取。 The source code and binary installers for the latest released version ar…

Aria2安装和使用-Mac版

起因是需要网盘下载,无奈限速很烦,查找很多方案后,最终决定使用Aria2 Tampermonkey。 其中Aria2是一款开源轻量的下载软件,简单来说就是可以通过URL直接下载。 Tampermonkey则是一款插件,我这里是.crx结尾的谷歌插件…

文件IO函数:open/close,read/write,lseek

open和close函数 C语言中的文件IO操作需要使用到open()函数和close()函数来打开和关闭文件。 open()函数的原型如下: int open(const char *pathname, int flags); int open(const char *filename, int flags,mode_t mode);其中,filename表示要打开…

性能优化理论篇 | swap area是个什么东西

我们知道每台计算机的内存(RAM)都是有限的,而我们的应用程序需要加载到内存才能被运行,如果一台机器运行多个应用程序时,内存可能会耗尽。Linux 系统中的“交换空间(也称为交换分区)”可以帮助缓…

Google Play开发者账号地址验证难题?这些经验或许能帮到你

目前,想要把应用顺利上架到 Google Play,已经不像以前那么简单了,主要是开发者需要应对 Google 日益严格的审核机制。其中,账号验证的地址验证绝对是让很多人头疼的一个环节。 今天就来给大家分享一些真实的经验和干货&#xff0c…

IA实验:静态路由(1基础版)

实验拓扑: 实验要求: 1.实现全网通 实验思路: 1.给各个设备配置好端口的IP地址并且划分广播域,暂定网段为: 192.168.1.0 192.168.2.0 192.168.3.0 2.pc1去ping各网段的设备以及端口,发现3.0网段以及2.2网…

数控单主轴走心机多少钱

单主轴走心机的价格因品牌、型号、性能及配置等因素而异,因此无法给出一个具体的统一价格。一般来说,单主轴走心机的价格在数万元到数十万元不等。 市场上某些品牌的单主轴走心机价格可能在十几万之间不等,而另一些高端型号或定制产品的价格可…