redis实现分布式锁

做分布式锁的思路:

用一个全局唯一的资源来满足资源竞争的顺序执行和原子性就行。

步骤:

1、A先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。但这种做法可能带来的一个问题:在setnx之后执行expire之前进程意外crash或者要重启维护了,导致永远不释放该锁。

2、为了避免上面提到的问题。setnx时加上一个时间戳,表示失效时间。

SETNX lock.foo <current Unix time + lock timeout + 1>

该锁包含一个Unix时间戳,如果这样一个时间戳等于当前的Unix时间,该锁将不再有效。

3、另一个客户端比如B检测到一个过期的锁并且都尝试去释放它的算法:

  • B发送SETNX lock.foo为了获得该锁

  • 已经崩溃的客户端 A仍然持有该锁,所以Redis将会返回0给B

  • B发送GET lock.foo检查该锁是否已经过期。如果没有过期,B客户端将会睡眠一会,并且从一开始进行重试操作

  • 另一种情况,如果因为 lock.foo键的Unix时间小于当前的Unix时间而导致该锁已经过期,会尝试执行以下的操作:

    GETSET lock.foo <current Unix timestamp + lock timeout + 1>

    由于GETSET 的语意,B会检查已经过期的旧值是否仍然存储在lock.foo中。如果是的话,B会获得锁

  • 如果另一个客户端,假如为 C ,比 B更快的通过GETSET操作获取到锁,那么 B执行GETSET操作会被返回一个不过期的时间戳。C4 将会从第一个步骤重新开始。请注意:即使 B在将来几秒设置该键,这也不是问题。

为了使这种加锁算法更加的健壮,持有锁的客户端应该总是要检查是否超时,保证使用DEL释放锁之前不会过期,因为客户端故障的情况可能是复杂的,不止是崩溃,还会阻塞一段时间,阻止一些操作的执行,并且在阻塞恢复后尝试执行DEL(此时,该LOCK已经被其他客户端所持有)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值