redis面试(十八)RedLock加锁原理

server/2024/10/22 15:35:01/

redLock_0">什么是redLock

RedLock算法思想,不只在一个redis实例上创建锁,是在多个redis实例上创建锁,n / 2 + 1,必须在大多数redis节点上都成功创建锁,才能算这个整体的RedLock加锁成功,避免说仅仅在一个redis实例上加锁。
普通的redis分布式锁,其实是在redis集群中根据hash算法选择一台redis实例创建一个锁就可以了

大致流程如下:

  1. 获取当前时间戳,单位是毫秒
  2. 跟上面类似,轮流尝试在每个master节点上创建锁,过期时间较短,一般就几十毫秒,在每个节点上创建锁的过程中,需要加一个超时时间,一般来说比如几十毫秒如果没有获取到锁就超时了,标识为获取锁失败
  3. 尝试在大多数节点上建立一个锁,比如3个节点就要求是2个节点(n / 2 +1)
  4. 客户端计算建立好锁的时间,如果建立锁的时间小于超时时间,就算建立成功了
  5. 要是锁建立失败了,那么就依次删除已经创建的锁
  6. 只要别人创建了一把分布式锁,你就得不断轮询去尝试获取锁

实现

RLock lock1 = redisson.getLock("anyLock1");
RLock lock2 = redisson.getLock("anyLock2");
RLock lock3 = redisson.getLock("anyLock3");RedissonRedLock redissonRedLock = new RedissonRedLock(lock1, lock2, lock3);
redissonRedLock.lock();
redissonRedLock.unlock();

剖析

RedissonRedLock锁的实现,非常的简单,他是RedissonMultiLock的一个子类,RedLock算法的实现,是依赖于MultiLock的一个机制来实现的
在这里插入图片描述

主要就是通过方法的重写,改变了MultiLock中的几个特殊的行为

failedLocksLimit,locks.size() - minLocksAmount(locks) = 1,也就是failedLocksLimit,就是能够加锁失败的一个数量

minLocksAmount(locks)里面就是用的大多数节点的一个算法,n / 2 + 1,比如你有3个lock,那么至少要成功加上3 / 2 + 1 = 2个lock

RedLock里包裹了3个小锁,最多能够加锁失败1个锁

calcLockWaitTime,这个东西算出来的时间,是说在对每个lock进行加锁的时候,有一个尝试获取锁超时的时间,原来默认的就是remainTime,4500毫秒,4500毫秒 / 3 = 1500毫秒,每个小lock获取锁超时的时间改成了1500毫秒

waitTime = 4500毫秒
remainTime = 4500毫秒
lockWaitTIme = 1500毫秒
failedLocksLimit,默认是0,就是一个锁都不能容忍加失败了,现在最新的是n - (n / 2 + 1),3个lock,最多可以容忍1个lock加锁失败
waitTime = 1500毫秒

对每个小lock尝试加锁的时候,能够容忍的最大超时时间,就是1500毫秒,1500毫秒之内必须加成功这个小锁,否则就是加锁失败

大家先试想一下,如果是之前讲解的那个最原始的MultiLock,如果任何一个lock加锁失败了,走这里会如何呢?failedLocksLimit = 0,不可能的,因为你都已经一个锁加锁失败了,所以此处不可能等于0

如果failedLocksLimit是0,默认的一个行为,此时就会将所有已经加锁的lock都释放掉,返回一个false,标记本次尝试加锁失败

之前讲解的那个MultiLock的话,只要你有任何一个锁加锁失败,此次加这个MultiLock就会标记为失败,再重来一次

但是,现在的话呢,使用的是RedLock,faildLocksLimit(3个小lock的时候,这个值是1),可以容忍一个锁加锁失败的,此时就会将failedLockLimit–,从1变为了0,也就是说之前可以容忍一次lock加锁失败,但是此时已经失败了一次了,不能再容忍加锁失败了

如果第二个lock加锁又失败了,此时failedLocksLimit已经是0了,那么就会标记为加锁失败,RedLock加锁失败了

如果是假设是3个lock,前2个加锁成功的,最后一个加锁失败了,3 - 2 = 1 = failedLocksLimit,此时是正好需要的最少的加锁的次数都加锁成功了,剩余的锁加锁失败了,也不要紧的,本次加锁就成功了

也就是说,针对多个lock进行加锁,每个lock都有一个1500毫秒的加锁超时时间,如果在4500毫秒内,成功的对n / 2 + 1个lock加锁成功了,就可以认为这个RedLock加锁成功了,不要求所有的lock都加锁成功的

RedLock,是一个锁,只不过是在各个不同的master实例上进行加锁,但是现在说RedLock合并了多个小lock。也就是说,如果你有3个redis master实例,你就用lock1、lock2、lock3三个锁key,人家本来就是分布在3个不同的redis master实例上的

加这个RedLock,相当于是3个redis master实例上的key,有2个加成功了,就算这个RedLock加锁成功了

此时别人如果要来加锁,用一样的key,人家是无法成功加锁的,锁被你占用了,人家就会卡在那儿,死循环,不断的尝试加锁,直到你释放锁
在这里插入图片描述


http://www.ppmy.cn/server/104666.html

相关文章

Java将一张excel数据填充到另一张excel表

需求:根据数据库中excel保存地址url,获取到Excel表格,将其中数据填充到一张新生成的excel表格中 1.设置读取excel和要填充excel的起始行列 public void setExcelData(String fileUrl, String downloadPath, String reportFilePath, String …

Redis后台线程之非阻塞删除

当Redis执行删除命令的时候,如果被删除的对象是列表、集合、散列类型,因为这些数据类型包含的元素存放在不同的内存块中,redis需要遍历所有元素来释放其对应的内存块空间,这个耗时操作可能导致redis阻塞,redis4提供的U…

钡铼技术BL196模块化远程IO模块数字输入输出

钡铼技术的BL196模块化远程IO模块是一款专为工业自动化设计的高度灵活的解决方案。特别地,BL196模块支持数字输入/输出功能,这使得它能够在各种工业环境中发挥重要作用。 产品概述 BL196模块化远程IO模块是一种高度灵活的远程IO系统,它支持…

【前端基础篇】CSS基础速通万字介绍(下篇)

文章目录 前言背景属性背景颜色背景图片背景平铺背景位置背景尺寸 圆角矩形生成圆形生成圆角矩形 Chrome调试工具打开方式标签页含义elements标签页使用 元素显示模式块级元素行内元素/内联元素行内元素和块级元素的区别 盒模型边框内边距外边距 块级元素水平居中去除浏览器默认…

Ignition Gateway配置

Config-System backup和restore: backup可以直接备份整个gateway配置,包括所有项目。 restore可以恢复gateway配置,包括所有项目。

node版本管理工具Node Version Manager(nvm)的安装及使用

文章目录 一、nvm安装1.1,下载nvm安装包程序(选最高版本安装即可,安装前先把本机电脑node卸载,不然管理不到)双击安装包进行安装(傻瓜式下一步即可) 二、配置镜像2.1、使用管理员运行命令提示符2.2、检查nv…

嵌入式和单片机有什么区别?

目录 (1)什么是嵌入式? (2)什么是单片机? (3)嵌入式和单片机的共同点 (4)嵌入式和单片机的区别 (1)什么是嵌入式? 关…