Redlock算法实现Redis分布式锁

Redlock算法实现Redis分布式锁

为什么基于故障转移的实现还不够

使用 Redis 锁定资源的最简单方法是在实例中创建密钥。密钥通常是在有限的生存时间内创建的,使用 Redis 过期功能,以便最终它被释放(我们列表中的属性 2)。当客户端需要释放资源时,它会删除密钥。

从表面上看,这很好用,但有一个问题:这是我们架构中的单点故障。如果 Redis 主节点出现故障会怎样? 好吧,让我们添加一个副本!如果主站不可用,请使用它。不幸的是,这是不可行的。这样一来,我们就无法实现互斥的安全属性,因为 Redis 复制是异步的

此模型存在竞争条件:

  1. 客户端 A 获取主服务器中的锁。
  2. 在对密钥的写入传输到副本之前,主服务器崩溃。
  3. 复制副本将升级为主副本。
  4. 客户端 B 获取 A 已为其持有锁的同一资源的锁。违反安全规定!

在这里插入图片描述

如何实现单个实例的Redis分布式锁

  SET resource_name my_random_value NX PX 30000

仅在秘钥不存在时生成秘钥,并且其中的值my_random_value是全局唯一的,并设置过期时间30000ms

使用随机值是为了以安全的方式释放锁,并带有一个脚本告诉 Redis:仅当密钥存在并且存储在密钥中的值正是我期望的值时才删除密钥。这是通过以下 Lua 脚本完成的:

if redis.call("get",KEYS[1]) == ARGV[1] thenreturn redis.call("del",KEYS[1])
elsereturn 0
end

使用lua脚本是为了保证语句的原子性;

防止误删key为了避免删除由其他客户端创建的锁,这一点很重要。例如,客户端可能会获取锁,在超过锁有效期(密钥过期的时间)的运行时间长于某些操作时被阻止,然后删除已由其他客户端获取的锁。 仅使用 DEL 是不安全的,因为客户端可能会删除另一个客户端的锁。使用上面的脚本,每个锁都使用随机字符串进行“签名”,因此只有当它仍然是客户端尝试删除它时设置的锁才会被删除。

这个随机字符串应该是什么?我们假设它是 的 20 个字节,但您可以找到更便宜的方法来使其对您的任务足够独特。 例如,一个安全的选择是用 为 RC4 提供种子,并从中生成伪随机流。 更简单的解决方案是使用具有微秒精度的 UNIX 时间戳,将时间戳与客户端 ID 连接起来。它不那么安全,但对于大多数环境来说可能已经足够了

Redlock算法

用来实现基于多个实例的分布式锁。

锁变量由多个实例维护,即使有实例发生了故障,锁变量仍然是存在的,客户端还是可以完成锁操作。

该方案也是基于(set 加锁、Lua 脚本解锁)进行改良的,所以redis之父antirez 只描述了差异的地方,大致方案如下。

假设我们有N个Redis主节点,例如 N = 5这些节点是完全独立的,我们不使用复制或任何其他隐式协调系统,确保它们以几乎独立的方式失败

为了取到锁客户端执行以下操作:

1获取当前时间,以毫秒为单位;
2依次尝试从5个实例,使用相同的 key 和随机值(例如 UUID)获取锁。当向Redis 请求获取锁时,客户端应该设置一个请求超时时间,这个超时时间应该小于锁的失效时间。例如你的锁自动失效时间为 10 秒,则超时时间应该在 5-50 毫秒之间。这样可以防止客户端在试图与一个宕机的 Redis 节点对话时长时间处于阻塞状态。如果一个实例不可用,客户端应该尽快尝试去另外一个 Redis 实例请求获取锁;
3客户端通过当前时间减去步骤 1 记录的时间来计算获取锁使用的时间。当且仅当从大多数(N/2+1,这里是 3 个节点)的 Redis 节点都取到锁,并且获取锁使用的时间小于锁失效时间时,锁才算获取成功;
4如果取到了锁,其真正有效时间等于初始有效时间减去获取锁所使用的时间(步骤 3 计算的结果)。
5如果由于某些原因未能获得锁(无法在至少 N/2 + 1 个 Redis 实例获取锁、或获取锁的时间超过了有效时间),客户端应该在所有的 Redis 实例上进行解锁(即便某些Redis实例根本就没有加锁成功,防止某些节点获取到锁但是客户端没有得到响应而导致接下来的一段时间不能被重新获取锁)。

