好文章:
https://blog.csdn.net/hh1sdfsf56456/article/details/79474434
分布式锁,存在无法解决的问题,一起回顾如下
1、为了提高单redis的可用性,给master挂了一个从slave节点,因为主从复制是异步的,会出现不同客户端同时获取锁的情况
客户端1在master中获得了锁,
在锁同步到slave之前,master宕机,还未来得及将锁同步到slave
slave升级为master
客户端2在新的master中获取了锁
这样客户端1、客户端2就
同时持有了同一个资源的锁
2、客户端1获取锁,因网络延时,客户端长时间阻塞,锁过期,这时客户端2获取锁,与此同时客户端1的网络恢复正常,这就导致
两个客户端可同时访问共享资源。
备注:有两种情况会引发阻塞
情况1:客户端跟redis通信的问题,
情况2:客户端跟共享资源服务器交互延时
那么接下来我看看Redlock是否能解决上述两个问题
一、分布式锁Redlock
antirez因为上述问题提出了新的分布式锁的算法Redlock,它基于N个完全独立的Redis节点(通常情况下N可以设置成5)。
运行Redlock算法的客户端依次执行下面各个步骤,来完成获取锁的操作:
获取当前时间(毫秒数)。
按顺序依次向N个Redis节点执行获取锁的操作。这个获取操作跟前面基于单Redis节点的获取锁的过程相同,包含随机字符串my_random_value,也包含过期时间(比如PX 30000,即锁的有效时间)。为了保证在某个Redis节点不可用的时候算法能够继续运行,这个获取锁的操作还有一个超时时间(time out),它要远小于锁的有效时间(几十毫秒量级)。
客户端在向某个Redis节点获取锁失败以后,应该立即尝试下一个Redis节点。这里的失败,应该包含任何类型的失败,比如该Redis节点不可用,或者该Redis节点上的锁已经被其它客户端持有(注:Redlock原文中这里只提到了Redis节点不可用的情况,但也应该包含其它的失败情况)。
计算整个获取锁的过程总共消耗了多长时间,计算方法是用当前时间减去第1步记录的时间。
如果客户端从大多数Redis节点(>= N/2+1)成功获取到了锁,并且获取锁总共消耗的时间没有超过锁的有效时间(lock validity time),那么这时客户端才认为最终获取锁成功;否则,认为最终获取锁失败。
如果最终获取锁成功了,那么这个锁的有效时间应该重新计算,它等于最初的锁的有效时间减去第3步计算出来的获取锁消耗的时间。
如果最终获取锁失败了(可能由于获取到锁的Redis节点个数少于N/2+1,或者整个获取锁的过程消耗的时间超过了锁的最初有效时间),那么客户端应该立即向所有Redis节点发起释放锁的操作(即前面介绍的Redis Lua脚本)。
当然,上面描述的只是获取锁的过程,而释放锁的过程比较简单:客户端向所有Redis节点发起释放锁的操作,不管这些节点当时在获取锁的时候成功与否。
二、Redlock存在的问题
由于N个Redis节点中的大多数能正常工作就能保证Redlock正常工作,因此理论上它的可用性更高。
我们前面讨论的单Redis节点的分布式锁在failover的时候锁失效的问题,在Redlock中不存在了(解决了遗留问题1),但如果有节点发生崩溃重启,还是会对锁的安全性有影响的。具体的影响程度跟Redis对数据的持久化程度有关。
根据上述提出的算法,当N个节点中有一个节点宕机,仍然存在锁的安全性问题。具体的影响跟redis的持久化程度有关
假设一共有5个Redis节点:A, B, C, D, E。设想发生了如下的事件序列:
客户端1成功锁住了A, B, C,获取锁成功(但D和E没有锁住)。
节点C崩溃重启了,但客户端1在C上加的锁没有持久化下来,丢失了。
节点C重启后,客户端2锁住了C, D, E,获取锁成功。
这样,客户端1和客户端2同时获得了锁(针对同一资源)。
在默认情况下,
Redis的AOF持久化方式是每秒写一次磁盘(即执行fsync),因此最坏情况下可能丢失1秒的数据。
为了尽可能不丢数据,Redis允许设置成每次修改数据都进行fsync,但这会降低性能。当然,即使执行了fsync也仍然有可能丢失数据(这取决于系统而不是Redis的实现)。所以,上面分析的由于节点重启引发的锁失效问题,总是有可能出现的。
为了应对这一问题,antirez又提出了延迟重启(delayed restarts)的概念。也就是说,
一个节点崩溃后,先不立即重启它,而是等待一段时间再重启,这段时间应该大于锁的有效时间(lock validity time)。这样的话,这个节点在重启前所参与的锁都会过期,它在重启后就不会对现有的锁造成影响。
关于Redlock还有一点细节值得拿出来分析一下:
antirez在算法描述中特别强调:
在最后释放锁的时候,客户端应该向所有Redis节点发起释放锁的操作。也就是说,即使当时向某个节点获取锁没有成功,在释放锁的时候也不应该漏掉这个节点。
这是为什么呢?设想这样一种情况,客户端发给某个Redis节点的获取锁的请求成功到达了该Redis节点,这个节点也成功执行了SET操作,但是它返回给客户端的响应包却丢失了。这在客户端看来,获取锁的请求由于超时而失败了,但在Redis这边看来,加锁已经成功了。因此,释放锁的时候,客户端也应该对当时获取锁失败的那些Redis节点同样发起请求。实际上,这种情况在异步通信模型中是有可能发生的:客户端向服务器通信是正常的,但反方向却是有问题的。
三、其它问题
1、仍然存在开篇我们提到的第2个问题:客户端长时间阻塞,导致获得的锁释放,访问的共享资源不受保护的问题。
2、在Redlock的算法中,我们可以看到第3步,当获取锁耗时太多,留给客户端的访问共享资源的时间很短,这种情况若来不及操作,是不是要释放锁呢?且到底剩下多少时间才算短?这又是一个选择难题。
3、Redlock算法对时钟依赖性太强,若N个节点中的某个节点发生时间跳跃,也可能会引此而引发锁安全性问题。
分享到:
相关推荐
redlock-py, 在 python 中,Redis分布式锁 redlock - python 中的分布式锁这个 python 库实现了基于redis的分布式锁管理器算法( ) 。要创建锁定管理器:dlm = Redlock([{"host":"localhost","port":
分布式锁是解决分布式系统中多个进程间共享资源互斥访问的一种方法,它保证了即使在分布式环境下,也能维持数据的一致性。随着互联网公司业务的不断扩展和技术的进步,分布式系统的数据量和业务复杂性大幅增加,...
分布式锁是一种在分布式系统中实现同步访问资源的机制,它允许多个节点在同一时间对共享资源进行操作,而不会导致数据不一致或并发问题。在Java开发中,分布式锁的应用广泛,尤其是在微服务架构中,当服务间的通信...
Redis提供了多种实现分布式锁的方法,如使用`SETNX`命令设置带有过期时间的键,或者使用`RedLock`算法,通过在多个Redis实例上创建锁来提高健壮性。`SETNX`简单易用,但不支持可重入性和自动释放;而`RedLock`通过...
在现代的高并发系统中,分布式锁是一种非常重要的机制,用于协调多个节点间的资源访问,以确保数据的一致性和完整性。SpringBoot是一个流行的Java微服务框架,它简化了与各种技术栈的集成,包括Redis这样的高性能...
本教程将基于SpringBoot框架,结合Redisson库来实现RedLock分布式锁,确保高可用性和数据一致性。 首先,让我们了解SpringBoot。SpringBoot是由Pivotal团队提供的全新框架,它简化了基于Spring的应用程序开发过程,...
分布式锁是一种在分布式系统中实现锁机制的技术,用于在多节点之间协调访问共享资源,确保在高并发环境下数据的一致性和完整性。本压缩包“zk:redis分布式锁.zip”提供了基于Zookeeper(zk)和Redis两种分布式锁实现...
为规避Redis分布式锁的缺陷,可能采用了如红锁(RedLock)等方案,或者优化了单点故障、锁续租等问题。Redis分布式锁常见的问题包括单节点故障导致的锁失效、客户端崩溃后锁无法释放等。通过改进算法或增加额外的...
### 分布式锁原理介绍 #### 一、分布式锁概览 **分布式锁**是一种用于在分布式系统中控制多个节点对共享资源进行访问的技术。它主要用于解决多节点间并发访问同一资源时产生的竞争问题,确保资源的一致性和完整性...
分布式锁是一种在分布式系统中确保多个节点对共享资源进行互斥访问的机制。在分布式环境中,由于网络延迟和并发操作,可能会出现竞态条件,即多个节点同时执行相同的操作,导致数据一致性问题。为了解决这些问题,...
2. Redlock:由Redis作者Antirez提出的分布式锁算法,通过在多台Redis实例上实现锁来提高可用性和容错性。 综上所述,Redis是实现分布式锁的理想选择,其高效、原子性的特性使得在分布式系统中控制共享资源成为可能...
本文将深入探讨分布式锁的概念、其在防刷单场景中的应用以及如何利用Redis实现分布式锁。 分布式锁是一种在分布式系统中协调不同节点间对共享资源访问的机制。它的核心目标是保证在多节点环境下,对于同一资源的...
而Redis虽然也支持分布式锁,但需要额外的机制(如RedLock)来确保高可用性。 2. **故障恢复**:Zookeeper的临时节点特性使得在客户端故障时,锁能自动释放,避免死锁问题。而在Redis中,如果客户端崩溃,需要额外的...
Redis分布式锁是解决多节点集群部署中并发控制的重要工具,但在使用过程中,它存在一些问题,需要谨慎处理。本文将详细探讨这些问题及其解决方案。 首先,死锁问题是Redis分布式锁的一个常见挑战。当一个进程获取了...
redlock-rb, 在 ruby 中,基于Redlock的分布式锁实现 redlock ruby - 中的分布式锁这个 ruby 库实现了基于redis的分布式锁管理器算法( ) 。要创建锁定管理器:dlm = Redlock.new("redis://127.0.0.1:6379","redis
在IT行业中,分布式系统的设计与实现常常涉及到数据一致性与并发控制的问题,而分布式锁作为解决这类问题的关键工具,被广泛应用于各种场景。本篇主要讨论的是如何基于SpringBoot框架,利用Redis实现高可用的分布式...
### 分布式锁与信号量知识点详解 #### 一、分布式锁 **1.1 定义** 分布式锁是一种在分布式系统中实现资源共享控制的方法。它确保了在任何时刻,只有一个系统实例能够访问共享资源,从而避免了并发访问导致的数据不...
java lru leetcode 一、Redis数据类型使用场景 1. 两个小细节 (1)命令不区分大小写,而 key 区分大小写。 (2)help @ 可以快速查看命令。 # 1: 命令不区分大小写,而 `key` 区分大小写 ...increment
Redis分布式锁主要基于`SETNX`命令或者RedLock算法。`SETNX`命令在键不存在时设置键值,但如果存在则返回失败,这可以用来简单地实现锁。然而,单实例的Redis分布式锁存在一定的风险,如主节点故障可能导致锁无法...
Java 使用 Redlock 实现分布式锁过程解析 在分布式系统中,锁机制是一种非常重要的技术手段,能够确保在不同进程需要互斥地访问共享资源时,避免了数据的不一致性和并发冲突。Java 使用 Redlock 实现分布式锁过程...