redis面试(十九)读写锁ReadLock

2024-08-23 01:20

本文主要是介绍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]

这篇关于redis面试(十九)读写锁ReadLock的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1097950

相关文章

Redis Cluster模式配置

《RedisCluster模式配置》:本文主要介绍RedisCluster模式配置,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录分片 一、分片的本质与核心价值二、分片实现方案对比 ‌三、分片算法详解1. ‌范围分片(顺序分片)‌2. ‌哈希分片3. ‌虚

Springboot整合Redis主从实践

《Springboot整合Redis主从实践》:本文主要介绍Springboot整合Redis主从的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言原配置现配置测试LettuceConnectionFactory.setShareNativeConnect

Redis过期删除机制与内存淘汰策略的解析指南

《Redis过期删除机制与内存淘汰策略的解析指南》在使用Redis构建缓存系统时,很多开发者只设置了EXPIRE但却忽略了背后Redis的过期删除机制与内存淘汰策略,下面小编就来和大家详细介绍一下... 目录1、简述2、Redis http://www.chinasem.cn的过期删除策略(Key Expir

Redis指南及6.2.x版本安装过程

《Redis指南及6.2.x版本安装过程》Redis是完全开源免费的,遵守BSD协议,是一个高性能(NOSQL)的key-value数据库,Redis是一个开源的使用ANSIC语言编写、支持网络、... 目录概述Redis特点Redis应用场景缓存缓存分布式会话分布式锁社交网络最新列表Redis各版本介绍旧

Java如何从Redis中批量读取数据

《Java如何从Redis中批量读取数据》:本文主要介绍Java如何从Redis中批量读取数据的情况,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一.背景概述二.分析与实现三.发现问题与屡次改进3.1.QPS过高而且波动很大3.2.程序中断,抛异常3.3.内存消

Redis中的Lettuce使用详解

《Redis中的Lettuce使用详解》Lettuce是一个高级的、线程安全的Redis客户端,用于与Redis数据库交互,Lettuce是一个功能强大、使用方便的Redis客户端,适用于各种规模的J... 目录简介特点连接池连接池特点连接池管理连接池优势连接池配置参数监控常用监控工具通过JMX监控通过Pr

ShardingSphere之读写分离方式

《ShardingSphere之读写分离方式》:本文主要介绍ShardingSphere之读写分离方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录ShardingSphere-读写分离读写分离mysql主从集群创建 user 表主节点执行见表语句项目代码读写分

python操作redis基础

《python操作redis基础》Redis(RemoteDictionaryServer)是一个开源的、基于内存的键值对(Key-Value)存储系统,它通常用作数据库、缓存和消息代理,这篇文章... 目录1. Redis 简介2. 前提条件3. 安装 python Redis 客户端库4. 连接到 Re

Redis迷你版微信抢红包实战

《Redis迷你版微信抢红包实战》本文主要介绍了Redis迷你版微信抢红包实战... 目录1 思路分析1.1hCckRX 流程1.2 注意点①拆红包:二倍均值算法②发红包:list③抢红包&记录:hset2 代码实现2.1 拆红包splitRedPacket2.2 发红包sendRedPacket2.3 抢

Golang实现Redis分布式锁(Lua脚本+可重入+自动续期)

《Golang实现Redis分布式锁(Lua脚本+可重入+自动续期)》本文主要介绍了Golang分布式锁实现,采用Redis+Lua脚本确保原子性,持可重入和自动续期,用于防止超卖及重复下单,具有一定... 目录1 概念应用场景分布式锁必备特性2 思路分析宕机与过期防止误删keyLua保证原子性可重入锁自动