百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

八、redis中布式锁的实现及原理(redis的分布式锁原理)

mhr18 2024-10-22 12:37 24 浏览 0 评论

导读

前面文章【一、深入理解redis之需要掌握的知识点 】中,我们对redis需要学习的内容框架进行了一个梳理。

二、redis中String和List两种数据类型和应用场景 】、【二、redis中Hash、Set、SortedSet应用场景 】两篇文章我们对redis中String、List、Hash、Set、SortedSet五种数据类型做了一下讲解,并且对他们各自的应用场景进行了介绍。

三、redis数据存储之跳跃表(SKIP LIST) 】深入学习支撑SortedSet排序背后的数据结构,跳跃表;

四、redis持久化之RDB与AOF 】学习了redis中的两种持久化策略:RDB(快照)和AOF(追加日志);

五、redis集群进化过程 】文章中我们学习了redis集群的进化过程,包括解决单点故障问题和性能瓶颈问题等。

六、redis中AKF问题解决方案 】讲解了Redis使用及集群进化过程中AKF问题的解决方案。

七、redis中CAP问题解决方案-Paxos理论过半通过 】我们讲解了Redis使用过程中出现CAP问题的解决方案,以及初步认识Paxos分布式一致性协议。

本章我们将要讲解redis中布式锁的理论、原理及解决方案。



如果大家工作、学习、面试中针对redis还有什么疑问或者其他问题,可以评论区告诉我。
为了保证可以连续不间断地获取最新的技术分析及讲解,建议关注本头条号【程序猿的花果山】。

声明:redis不是实现分布式锁的最佳工具。要想使用分布式锁,最好使用zookeeper。虽然Redisson (Java 版)已经为我们封装了redis分布式锁,在懂得CAP原理及Paxos原理后,依然认为redis不是实现分布式锁的最佳工具.因为redis最初的设计思想是用来做缓存的,用他去解决分布式问题有点麻烦且棘手,所以何不用直接用天生就是用来解决分布式协调问题的zookeeper.

Redisson (Java 版).实现了分布式锁

理论


理论:

1.多线程分为单机多线程和多服务器多线程;同样锁也分为单机锁和多服务器锁

2.单机多线程环境下需要解决的问题有三个:可见性,原子性,顺序性。

在JAVA语言中使用锁(synchronized,RentrentLock等)来保证单机多线程环境下的原子性,使用vvolatile关键字来保证单机多线程环境下的可见性与顺序性。

3.在单机中借助某个关键字(synchronized)或者某种理论(CAS)来实现锁,同样在多服务器多线程环境中也需要借助一个所有服务器都可以看到的工具来实现锁理论,从而达到分布式锁的目的。

需要注意的是,多服务器多线程的锁比单机多线程锁要复杂的多,因为他不仅仅要解决单机的问题,还要解决多服务器之间的网络错误、宕机问题,也就是CAP(一致性、可用性、分区容错性)理论的问题。

4.本文要讲解的是使用redis实现分布式锁的理论。

5..这个页面试图提供一个使用Redis实现分布式锁的规范算法。我们提出一种算法,叫Redlock(红锁),我们认为这种实现比普通的单实例实现更安全。

6..使用redis实现的分布式锁要实现满足以下几个理论条件才可以满足真实的使用:

安全性(锁互斥)、

活性A(无死锁)、

活性B(单机故障不影响整体)

分布式锁特性


解决方案


Redis实现锁的几种方案优缺点:

1.基于故障转移(主从复制)的实现:

实现redis分布式锁的最简单的方法就是在redis中创建一个key,这个key有一个失效时间(TTL),以保证锁最终会被自动释放(对应无死锁特性)。当客户端释放资源(解锁)的时候,会删除这个key。

从表面上看,似乎效果还不错,但是存在这样一个问题:单点故障。如果redis挂了怎么办?你可能会说可以通过增加一个slave节点来解决问题。但是这个是行不通的。因为redis的主从复制默认是异步的。在以下场景中锁就失效了:

1.客户端A从master中获取到了锁;

2.在master把锁信息同步到slave之前,master挂掉了;

3.slave被晋升为master节点;

4.客户端B在新的master节点上获得了同一个资源被客户端A已经获取到的另外一个锁。

这个时候锁互斥的安全失效。

如果你可以接受这种小概率事件,那么这种基于主从复制的方案是可以接受的。


