利用Zookeeper实现分布式锁

[文章目录]

单机-不加锁

先来复习一下:多线程修改同一个变量所导致的问题:

两个线程,分别进行了10000次x = x + 1操作,但是运行的结果确是12590,且每次运行结果都不一样。显然是两个线程并发访问变量所致。

单机-加锁

要想解决上面的问题,根据并发编程方面的知识,可以用synchronized关键字做线程间的同步,或者用其他JUC工具做同步。

这里使用可重入锁演示:

程序跑出了正确的结果:20000

分布式锁

如果把上面的程序部署在分布式的环境中,x是可以共同修改的变量(比如MySQL中的一条记录,程序从数据库读出后,修改值,再写回数据库),这个时候会发现做单机的线程间同步都无济于事,因为不同机器之间的线程仍然会产生同步问题。解决方法之一便是是分布式锁。

分布式锁可以有多重不同实现,而Zookeeper是可以专业解决分布式一致性问题的。

Apache Curator框架,是Zookeeper API的封装,其中就提供了分布式排他锁InterProcessMutex

下面利用这个框架来修复这个问题:

关于Curator框架的使用方法这里不再赘述,这里我们主要关注,如何自己用Zookeeper实现一个分布式锁?

利用Zookeeper实现分布式锁的原理

基本原理:

通过Zookeeper上的一个数据节点来表示一个锁,如/distributed_exclusive_lock/lock节点就可以被定义为一个锁。

在需要获取锁时,所有客户端通过尝试create()接口,创建临时节点。由于在Zookeeper中只会有一个客户端会创建成功同一个节点,我们认为成功创建节点的客户端获取到了分布式锁。而未获取到锁的客户端可以通过在这个节点上调用exists()接口注册Watcher,当接收到节点被删除通知时再尝试重新注册。

当客户端发上宕机与Zookeeper服务器断开连接时,临时节点自动删除,或者客户端主动删除lock节点时,代表释放了锁。

代码实现:

测试代码:

程序跑出了40000.







发表评论

电子邮件地址不会被公开。