四方农业网

Java互联网架构-手把手实现分布式锁

编号:java小马

周一至周日下午三点半!精品技术文章准时送上!!!

精品学习资料获取通道,参见文末

图像

如果删除成功返回1,则其他服务器可以继续重复上述步骤来设置密钥以达到获取锁定的目的。

当然,上述操作直接在redis客户端上执行。如果你通过程序调用它,则无法编写它。例如,java需要通过jedis调用,但整个处理逻辑基本相同

通过上面的方法,我们似乎解决了分布式锁的问题,但想想有什么问题吗?

是的,问题仍然存在。可能存在死锁问题。例如,在设置服务器1之后,在获取锁定之后,突然发生停机。

随后的删除键操作无法执行,密钥将始终存在于redis中,每次其他服务器检查时,它都会返回0,他们会认为有人正在使用锁,我需要等待。

为了解决这个死锁问题,我们需要设置密钥的有效期。

有两种方法可以设置

1,首先是设置密钥的有效期'expire key timeout'设置密钥完成后,设置密钥的超时时间,单位为秒,此时锁定会自动释放,以避免死锁。

此方法相当于保持redis控制的锁的有效期。如果时间到了,你没有为我删除密钥,那么redis会直接为你删除它,其他服务器可以继续去setnx获取锁。

2,第二种方法是将密钥交给其他服务器,然后你需要使用值

例如,服务器1,设置值,即超时是当前时间+1秒。此时,服务器2通过get发现时间已超过系统当前时间,表明服务器1尚未解除锁定,服务器1可能出现问题,

服务器2开始执行删除键操作并继续执行setnx操作。

但是这个有一个问题,就是不仅你的服务器2可能发现服务器1已超时,而服务器3也可能发现如果它发生,服务器2,setnx操作完成,服务器3被删除,是服务器3也可以setnx成功吗?

这等于服务器2和服务器3都获得锁定的事实,问题很大。我现在该怎么办?

这次您需要使用“GETSET键值”命令。此命令的含义是获取当前键的值并设置新值。

假设服务器2发现密钥已过期,则开始调用getset命令,然后使用获取的时间来确定密钥是否过期。如果获取的时间仍然过期,则表示已获得锁定。

如果不是,则意味着在服务2执行getset之前,服务器3还可以发现锁已经到期,并且在服务器2之前执行getset操作,并且重置到期时间。

然后,服务器2需要放弃后续操作,继续等待服务器3释放锁或监视密钥的有效期是否到期。

这实际上有一个小问题。服务器3修改了有效期。获得锁定后,服务器2也修改了有效期,但未能获得锁定,但此有效期的时间基于服务器3.添加一些,但影响实际上非常小,几乎可以忽略不计。

3.2,为什么zookeeper可以实现分布式锁?

百度百科全书介绍如下:ZooKeeper是一个分布式,开源的分布式应用协调服务。它是Google的Chubby的开源实现,是Hadoop和Hbase的重要组成部分。

对于我们第一次遇到的人,我们可以理解ZooKeeper就像我们的计算机文件系统,我们可以在d盘中创建文件夹a,并且可以继续在文件夹a中创建文件夹a1,a2。

我们的文件系统有什么特点?也就是说,同一目录中的文件名不能复制,ZooKeeper也是如此。

ZooKeeper中的所有节点(称为文件夹)都称为Znodes,此Znode节点可以存储数据。

我们可以通过“create/zkjjj nice”创建一个节点。此命令意味着在目录中创建了zkjjj的节点,并且值很好。同样,这里的值与我在redis中提到的值相同。它没有意义,你只是给它。

此外,ZooKeeper可以创建4种类型的节点,即:

1,持久节点

2,持久性序列节点

3,临时节点

4,临时订单节点

首先,我们来谈谈持久节点和临时节点之间的区别。只要您创建此节点,ZooKeeper服务器将记录此节点,无论您的ZooKeeper客户端是否已断开连接。

临时节点正好相反。一旦ZooKeeper客户端断开连接,ZooKeeper服务器将不会保存节点。

我们来谈谈顺序节点。顺序节点意味着当您创建节点时,ZooKeeper将自动为节点编号。

最后,zookeeper有一个监控机制。客户端注册以侦听它关心的目录节点。当目录节点更改(数据更改,删除,子目录节点添加和删除)时,zookeeper将通知客户端。

下面我们继续结合上面的分红包方案,描述如何锁定zookeeper。

假设服务器1创建了一个node/zkjjj,成功,然后服务器1获取锁,服务器2然后创建相同的锁,然后他将失败,此时他只能监听该节点的变化。

等到服务器1,处理完业务后,删除节点,他会收到通知,然后创建相同的节点,获取锁处理业务,然后删除该节点,后续的100台服务器都类似

请注意,此处的100台服务器不是执行上述节点创建但是并发的服务器。成功创建服务器1后,剩余的99将注册以侦听此节点,等待通知,依此类推。

但是你注意到这里仍然存在问题,仍然会出现僵局,对吧?

当服务器1在创建节点后挂起并且无法将其删除时,其他99台服务器将等待通知,并且它将完成。

此时,您需要使用临时节点。正如我们之前所说的,临时节点的特征在于,一旦客户端断开连接,它就会丢失,也就是说,当服务器1创建节点时,它会挂起。

该节点将自动删除,以便其他服务器将继续创建节点并获取锁。

但我们可能还需要注意这是一个令人震惊的效果:一个非常简单的例子,当你在一群鸽子中扔一块食物时,虽然只有一只鸽子最终会抓住食物,所有的鸽子都会惊慌失措地打架,没有抓住.

也就是说,当服务器1节点发生变化时,将通知剩余的99个服务器,但只会成功创建一个服务器,因此98仍然需要等待监听器,因此为了应对这种情况,需要临时序列节点。 p>

一般的想法是,在所有99个服务器都收听节点之前,现在每个服务器都会监听自身前面的节点。

假设100台服务器同时发送请求。这时,将在/zkjjj节点下创建100个临时顺序节点/zkjjj /,/zkjjj /,直到数字:java Xiaoma Ge

周一至周日早九点半!下午三点半!精品技术文章准时送上!!!

十余年BAT架构经验倾囊相授