Redis面试题——分布式锁

分布式锁

分布式锁的应用场景

抢券问题

我们在电商平台抢购优惠券的时候,首先要进行优惠券数量的查询,判断库存是否充足,如果为否,则抛出异常,为是则扣减库存。

但是实际场景中,由于存在多个线程同时抢券,在线程1查询优惠券之后(此时库存为1),判断库存是否充足之前,线程2同样查询优惠券(同样为1),这时就会导致库存被扣减2次,库存为-1。
在这里插入图片描述
为了解决上述问题,我们在程序开始时,添加互斥锁(synchronized),当线程1获取互斥锁后,线程2获取互斥锁失败,仅当线程1释放锁后,线程1才能进行查询。

在这里插入图片描述

互斥锁解决了线程之间数据不一致的问题,但是互斥锁是一种本地锁,属于JVM,当我们一个应用部署在多台服务器上时,每台服务器都可以获取自己的互斥锁,同样会产生数据不一致的问题。

在这里插入图片描述

因此,为了解决以上问题,我们就需要引入分布式锁。服务器1的线程1获取互斥锁成功后,就会在分布式锁里添加1条记录,这时服务器2的线程1也想去加锁时,就会加锁失败。
在这里插入图片描述

分布式锁的实现原理

Redis实现分布式锁主要利用Redis的setnx命令。setnx是SET if not exists(如果不存在,则 SET)的简写。

  • 获取锁:
# 添加锁,NX是互斥,EX是设置超时时间
SET lock value NX EX 10
  • 释放锁:
# 释放锁,删除即可
DEL key

如何合理控制锁的有效时长

既然可以给锁设置超时时间,那Redis分布式锁如何合理的控制锁的有效时长?方法主要有两种:

  • 根据业务执行时长预估
  • 给锁续期(设置了过期时间,再开另一个进程进行监控,如果业务执行时间长,就给锁增加时长)

由于业务执行的过程中,可能受到网络卡顿延迟等影响,我们没法精准预估业务的具体执行时长,因此,第一种方式不太可行。而给锁续期的方式,目前市面上已经有了现成的redisson框架,让我们接着往下看。

redisson实现分布式锁

实现原理

😺redisson实现分布式锁,加锁、设置过期时间等操作,都是基于setnx命令和lua脚本完成的,Lua 是一种轻量级、高效、嵌入式的脚本语言,被 Redis 集成用于执行原子性操作和复杂逻辑。Redis 提供了两个主要命令用于执行 Lua 脚本,分别是:

  • EVAL:直接执行 Lua 脚本。
  • EVALSHA:通过脚本的 SHA1 哈希值执行已缓存的脚本。

那么它究竟是如何加锁和释放锁的呢?

执行流程——看门狗

由于我们没法精确预估业务的执行时长,因此,我们在加锁的过程中,需要另开一个线程来对持有锁的线程进行监控,给线程增加锁的使用时间,我们称之为看门狗(watch dog),那什么是看门狗呢?

比如我们设置了锁的超时时间(releaseTime)为30s(默认),那每隔30/10=10s,如果业务没有停止,我们就给锁做一次续期,即,重置过期时间为30s,这样可以保证业务不中断。

在这里插入图片描述

那我们应该什么时候去释放锁呢?手动释放,释放后,会自动通知看门狗不需要再做监听。

在这里插入图片描述
trylock中的time如果不传,则启用看门狗。

重试机制

另外,当锁被一个线程占用时,其他线程再进行加锁,这时会加锁失败,但是线程并不会因此中断,而是通过while循环,不断尝试去获取锁,直到获取成功,即重试机制。(为了避免一直获取又获取不到,通常会设置锁最大的尝试次数)

redisson的特性

可重入性

如下图所示,在同一个线程中,我们可以获取分布式锁两次,这里是利用hash结构记录线程id和重入次数。
在这里插入图片描述

无法解决主从一致性

当应用获取锁时,把数据写到主节点中,而在主节点还没来得及把数据同步给从节点时,主节点宕机,会从两个从节点中再选择一个作为主节点,当再次获取锁时,会导致两个线程同时持有一把锁,违背了分布式锁的互斥性,同时可能会导致产生脏数据。
在这里插入图片描述
为了解决这个问题,我们引入了红锁。RedLock(红锁):不能只在一个redis实例上创建锁,应该是在多个redis实例上创建锁(n / 2 + 1),避免在一个redis实例上加锁。
在这里插入图片描述

但是,红锁实现起来复杂、性能差、运维繁琐,在实际应用中,并不常用。在这里,注意区分AP思想和CP思想,如果想要数据高一致性,建议使用zookeeper。

C(Consistency)表示数据一致性,A(Availability)表示系统可用性,P(Partition tolerance)表示分区容错性。

CP:保证了数据的一致性。适用于一些强一致性要求较高、可以容忍短暂的不可用性的应用场景,缺点就是在在发生网络波动时,会导致服务不可用,需要等到数据一致后,才能让用户正常访问,所以会影响用户体验。
如:zookeeper

AP:对于一些对一致性要求较低、需要保证系统的高可用性和持续可用性的应用场景。适用于社交媒体,AP不会影响用户体验,能保证系统的正常运行;在面对网络分区时,AP系统会牺牲一致性,允许系统中的数据存在短暂的不一致。如:redis

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值