redis的分布式锁(面试题)

首先想想为什么要有分布式锁?
保证一个方法在高并发情况下的同一时间只能被同一个线程执行。

锁的用途?
(1)允许多个客户端操作共享资源
这种情况下,对共享资源的操作一定是幂等性操作,无论你操作多少次都不会出现不同结果。在这里使用锁,无外乎就是为了避免重复操作共享资源从而提高效率。
(2)只允许一个客户端操作共享资源
这种情况下,对共享资源的操作一般是非幂等性操作。在这种情况下,如果出现多个客户端操作共享资源,就可能意味着数据不一致,数据丢失。

redis的分布式锁如何实现?
正常情况下redis使用setnx lock加锁,使用del lock释放锁就可以了。但是如果还没释放锁,服务中途就挂了,这样锁得不到释放造成死锁。可以加上超时时间,等服务启了在释放锁。
因为setnx和expire指令不是原子性,redis在2.8以后加入set扩展命令,使得这两个命令能一起执行。

问题一:分布式锁不能解决超时问题
如果在加锁或者释放锁的期间,业务逻辑太长了导致超时时间过了业务还没执行完,第二个线程重新持有锁 就造成业务的得不到严格执行。这时候需要lua脚本执行。确保原子性。

问题二:可重入锁
redis使用redission插件,首先客户端会发lua脚本个redis查找是否有同名锁,没有就加锁。有就等待该线程释放锁。锁一旦加上会启动一个watch dog,这是一个后台线程,每过十秒检查是否持有锁,如果还持有就会延长key的生存时间。
如果reids主节点宕机了,那么系统会自动切换到slave节点上。但是主从在切换过程中,主从复制是异步的操作,就导致锁丧失了安全性,可能导致第二个线程占有原先的锁。

问题三:主节点宕机,锁安全得不到保障
也是使用redission,其中有一个redlock红锁。Redlock的算法大致是这样。假设有N个主节点。在此我们假设N为5。这些节点相互独立,互不影响。在不同服务器上运行实例。保证不会同时宕机。
客户端应该执行以下操作:

  1. 获取当前时间,精准到毫秒
  2. 使用相同的key和value依次请求5个redis获取锁。这时候客户端应该建立请求响应时间和超时时间。超时时间应该小于锁的失效时间。这样可以避免如果是redis挂了,客户端就没必要等待,继续去下一个redis获取锁。
  3. 只有获取超过半数redis的锁并且获取锁的时间小于锁的失效时间才算获取成功。
  4. 如果获取锁失败 应该释放全部的锁

问题四:加锁失败怎么处理

  1. 抛出异常,通知用户稍后重试
  2. Sleep 一会重试
  3. 将请求转移到延时队列。稍后重试
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值