Redis实现分布式锁

文章介绍了如何基于Redis实现分布式锁,包括单个Redis节点和Redis集群两种情况。在单节点中,利用SETNX保证加锁原子性,并设置过期时间防止死锁。在集群中,通过RedLock算法,确保在多数节点成功加锁时才认为锁定成功,提供高可用性。
摘要由CSDN通过智能技术生成

基于Redis实现分布式锁。分为单Redis节点实现和Redis集群实现。

基于单个Redis节点实现分布式锁

作为分布式锁实现过程中的共享存储系统,Redis可以使用键值对来保护锁变量,在接收和处理不同客户端发送的加锁的操作请求。

image

客户端A、C同时请求加锁,因为Redis使用单线程处理请求,所以,即使客户端同时发起加锁请求,Redis也会串行处理,保证每次只有一个客户端加锁成功,另一个客户端返回加锁失败。

客户端执行释放锁操作后,Redis将锁的值改为0,表明没有客户端持有锁。

加锁包含了三个操作,分别是读锁变量、判断锁、把锁的值修改为1,这三个操作在执行时需要保证原子性。可以使用单命令操作或者使用Lua脚本。

常用的但命令操作:SETNX。它用于设置键值对的值。具体来说,就是这个命令在执行时会判断键值对是否存在,如果不存在,就设置键值对的值,如果存在,就不做任何设置。

对于释放锁操作来说,我们可以在执行完业务逻辑后,使用 DEL 命令删除锁变量。不过,你不用担心锁变量被删除后,其他客户端无法请求加锁了。因为 SETNX 命令在执行时,如果要设置的键值对(也就是锁变量)不存在,SETNX 命令会先创建键值对,然后设置它的值。所以,释放锁之后,再有客户端请求加锁时,SETNX 命令会创建保存锁变量的键值对,并设置锁变量的值,完成加锁。

风险点就是,如果客户端加锁后,因为发生异常,一直没有执行最后的释放锁操作,锁就一直不能释放,其他客户端就无法拿到锁,无法正常执行业务。解决办法就是给锁变量设置一个过期时间,即使客户端发生异常无法释放锁,在锁变量过期后,把它删除。

SET key value [EX seconds | PX milliseconds]  [NX]
基于多个Redis节点实现高可靠的分布式锁

在我们实现高可靠的分布式锁时,就不能只依赖单个命令操作,需要按照一定的步骤和规则进行加锁操作。否则,就可能会出现锁无法工作的情况。其实就是分布式锁的算法。常见的分布式锁算法很多,这里介绍RedLock。

Redlock 算法的基本思路,是让客户端和多个独立的 Redis 实例依次请求加锁,如果客户端能够和半数以上的实例成功地完成加锁操作,那么我们就认为,客户端成功地获得分布式锁了,否则加锁失败。这样一来,即使有单个 Redis 实例发生故障,因为锁变量在其它实例上也有保存,所以,客户端仍然可以正常地进行锁操作,锁变量并不会丢失。

实现步骤:

  1. 客户端获取当前时间。
  2. 客户端按顺序依次向 N 个 Redis 实例执行加锁操作。
  3. 一旦客户端完成了和所有 Redis 实例的加锁操作,客户端就要计算整个加锁过程的总耗时。

客户端只有在满足下面两个条件时才能认为加锁成功:

  • 条件一:客户端从超过半数的Redis实例上成功获取到了锁;
  • 条件二:客户端获取锁的总耗时没有超过锁的有效时间。

在满足了这两个条件后,我们需要重新计算这把锁的有效时间,计算的结果是锁的最初有效时间减去客户端为获取锁的总耗时。如果锁的有效时间已经来不及完成共享数据的操作了,我们可以释放锁,以免出现还没完成数据操作,锁就过期了的情况。

学习来源:极客时间 《Redis核心技术与实战》 学习笔记 Day20

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

故里学Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值