该方案为了解决数据不一致的问题,直接舍弃了异步复制只使用 master 节点,同时由于舍弃了 slave,为了保证可用性,引入了 N 个节点,官方建议是 5。

客户端只有在满足下面的这两个条件时,才能认为是加锁成功。

条件1:客户端从超过半数(大于等于N/2+1)的Redis实例上成功获取到了锁;

条件2:客户端获取锁的总耗时没有超过锁的有效时间。

N = 2X + 1 (N是最终部署机器数,X是容错机器数)

Redlock的实现之Redisson

Redisson 是一个在 Redis 的基础上实现的 Java 驻内存数据网格(In-Memory Data Grid)

加锁:
在这里插入图片描述

在这里插入图片描述
通过redisson新建出来的锁默认是30s过期时间
在这里插入图片描述

可重入:
在这里插入图片描述
采用hset,如果所不存在则创建锁并设置过期时间,如果key存在则锁的值递增,如果锁已存在但并非本线程则返回过期时间
续期:

额外起一个线程,定期检查线程是否还持有锁,如果有则延长过期时间。

Redisson 里面就实现了这个方案,使用“看门狗”定期检查(每1/3的锁时间检查1次),如果线程还持有锁,则刷新过期时间;

在这里插入图片描述

在这里插入图片描述
这里面初始化了一个定时器,dely 的时间是 internalLockLeaseTime/3。
在 Redisson 中,internalLockLeaseTime 是 30s,也就是每隔 10s 续期一次,每次 30s。
客户端A加锁成功,就会启动一个watch dog看门狗,他是一个后台线程,会每隔10秒检查一下,如果客户端A还持有锁key,那么就会不断的延长锁key的生存时间,默认每次续命又从30秒新开始
自动续期的lua脚本
在这里插入图片描述

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

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

相关文章

每日一题 2646. 最小化旅行的价格总和(困难,树)

分解为两个子问题,树中节点到节点的路径问题,价格减半树的最小值问题由于它是无向的树,所以对于每一次旅行,以 start 为根,通过dfs寻找 end 就可以很简单地找到需要的路径且它是唯一的,这里我们统计每经过一…

Splashtop 荣获 SDC“年度安全供应商”奖

2023年12月5日 荷兰阿姆斯特丹 Splashtop 是随处办公环境改革的先驱,在伦敦举办的第14届 SDC 颁奖典礼上荣获“年度安全供应商”奖,我们对此感到十分自豪。荣获这一知名奖项凸显了 Splashtop 致力于通过企业级加密和基于权限的访问保护不同规模组织的决…

准确!!!在 CentOS 8 上配置 PostgreSQL 14 的主从复制

在 CentOS 8 上配置 PostgreSQL 14 的主从复制,并设置 WAL 归档到特定路径 /home/postgres/archive 的步骤如下: 主服务器配置(主机) 配置 PostgreSQL: 编辑 postgresql.conf 文件: vim /data/postgres/p…

iis--IIS8中安装和使用URL重写工具(URL Rewrite)的方法

URL重写-下载 IIS8中安装和使用URL重写工具(URL Rewrite)的方法 IIS版本号可以被识别,修复图解,亲测有效

我的NPI项目之Android 安全系列 -- 天地混沌初开

最近在因为有新项目启动,目前处在kickoff之后research阶段,预计在1st March能拿到到Pre-EVT; 在此之前最主要的就是需求分析/可行性分析/风险评估。 而对于软件来说,作为传说中的software project leader,要做的最重要…

运维之远程桌面连接失败问题排查

背景:同一局域网,可以ping通但是远程连接不上,排查一下问题。 1、被远程计算机是否允许远程连接 2、被远程计算机防火墙是否允许 3、被远程计算机远程桌面服务是否正常 4、查看用户权限

mfc项目设置软件版本

//上面设置的版本通过下面的代码可以获取到 TSTRING CVersion::GetSoftVersion() {TSTRING strVer _T("");TCHAR szPath[MAX_PATH] _T("");memset(szPath, 0, sizeof(szPath));::GetModuleFileName(NULL, szPath, sizeof(szPath));//得到本程序的目录UIN…

Ubuntu22.04 安装nvida-docker2和改路径