2.单一redis实例实现分布式锁:

当你可以接受上一种“基于故障转移(主从复制)实现”方案的缺点时,我们讨论这一种方案的细节问题。

单实例加锁:

获取锁使用命令 SET resource_name my_random_value NX PX 30000 这个命令仅在key不存在的时候才能被执行成功(NX选项),并且这个key具有30秒的过期时间(PX属性)

这个key的值是“my_random_value”,他是一个随机值。必须保证这个值在所有客户端中是唯一的。所有同一key的获取者(竞争者)这个值都不能一样。

Value的值必须是随机数主要是为了更安全的释放锁,释放锁的时候,使用脚本告诉redis,只有key存在,且值与存储的值是一样的才能删除成功。

可以通过lua脚本实现:

if redis.call("get",KEYS[1]) == ARGV[1] then

return redis.call("del",KEYS[1])

else

return 0

end

使用这种方式释放锁,可以避免误删别的客户端获取到的锁。这个VALUE相当于一个签名。

这个value随机值该怎么设置呢?在linux系统中它应该是从/dev/urandom产生一个20自己的随机数。但是我们可以找到一个比这个代价更小的方法,因为只要保证这个数在所有客户端中是唯一的即可。

例如:把以毫秒为单位的unix时间和客户端ID拼接起来。虽然这种方案理论上不是完全完全的,但是在多数情况下可以满足需求。

Key的失效时间,被称作“锁有效期”。他不仅仅是为了key在已经获取锁客户端出现问题的时候保证其他客户端可以在一段时间后继续使用锁,而且还是为了保证key可以自动失效,更一种情况是定义了客户端必须在有效期内执行完自己的操作,否则视为失败。因此key的过期时间的设定是需要仔细斟酌的,可以在多次压测后获取一个可行的时间。

3.ReadLock-Redis分布式环境-CAP理论与Paxos理论(过半通过)

在redis分布式环境中,我们假设有N个相互独立的RedisMaster,这N个节点相互独立,不存在主从复制或者其他协调机制。

在“单redis实例实现分布式锁”方案中,我们已经可以安全的获取和释放锁了,这就保证了安全性(锁互斥)和活性A(无死锁)。为了保证活性B(单机故障不影响整体),我们引入N个相互独立的redis实例,在这N个实例上使用安全的获取和释放锁。

这里我们假设有5个RedisMaster节点,这5个节点在5台服务器上或5台虚拟机上运行,这样就保证了他们不会同时宕机。

为了安全的获取到锁,我们可以执行以下操作:

①.获取当前unix时间,以毫秒为单位。

②.一次从5个实例上使用相同的key和随机value获取锁。

在步骤2,当redis设置锁时候,客户端应该设置一个网络连接和响应超时时间,这个超时时间应该小于锁失效时间。

例如:你的锁自动失效时间为10秒,则超时时间应该在5-50毫秒之间。这样可以避免在某个redis服务实例已经挂掉的情况下,客户端还在死死的等待响应结果。如果某个redis服务端没有再规定的时间内响应,则客户端应该尽快去尝试另外一个redis实例。

③.客户端使用当前时间减去开始获取锁时间(步骤1记录的时间)就得到了获取锁使用的时间。当且仅当从大多数(3个节点)redis节点都获取到锁,并且使用的时间小于锁失效时间,锁才算获取成功。

④.如果获取到了锁,key的真正有效时间等于有效时间减去获取锁锁使用的时间(步骤3计算的结果)。如果因为某些原因获取锁失败,客户端应该在所有的redis实例上进行解锁(即便某些redis实例根本就没有加锁成功)

Redis实现分布式锁的其他理论详见:http://redis.cn/topics/distlock.html


如需了解更多更详细内容也可关注本人CSDN博客:不吃_花椒

往期文章

一、深入理解redis之需要掌握的知识点

二、redis中String和List两种数据类型和应用场景

二、redis中Hash、Set、SortedSet应用场景

三、redis数据存储之跳跃表(SKIP LIST)

四、redis持久化之RDB与AOF

五、redis集群进化过程

六、redis中AKF问题解决方案

七、redis中CAP问题解决方案-Paxos理论过半通过

后续还需要学习的内容




相关推荐

甲骨文签署多项大型云协议,其一未来可贡献超300亿美元年收入

