原创 | 大数据入门基础系列之ZooKeeper如何实现分布式锁
Posted 大数据躺过的坑
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原创 | 大数据入门基础系列之ZooKeeper如何实现分布式锁相关的知识,希望对你有一定的参考价值。
在前面的博文里,我已经介绍了
分布式锁介绍
分布式锁主要用于在分布式环境中保护跨进程、跨主机、跨网络的共享资源实现互斥访问,以达到保证数据的一致性。
在昨天
里,初步谈及到了分布式环境下的这个锁叫作分布式锁。
为什么要分布式锁?
首先,说个非常普通直白的场景。
首先假设有两个线程, 两个线程要同时到mysql中更新一条数据, 对数据库中的数据进行累加更新。由于在分布式环境下, 这两个线程可能存在于不同的机器上的不同jvm进程中, 所以这两个线程的关系就是垮主机跨进程, 使用java中的synchronized锁是搞不定的。
主要利用了zookeeper的临时有序节点的特性和watcher监视器。
我们认为最小的节点具备执行权, 也就是获取到了锁。
临时节点有一个特点: 当创建临时节点的程序停掉之后, 这个临时节点就会消失。
监视器的特点: 可以给 zk 中的节点注册监视器, 监视这个节点的子节点的变化情况监视器注册一次, 只能使用一次。 多次使用需要多次注册 。
大致思路如下:
1: 当这两个线程去mysql更新数据之前, 先到zookeeper的/locks(永久节点)下面注册一个临时有序节点, 这样每个线程都注册了一个临时节点, 两个临时节点肯定是有序的。
线程1: /locks/000000002 线程2: /locks/000000001
2: 当每个线程注册完节点之后, 需要尝试获取锁, 这个时候, 哪个节点最小, 哪个线程就获取到锁, 这个时候, 线程2注册的节点最小, 所以线程2 就获取到锁, 执行更新数据库的代码, 更新完
成之后, 删除自己注册的临时节点。同时线程1会判断自己不是最小的, 所以就会监控比自己小1的那个节点, 当发现那个节点消失的话, 也就意味着它的节点就是最小的节点, 获取锁, 执行更新数据库的代码。
架构介绍
在介绍使用Zookeeper实现分布式锁之前,首先看当前的系统架构图。
左边的整个区域表示一个Zookeeper集群,locker是Zookeeper的一个持久节点,node_1、node_2、node_3是locker这个持久节点下面的临时顺序节点。client_1、client_2、client_n表示多个客户端,Service表示需要互斥访问的共享资源。
分布式锁获取思路
1.获取分布式锁的总体思路
在获取分布式锁的时候在locker节点下创建临时顺序节点,释放锁的时候删除该临时节点。
客户端调用createNode方法在locker下创建临时顺序节点,然后调用getChildren(“locker”)来获取locker下面的所有子节点,注意此时不用设置任何Watcher。客户端获取到所有的子节点path之后,如果发现自己在之前创建的子节点序号最小,那么就认为该客户端获取到了锁。如果发现自己创建的节点并非locker所有子节点中最小的,说明自己还没有获取到锁,
此时客户端需要找到比自己小的那个节点,然后对其调用exist()方法,同时对其注册事件监听器。
之后,让这个被关注的节点删除,则客户端的Watcher会收到相应通知,此时再次判断自己创建的节点是否是locker子节点中序号最小的,如果是最小的则获取到了锁,如果不是最小的则重复以上步骤继续获取到比自己小的一个节点并注册监听。当前这个过程中还需要许多的逻辑判断。
2.获取分布式锁的核心算法流程
下面用同一个流程图来分析获取分布式锁的完整算法,如下:
客户端A要获取分布式锁的时候首先到locker下创建一个临时顺序节点(node_n),然后立即获取locker下的所有(一级)子节点。此时因为会有多个客户端同一时间争取锁,因此locker下的子节点数量就会大于1。
对于顺序节点,特点是节点名称后面自动有一个数字编号, 先创建的节点数字编号小于后创建的,因此可以将子节点按照节点名称后缀的数字顺序从小到大排序,这样排在第一位的就是最先创建的顺序节点,此时它就代表了最先争取到锁的客户端。
此时判断最小的这个节点是否为客户端A之前创建出来的node_n,如果是则表示客户端A获取到了锁,如果不是则表示锁已经被其它客户端获取,因此客户端A要等待它释放锁,也就是等待获取到锁的那个客户端B把自己创建的那个节点删除。
此时就通过监听比node_n次小的那个顺序节点的删除事件来知道客户端B是否已经释放了锁,如果是,此时客户端A再次获取locker下的所有子节点,
再次与自己创建的node_n节点对比,直到自己创建的node_n是locker的所有子节点中顺序号最小的,此时表示客户端A获取到了锁。
基于Zookeeper的分布式锁的代码实现
1.定义分布式锁接口
2.定义一个简单的互斥锁
3. 分布式锁的实现细节
http://blog.csdn.net/sunfeizhi/article/details/51926396
zookeeper编程入门系列之zookeeper实现分布式进程监控和分布式共享锁(图文详解)
http://www.cnblogs.com/zlslch/p/7242381.html
同时,大家可以关注我的个人博客:
http://www.cnblogs.com/zlslch/ 和 http://www.cnblogs.com/lchzls/
本文版权归(大数据躺过的坑)作者和微信公众平台共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。 如果您认为这篇文章还不错或者有所收获,您可以通过下边的“打赏”功能 打赏我一杯咖啡【物质支持】,也可以点击右下角的【点赞】按钮【精神支持】,因为这两种支持都是我继续写作,分享的最大动力!
觉得不错,请点赞和留言↓↓↓
以上是关于原创 | 大数据入门基础系列之ZooKeeper如何实现分布式锁的主要内容,如果未能解决你的问题,请参考以下文章