前言:
刚面试了一场,理所当然的挂了,所以写这篇文章给自己压抑,让我委屈的灵魂顺利进行.
正文:
一: 分布式锁面临的问题
1.1 锁需要独一无二
1.2 锁需要超时,防止死锁
1.3 锁的创建和设置需要具有原子性的锁超时间
1.4 锁的加时问题
1.5 锁的可重新进入问题
1.6 集群下分布式锁的问题
1.7 redis分布式锁还需要考虑其他问题
二: 解释和解决分布式锁面临的问题
2.1 锁需要独一无二
问题讲解:
首先,分布式锁需要解决的问题是,同一资源在分布式环境中被多个过程访问和操作。由于它们是相同的资源,因此必须考虑数据安全。事实上,解锁的原理与单个过程相同。在单个过程中,需要考虑多线程访问和修改同一变量。为了确保同一变量不同时被多个线程访问,变量应按顺序修改,访问变量时需要加锁,可以是重量级锁,也可以是基于cas的乐观锁.
解决方案:
使用redis命令setnx使用redis(set if not exist),也就是说,如果redis实例中有唯一的键,只能被客户端占用。(key),再想想这个键(key)上设置值将被拒绝.
2.2 锁需要超时,防止死锁
问题讲解:
redis释放锁需要客户端的操作。如果客户端在这个时候突然挂断,就不会有释放锁的操作,这也意味着其他客户想要重新加锁,但不能加锁。.
解决方案:
因此,为了避免客户端挂断或客户端无法正常释放锁的问题,有必要在加锁的同时给锁增加超时间.
也就是说,加锁和给锁加超时操作如下:
>setnx lockkey true #加锁操作
ok
>expire lockkey 5 #增加锁的超时间
... do something critical ...
>del lockkey #释放锁
(integer) 1
2.3 锁的创建和设置需要具有原子性的锁超时间
问题讲解:
从2.3加锁和超时设置可以看出,setnx和expire需要两个命令来完成操作,即两个RTT操作。如果客户端在setnx和expire之间突然挂断,锁就无法释放,又回到了死锁的问题.
解决方案:
使用set扩展命令
如下:
>set lockkey true ex 5 nx #加锁,过期时间5s
ok
... do something critical ...
>del lockkey
以上set lockkey true ex 5 nx命令可以一次性完成setnx和expire,即解决原子性问题.
2.4 锁的加时问题
问题讲解:
虽然上述锁增加了超时间,但客户端不一定能在超时间内完成定时任务。因此,即使目前的客户端没有完成任务,其他客户端也会成功设置锁。此时,同一资源将面临多个客户端同时操作的问题.
解决方案:
锁设置成功后,客户端可以执行定时任务,使用lua脚本删除锁,在锁加时前重新设置锁和加时间.
当然,为什么这里使用lua来完成操作?事实上,就像上述原子问题一样,在删除锁和重新设置锁和锁之间的超时间之间,其他客户可能会占用锁资源,lua具有原子特性。删除锁和重新锁要么完成,要么不完成.
2.5 锁的可重新进入问题
问题讲解:
正如我们上面所说,为了确保锁的独特性,我们需要使用setnx。后来,为了设置超时间,我们选择了set命令.
当然,这里的问题类似于2.5问题,当我们想加锁的时候,有锁的客户端想要再次得到锁,也就是锁重新进入。.
解决方案:
同样,我们也可以选择使用lua脚本重新删除和设置锁的方案.
2.6 集群下分布式锁的问题
问题讲解:
这个问题发生在redis集群方案中。事实上,为了保证redis的高可用性和访问性,redis的主节点和从节点将被设置。主节点负责编写和读取操作,这意味着我们所有的锁都应该写在主redis服务器的例子中。如果主redis服务器停机并释放资源(如果没有持久性,则添加持久性,这个问题会更复杂)。此时,redis主节点的数据没有从服务器复制。此时,其他客户端将抓住机会获得锁,以前锁定的客户端可能仍在操作资源。此时,多个客户端将访问和操作相同的资源.
解决方案:
这个问题准备单独讨论,因为一两句话不能说清楚.
2.7 redis分布式锁还需要考虑其他问题
以上讨论了redis在业务逻辑上会遇到的问题,解决方案可能局限于我上面讨论的解决方案.
当然,逻辑需要根据程序员自己的场景来选择.
例如:
(1) 设置键时,键资源从哪里获取?
它涉及到多客户端的资源共识。简单的分析是,当多个客户端锁定相同的资源时,您如何确定此键(key)需要多个客户端一致,否则,我如何确保键在多个客户端的唯一性?.
(2) 只有拥有锁资源的客户端才能释放锁
当然,这个问题是因为你的锁和解锁逻辑是错误的。根据以上分析,只要解决上述所有关于redis分布式锁的问题,客户端锁释放的问题就不会遇到.
然而,这也是一个细节,需要在业务逻辑中考虑这个问题
三: 总结
我将在另一篇文章中讨论redis分布式锁在集群下的问题
我希望我的工作能尽快稳定下来。来吧,屌丝
本文是转载内容,我们尊重原作者对文章的权利。如有内容错误或侵权行为,请联系我们更正或删除文章。