在 Ubuntu 22.04 上安装 nvidia-docker2 可以通过一系列步骤完成。nvidia-docker2 是一个用于运行 Docker 容器的工具,它使容器能够访问宿主机的 NVIDIA GPU。以下是安装过程: 1. 安装 Docker 首先,确保已经安装了 Docker。如果没有安装 Do…

使用Navicat连接MySQL出现的一些错误

目录 一、错误一:防火墙未关闭 二、错误二:安全组问题 三、错误三:MySQL密码的加密方式 四、错误四:修改my.cnf配置文件 一、错误一:防火墙未关闭 #查看防火墙状态 firewall-cmd --state#关闭防…

在Linux上优化HTTP服务器的性能

在Linux上优化HTTP服务器的性能是一个涉及多个方面的任务,包括服务器硬件、网络设置、软件配置和内容优化。以下是一些关键的优化建议: 选择合适的HTTP服务器软件 Linux上有多种HTTP服务器软件,如Apache、Nginx、Lighttpd等。选择适合您需求…

nodeJS爬虫-爬取虎嗅新闻

1.安装依赖库到本地,需要的库有:安装方法见Node.js笔记说明 const superagent require(superagent); const cheerio require(cheerio); const async require(async); const fs require(fs); const url require(url); const request require(reques…

Centos7如何安装MySQL

目录 一、卸载mysql 二、安装mysql 注:本文主要是看了这位大佬安装MySQL,才想着写一篇记录一下。 一、卸载mysql 安装mysql之前一定要将之前安装的mysql相关文件删除干净,防止出现错误。 (1)关闭mysql 开启了mysql就…

Python文件打包成exe可执行文件

我们平常用python写些脚本可以方便我们的学习办公,但限制就是需要有python环境才能运行。 那能不能直接在没有python环境的电脑上运行我们的脚本呢? 当然可以,那就是直接把python脚本打包成exe可执行程序(注针对win系统&#xf…

什么是数字化工厂?

数字化工厂通常需要资金和技术支持,对大企业来说更容易投入建设。 中小企业难道就毫无机会了吗? 当然不是。中小企业也能够实现数字化工厂,只是可能需要采取不同的策略。虽然中小企业可能面临资源有限的挑战,但通过渐进式的方式和…

品牌咨询策划服务预约小程序作用是什么

对很多行业公司来说,想要在竞争激烈的市场中生存和长期发展,就需要不断完善自身服务和信息流程、规范化。品牌咨询策划公司是企业发展中重要的合作伙伴。 二者都有寻找对方的需求,尤其是对咨询策划公司来说需要不断宣传推广品牌和服务来获得…

服务器数据恢复—重装系统导致XFS文件系统分区丢失的数据恢复案例

服务器数据恢复环境: 服务器使用磁盘柜RAID卡搭建了一组riad5磁盘阵列。服务器上层分配了一个LUN,划分了两个分区:sdc1分区和sdc2分区。通过LVM扩容的方式,将sdc1分区加入到了root_lv中;sdc2分区格式化为XFS文件系统。…

2023-简单点-Python中的attr那些事-hasattr,getattr,setattr

attr hasattrgetattr语法示例使用场景 setattr语法工作原理示例注意事项 hasattr 假设有一个名为Person的类,具有name和age属性: class Person:def __init__(self, name, age):self.name nameself.age age现在创建一个Person对象,并使用h…

Avalonia中使用Prism实现区域导航功能

前言 上一篇文章我们讲了在Avalonia开发中,引入Prism框架来完成项目的MVVM迁移。本章内容将带领大家学习如何在Avalonia中使用Prism框架实现区域导航功能。如果你还不知道Avalonia中如何引入Prism框架,请看我上一篇文章:Avalonia框架下面使用…

Java静态变量和实例变量区别——面试

主要从以下几个方面来解释: 1.定义不同: 静态变量被static关键字修饰, 实例变量前则不加; 2.初始化不同: 静态变量在类加…

跨文化合作指南:与海外网红沟通的不可忽视的文化差异

随着社交媒体的飞速发展,海外网红在全球范围内崭露头角,成为品牌推广和文化传播的重要力量。然而,由于不同国家和地区存在着独特的文化差异,与海外网红进行沟通合作时,我们必须认真对待文化差异,以确保合作…