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.rhkb.cn/news/406864.html

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

相关文章

“肯将玉钳作双戟,一舞天下定乾坤。”记唐铎《墨龙图》之中的笔墨画意

唐铎,1957 年生于北京,国家一级美术师,曾先后师从于刘文西、黄申发老师,原名唐京鸣,京城人士,取其名,不鸣则已,一鸣惊人之意,学画三十余年,专注于齐派虾蟹&am…

【技巧】-DNSlog外带文件

❤️博客主页: iknow181 🔥系列专栏: 网络安全、 Python、JavaSE、JavaWeb、CCNP 🎉欢迎大家点赞👍收藏⭐评论✍ 1.什么是DNSlog 我们都知道DNS就是将域名解析为ip,用户在浏览器上输入一个域名A.com&#x…

深入探索分布式任务调度框架:MySQL实现高效锁机制

本文主要介绍项目中怎么使用 MySQL 实现分布式锁的 背景 假如我们现在要做一个高性能、可扩展的分布式任务调度框架,要怎么设计呢?下面是我之前自己设计的一个架构图。 为了方便后续的分布式锁的设计,我们大致描述下各个角色都做了哪些事情…

鹏哥C语言自定义笔记重点(29-)

29.函数指针数组 30.void指针是不能直接解引用,也不能-整数。 void*是无具体类型的指针,可以接受任何类型的地址。 31.qsort:使用快速排序的思想实现一个排序函数(升序) 32. 33.地址的字节是4/8 34.char arr[]{a,b} sizeof(arr[0]1)答案是4&#xff0…

Godot《躲避小兵》实战之游戏开始界面制作

我们的游戏还需要用户可操作的界面,比如开始游戏,退出以及显示分数等UI界面。 创建新场景,点击“其他节点”按钮,然后添加一个 CanvasLayer 节点并命名为 HUD。“HUD”是“heads-up display”(游戏信息显示&#xff0…

windows所有功能都可使用就是电脑黑屏了

运行新任务然后输入explorer.exe勾选上创建任务确定就好了 下次尽量不手欠!!!!

Golang | Leetcode Golang题解之第367题有效的完全平方数

题目&#xff1a; 题解&#xff1a; func isPerfectSquare(num int) bool {x0 : float64(num)for {x1 : (x0 float64(num)/x0) / 2if x0-x1 < 1e-6 {x : int(x0)return x*x num}x0 x1} }

改编版猜数字小游戏,猜错了就黑屏(整蛊版本)

1. 前情提要 在前一篇博客中&#xff0c;我们了解到了如何获得随机数&#xff0c;并且通过运算可以规定所获得的这个随机数的范围在多少数值之间 那么接下来我们就需要去具体去实现猜数字游戏的各种布置 2. 布置主菜单 玩一个游戏&#xff0c;最开始的界面都会是一个主菜单…

hutool excel 导出,格式错误,打开乱码

现象 最近在使用hutool excel 实现网站数据导出excel功能。在swagger 中调试接口时候遇到下载文件不能打开或者乱码的问题。 1. xlsx 文件不能打开 2. xls 文件打开乱码 解决方案 直接使用postman 或者 get 请求使用浏览器地址栏 总之&#xff0c;excel 文件不能导出&#xf…

leetcode 49 字母异位分词

正文 基础解法 首先&#xff0c;我们创建一个字典对象&#xff0c;然后遍历整个字符串列表&#xff0c;并且使用 sorted() 函数对字符串列表进行排序&#xff0c;所有的异位分词经过排序后它们的组成和顺序会趋于一致。但是需要注意的是 sorted 对字符串进行排序后会变成一个由…

day06_算法训练

一. Stream流 1.1 Stream流概述 概念: jdk1.8以后提供的新的API, 主要用于批量操作数据(集合的另外一种操作方式),代码非常简洁 流式处理思想: 2.2 Stream对象获取 1.单列集合的Stream流对象获取 2.双列集合的Stream流对象获取 3.数组的Stream流对象获取 4.散装数据的St…

上线eleme项目

&#xff08;一&#xff09;搭建主从从数据库 主服务器master 首先下载mysql57安装包&#xff0c;然后解压 复制改目录到/usr/local底下并且改个名字 cp -r mysql-5.7.44-linux-glibc2.12-x86_64 /usr/local/mysql 删掉/etc/my.cnf 这个会影响mysql57的启动 rm -rf /etc…

科研绘图系列:Python语言时间趋势图

介绍 不同指标在时间上的变化,可以用时间序列线图表示趋势。 加载Python包 import sys import pandas as pd import numpy as np import scipy as sp from scipy import stats import randomimport seaborn as sns import matplotlib.pyplot as plt from matplotl

Open3D mesh 隐藏点移除

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 3.1原始点云 3.2去除隐藏点后的点云 Open3D点云算法汇总及实战案例汇总的目录地址&#xff1a; Open3D点云算法与点云深度学习案例汇总&#xff08;长期更新&…

C++ | Leetcode C++题解之第363题矩形区域不超过K的最大数值和

题目&#xff1a; 题解&#xff1a; class Solution { public:int maxSumSubmatrix(vector<vector<int>> &matrix, int k) {int ans INT_MIN;int m matrix.size(), n matrix[0].size();for (int i 0; i < m; i) { // 枚举上边界vector<int> sum(…

开关电源测试系统方案:系统结构功能、特点、测试项目

为了应对开关电源测试中的复杂挑战&#xff0c;我们推出了NSAT-8000系列开关电源ate测试系统&#xff0c;它以其全面的功能和灵活性&#xff0c;适应了电源产品测试场景&#xff0c;解决了测试难题。 开关电源测试系统 NSAT-8000系列之开关电源测试系统适用于AC/DC和DC/DC开关电…

如何使用 Higress 快速构建 AI 应用?

随着 AI 时代到来&#xff0c;基于大模型的应用对网关提出了新的要求&#xff0c;例如在不同 LLM 提供商之间进行负载均衡、构建 AI 应用的可观测能力、基于 token 的限流保护与配额管理、AI 应用内容安全等等。Higress 基于企业内外的丰富场景沉淀了众多面向AI的功能&#xff…

【前端面试】看react源码,解读useState

点击:react git 链接 截止2024.8.22最新版本如下 React hooks 源码好深,hook封装位于packages/react-reconciler/src/ReactFiberHooks.js hook的数据类型: export type Hook = {memoizedState: any,baseState: any,baseQueue: Update<any, any> | null,queue: an…

数据结构(6.2_4)——图的基本操作

注&#xff1a;只探讨邻接矩阵和邻接表怎么实现图的基本操作 Adjacent(G,x,y):判断图G是否存在边<x,y>或(x,y) 领接矩阵 邻接表 有向图&#xff1a; Neighbors(G,x):列出图G中与结点x邻接的边 有向图 InsertVertex(G,x):在图G中插入顶点x DeleteVertex(G,x):在图G中删除…