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

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

mhr18 2024-10-22 12:37 19 浏览 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理论过半通过

后续还需要学习的内容




相关推荐

使用 Docker 部署 Java 项目(通俗易懂)

前言:搜索镜像的网站(推荐):DockerDocs1、下载与配置Docker1.1docker下载(这里使用的是Ubuntu,Centos命令可能有不同)以下命令,默认不是root用户操作,...

Spring Boot 3.3.5 + CRaC:从冷启动到秒级响应的架构实践与踩坑实录

去年,我们团队负责的电商订单系统因扩容需求需在10分钟内启动200个Pod实例。当运维组按下扩容按钮时,传统SpringBoot应用的冷启动耗时(平均8.7秒)直接导致流量洪峰期出现30%的请求超时...

《github精选系列》——SpringBoot 全家桶

1简单总结1SpringBoot全家桶简介2项目简介3子项目列表4环境5运行6后续计划7问题反馈gitee地址:https://gitee.com/yidao620/springbo...

Nacos简介—1.Nacos使用简介

大纲1.Nacos的在服务注册中心+配置中心中的应用2.Nacos2.x最新版本下载与目录结构3.Nacos2.x的数据库存储与日志存储4.Nacos2.x服务端的startup.sh启动脚...

spring-ai ollama小试牛刀

序本文主要展示下spring-aiollama的使用示例pom.xml<dependency><groupId>org.springframework.ai<...

SpringCloud系列——10Spring Cloud Gateway网关

学习目标Gateway是什么?它有什么作用?Gateway中的断言使用Gateway中的过滤器使用Gateway中的路由使用第1章网关1.1网关的概念简单来说,网关就是一个网络连接到另外一个网络的...

Spring Boot 自动装配原理剖析

前言在这瞬息万变的技术领域,比了解技术的使用方法更重要的是了解其原理及应用背景。以往我们使用SpringMVC来构建一个项目需要很多基础操作:添加很多jar,配置web.xml,配置Spr...

疯了!Spring 再官宣惊天大漏洞

Spring官宣高危漏洞大家好,我是栈长。前几天爆出来的Spring漏洞,刚修复完又来?今天愚人节来了,这是和大家开玩笑吗?不是的,我也是猝不及防!这个玩笑也开的太大了!!你之前看到的这个漏洞已...

「架构师必备」基于SpringCloud的SaaS型微服务脚手架

简介基于SpringCloud(Hoxton.SR1)+SpringBoot(2.2.4.RELEASE)的SaaS型微服务脚手架,具备用户管理、资源权限管理、网关统一鉴权、Xss防跨站攻击、...

SpringCloud分布式框架&amp;分布式事务&amp;分布式锁

总结本文承接上一篇SpringCloud分布式框架实践之后,进一步实践分布式事务与分布式锁,其中分布式事务主要是基于Seata的AT模式进行强一致性,基于RocketMQ事务消息进行最终一致性,分布式...

SpringBoot全家桶:23篇博客加23个可运行项目让你对它了如指掌

SpringBoot现在已经成为Java开发领域的一颗璀璨明珠,它本身是包容万象的,可以跟各种技术集成。本项目对目前Web开发中常用的各个技术,通过和SpringBoot的集成,并且对各种技术通...

开发好物推荐12之分布式锁redisson-sb

前言springboot开发现在基本都是分布式环境,分布式环境下分布式锁的使用必不可少,主流分布式锁主要包括数据库锁,redis锁,还有zookepper实现的分布式锁,其中最实用的还是Redis分...

拥抱Kubernetes,再见了Spring Cloud

相信很多开发者在熟悉微服务工作后,才发现:以为用SpringCloud已经成功打造了微服务架构帝国,殊不知引入了k8s后,却和CloudNative的生态发展脱轨。从2013年的...

Zabbix/J监控框架和Spring框架的整合方法

Zabbix/J是一个Java版本的系统监控框架,它可以完美地兼容于Zabbix监控系统,使得开发、运维等技术人员能够对整个业务系统的基础设施、应用软件/中间件和业务逻辑进行全方位的分层监控。Spri...

SpringBoot+JWT+Shiro+Mybatis实现Restful快速开发后端脚手架

作者:lywJee来源:cnblogs.com/lywJ/p/11252064.html一、背景前后端分离已经成为互联网项目开发标准,它会为以后的大型分布式架构打下基础。SpringBoot使编码配置...

取消回复欢迎 发表评论: