Java redis分布式锁 redis 分布式锁问题

发布时间:2023-05-18 09:11:09

前言:

刚面试了一场,理所当然的挂了,所以写这篇文章给自己压抑,让我委屈的灵魂顺利进行.

正文:

一: 分布式锁面临的问题

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分布式锁在集群下的问题

我希望我的工作能尽快稳定下来。来吧,屌丝

本文是转载内容,我们尊重原作者对文章的权利。如有内容错误或侵权行为,请联系我们更正或删除文章。

上一篇 Java enc解密 encrypt java
下一篇 Java 定义二元数组 java二维数组元素个数

文章素材均来源于网络,如有侵权,请联系管理员删除。

标签: Java教程Java基础Java编程技巧面试题Java面试题