IT之家7月1日消息,根据甲骨文Oracle当地时间6月30日向美国证券交易委员会(SEC)递交的FORM8-K文件,该企业在始于2025年6月1日的202...

甲骨文获TEMU巨额合同,后者大部分基础设施将迁移至Oracle云

IT之家6月23日消息,Oracle甲骨文创始人、董事长兼首席技术官LarryEllison(拉里埃里森)在本月早些时候的2025财年第四财季和全财年财报电话会议上表示,Oracle...

Spring Boot 自定义数据源设置,这些坑你踩过吗?

你在使用SpringBoot进行后端开发的过程中,是不是也遇到过这样的问题:项目上线后,数据库连接总是不稳定,偶尔还会出现数据读取缓慢的情况,严重影响了用户体验。经过排查,发现很大一部分原因竟然...

一个开箱即用的代码生成器(一个开箱即用的代码生成器是什么)

今天给大家推荐一个好用的代码生成器,名为renren-generator,该项目附带前端页面,可以很方便的选择我们所需要生成代码的表。首先我们通过git工具克隆下来代码(地址见文末),导入idea。...

低代码建模平台-数据挖掘平台(低代码平台的实现方式)

现在来看一下数据连接。·这里是管理数据连接的空间,点击这里可以新增一个数据连接。·输入连接名称,然后输入url,是通过gdbc的方式去连接的数据库,目前是支持mysql、oracle以及国产数据库达梦...

navicat 17.2.7连接oracle数据库提示加载oracle库失败

系统:macOS15.5navicat版本:navicatpremiumlite17.2.7连接oracle测试报错:加载oracle库失败【解决办法】:放达里面找到程序,显示简介里面勾选“使...

开源“Windows”ReactOS更新:支持全屏应用

IT之家6月17日消息,ReactOS团队昨日(6月16日)在X平台发布系列推文,公布了该系统的最新进展,包括升级Explorer组件,支持全屏应用,从Wine项目引入了...

SSL 推出采用全模拟内置混音技术的模拟调音台Oracle

英国调音台传奇品牌SolidStateLogic宣布推出Oracle——一款采用全模拟内置混音技术的调音台,在紧凑的AWS尺寸机箱内集成了大型调音台的功能。该调音台提供24输入和...

47道网络工程师常见面试题,看看有没有你不会的!

你们好,我的网工朋友。网络工程师面试的时候,都会被问到什么?这个问题其实很泛,一般来说,你肯定要先看明白岗位需求写的是什么。基本上都是围绕公司需要的业务去问的。但不可否认的是,那些最基础的概念,多少也...

汉得信息:发布EBS系统安装启用JWS的高效解决方案

e公司讯,从汉得信息获悉,近日,微软官方宣布InternetExplorer桌面应用程序将于2022年6月15日正式停用。目前大部分客户都是使用IE浏览器打开EBS的Form界面,IE停用后,只能使...

36.9K star ! 推荐一个酷炫低代码开发平台!功能太强!

前言最近在逛github,看看能不能搜罗到一些对自己有帮助的开源软件。不经意间看到一个高star的java开源项目:jeecg-boot。进入在线演示版一看,感叹实在是太牛了!此开源项目不管是给来学习...

Linux新手入门系列:Linux下jdk安装配置

本系列文章是把作者刚接触和学习Linux时候的实操记录分享出来,内容主要包括Linux入门的一些理论概念知识、Web程序、mysql数据库的简单安装部署,希望能够帮到一些初学者,少走一些弯路。注意:L...

手把手教你在嵌入式设备中使用SQLite3

摘要:数据库是用来存储和管理数据的专用软件,使得管理数据更加安全,方便和高效。数据库对数据的管理的基本单位是表(table),在嵌入式linux中有时候它也需要用到数据库,听起来好难,其实就是几个函数...

JAVA语言基础(java语言基础知识)

一、计算机的基本概念什么是计算机?计算机(Computer)全称:电子计算机,俗称电脑。是一种能够按照程序运行、自动高速处理海量数据的现代化智能电子设备。由硬件和软件组成、没有安装过任何软件的计算机称...

再见 Navicat!一款开源的 Web 数据库管理工具!

大家好,我是Java陈序员。在日常的开发工作中,常常需要与各种数据库打交道。而为了提高工作效率,常常会使用一些可视化工具进行操作数据库。今天,给大家介绍一款开源的数据库管理工具,无需下载安装软件,基...

取消回复欢迎 发表评论: