漫画:如何用Zookeeper实现分布式锁?

转载自   漫画:如何用Zookeeper实现分布式锁?







什么是临时顺序节点?


让我们来回顾一下Zookeeper节点的概念:




Zookeeper的数据存储结构就像一棵树,这棵树由节点组成,这种节点叫做Znode。


Znode分为四种类型:


1.持久节点 (PERSISTENT)


默认的节点类型。创建节点的客户端与zookeeper断开连接后,该节点依旧存在 。


2.持久节点顺序节点(PERSISTENT_SEQUENTIAL)


所谓顺序节点,就是在创建节点时,Zookeeper根据创建的时间顺序给该节点名称进行编号:




3.临时节点(EPHEMERAL) 


和持久节点相反,当创建节点的客户端与zookeeper断开连接后,临时节点会被删除:












4.临时顺序节点(EPHEMERAL_SEQUENTIAL) 


顾名思义,临时顺序节点结合和临时节点和顺序节点的特点:在创建节点时,Zookeeper根据创建的时间顺序给该节点名称进行编号;当创建节点的客户端与zookeeper断开连接后,临时节点会被删除。







Zookeeper分布式锁的原理


Zookeeper分布式锁恰恰应用了临时顺序节点。具体如何实现呢?让我们来看一看详细步骤:


获取锁


首先,在Zookeeper当中创建一个持久节点ParentLock。当第一个客户端想要获得锁时,需要在ParentLock这个节点下面创建一个临时顺序节点 Lock1。




之后,Client1查找ParentLock下面所有的临时顺序节点并排序,判断自己所创建的节点Lock1是不是顺序最靠前的一个。如果是第一个节点,则成功获得锁。




这时候,如果再有一个客户端 Client2 前来获取锁,则在ParentLock下载再创建一个临时顺序节点Lock2。




Client2查找ParentLock下面所有的临时顺序节点并排序,判断自己所创建的节点Lock2是不是顺序最靠前的一个,结果发现节点Lock2并不是最小的。


于是,Client2向排序仅比它靠前的节点Lock1注册Watcher,用于监听Lock1节点是否存在。这意味着Client2抢锁失败,进入了等待状态。




这时候,如果又有一个客户端Client3前来获取锁,则在ParentLock下载再创建一个临时顺序节点Lock3。




Client3查找ParentLock下面所有的临时顺序节点并排序,判断自己所创建的节点Lock3是不是顺序最靠前的一个,结果同样发现节点Lock3并不是最小的。


于是,Client3向排序仅比它靠前的节点Lock2注册Watcher,用于监听Lock2节点是否存在。这意味着Client3同样抢锁失败,进入了等待状态。




这样一来,Client1得到了锁,Client2监听了Lock1,Client3监听了Lock2。这恰恰形成了一个等待队列,很像是Java当中ReentrantLock所依赖的AQS(AbstractQueuedSynchronizer)。







释放锁


释放锁分为两种情况:


1.任务完成,客户端显示释放


当任务完成时,Client1会显示调用删除节点Lock1的指令。




2.任务执行过程中,客户端崩溃


获得锁的Client1在任务执行过程中,如果Duang的一声崩溃,则会断开与Zookeeper服务端的链接。根据临时节点的特性,相关联的节点Lock1会随之自动删除。




由于Client2一直监听着Lock1的存在状态,当Lock1节点被删除,Client2会立刻收到通知。这时候Client2会再次查询ParentLock下面的所有节点,确认自己创建的节点Lock2是不是目前最小的节点。如果是最小,则Client2顺理成章获得了锁。




同理,如果Client2也因为任务完成或者节点崩溃而删除了节点Lock2,那么Client3就会接到通知。




最终,Client3成功得到了锁。









Zookeeper和Redis分布式锁的比较


下面的表格总结了Zookeeper和Redis分布式锁的优缺点:




有人说Zookeeper实现的分布式锁支持可重入,Redis实现的分布式锁不支持可重入,这是错误的观点。两者都可以在客户端实现可重入逻辑。


在Apache的开源框架 Apache Curator 中,包含了对Zookeeper分布式锁的实现,有兴趣的小伙伴可以看看源码:


https://github.com/apache/curator/










什么是临时顺序节点?


让我们来回顾一下Zookeeper节点的概念:




Zookeeper的数据存储结构就像一棵树,这棵树由节点组成,这种节点叫做Znode。


Znode分为四种类型:


1.持久节点 (PERSISTENT)


默认的节点类型。创建节点的客户端与zookeeper断开连接后,该节点依旧存在 。


2.持久节点顺序节点(PERSISTENT_SEQUENTIAL)


所谓顺序节点,就是在创建节点时,Zookeeper根据创建的时间顺序给该节点名称进行编号:




3.临时节点(EPHEMERAL) 


和持久节点相反,当创建节点的客户端与zookeeper断开连接后,临时节点会被删除:












4.临时顺序节点(EPHEMERAL_SEQUENTIAL) 


顾名思义,临时顺序节点结合和临时节点和顺序节点的特点:在创建节点时,Zookeeper根据创建的时间顺序给该节点名称进行编号;当创建节点的客户端与zookeeper断开连接后,临时节点会被删除。







Zookeeper分布式锁的原理


Zookeeper分布式锁恰恰应用了临时顺序节点。具体如何实现呢?让我们来看一看详细步骤:


获取锁


首先,在Zookeeper当中创建一个持久节点ParentLock。当第一个客户端想要获得锁时,需要在ParentLock这个节点下面创建一个临时顺序节点 Lock1。




之后,Client1查找ParentLock下面所有的临时顺序节点并排序,判断自己所创建的节点Lock1是不是顺序最靠前的一个。如果是第一个节点,则成功获得锁。




这时候,如果再有一个客户端 Client2 前来获取锁,则在ParentLock下载再创建一个临时顺序节点Lock2。




Client2查找ParentLock下面所有的临时顺序节点并排序,判断自己所创建的节点Lock2是不是顺序最靠前的一个,结果发现节点Lock2并不是最小的。


于是,Client2向排序仅比它靠前的节点Lock1注册Watcher,用于监听Lock1节点是否存在。这意味着Client2抢锁失败,进入了等待状态。




这时候,如果又有一个客户端Client3前来获取锁,则在ParentLock下载再创建一个临时顺序节点Lock3。




Client3查找ParentLock下面所有的临时顺序节点并排序,判断自己所创建的节点Lock3是不是顺序最靠前的一个,结果同样发现节点Lock3并不是最小的。


于是,Client3向排序仅比它靠前的节点Lock2注册Watcher,用于监听Lock2节点是否存在。这意味着Client3同样抢锁失败,进入了等待状态。




这样一来,Client1得到了锁,Client2监听了Lock1,Client3监听了Lock2。这恰恰形成了一个等待队列,很像是Java当中ReentrantLock所依赖的AQS(AbstractQueuedSynchronizer)。







释放锁


释放锁分为两种情况:


1.任务完成,客户端显示释放


当任务完成时,Client1会显示调用删除节点Lock1的指令。




2.任务执行过程中,客户端崩溃


获得锁的Client1在任务执行过程中,如果Duang的一声崩溃,则会断开与Zookeeper服务端的链接。根据临时节点的特性,相关联的节点Lock1会随之自动删除。




由于Client2一直监听着Lock1的存在状态,当Lock1节点被删除,Client2会立刻收到通知。这时候Client2会再次查询ParentLock下面的所有节点,确认自己创建的节点Lock2是不是目前最小的节点。如果是最小,则Client2顺理成章获得了锁。




同理,如果Client2也因为任务完成或者节点崩溃而删除了节点Lock2,那么Client3就会接到通知。




最终,Client3成功得到了锁。









Zookeeper和Redis分布式锁的比较


下面的表格总结了Zookeeper和Redis分布式锁的优缺点:




有人说Zookeeper实现的分布式锁支持可重入,Redis实现的分布式锁不支持可重入,这是错误的观点。两者都可以在客户端实现可重入逻辑。


在Apache的开源框架 Apache Curator 中,包含了对Zookeeper分布式锁的实现,有兴趣的小伙伴可以看看源码:


https://github.com/apache/curator/





本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/328317.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用CoreProfiler/NanoProfiler实现跨平台amp;应用的整合性能调试

NanoProfiler是一个开源.NET性能调试类库,CoreProfiler是其.NET Core版本的实现。在之前的一些文章中,我曾介绍过NanoProfiler的主要使用方式,以及如何为生产环境,基于ELK对应用性能进行调试和监控。不过,对于一般的用…

oracle授权序列,oracle 第二集序列

方案一:直接授权法1.用happyy2165登录,之后,授权grant select on HAPPYY2165.STUDENT to scott2.用scott登录,用如下代码去访问Student表select * from HAPPYY2165.student方式二:通过角色去控制1.自定义角色 role_tes…

两种播放m3u8链接的方法

两种播放m3u8链接的方法 置顶 2018年12月21日 10:38:10 Saddyの云 阅读数:15200 本文将提供两种方法介绍如何播放m3u8链接 第一种是添加浏览器插件 Native HLS Playback ,此处以Firefox举例(谷歌浏览器也可以用这个插件,苹果电脑自带浏览器…

漫画:什么是ZooKeeper

转载自 漫画:什么是ZooKeeperZookeeper的数据模型Zookeeper的数据模型是什么样子呢?它很像数据结构当中的树,也很像文件系统的目录。树是由节点所组成,Zookeeper的数据存储也同样是基于节点,这种节点叫做Znode。但是&a…

异步性能:了解 Async 和 Await 的成本

异步编程长时间以来一直都是那些技能高超、喜欢挑战自我的开发人员涉足的领域 — 这些人愿意花费时间,充满热情并拥有心理承受能力,能够在非线性的控制流程中不断地琢磨回调,之后再回调。 随着 Microsoft .NET Framework 4.5 的推出&#xff…

什么叫做在oracle目录下,ORACLE directory 目录

Create directory让我们可以在Oracle数据库中灵活的对文件进行读写操作,极大的提高了Oracle的易用性和可扩展性。其语法为:CREATE [OR REPLACE] DIRECTORY directory AS pathname;本案例具体创建如下:create or replace directory exp_dir as /tmp;目录创建以后&…

银行营业网点管理系统——dao包(BaseDao)

package BranchesMgr.dao; /*** 数据库操作类* author Administrator**/ import java.sql.*; import java.util.List; public class BaseDao {Connection connnull;PreparedStatement psnull;ResultSet rsnull;public void getConnection(){try {Class.forName("com.micro…

netapp做内网穿透有问题

内网穿透 vue 返回 invalid host header 2019年03月17日 16:05:29 renzhehongyi 阅读数:1926收起 个人分类: 互联网Vue 问题:使用花生壳内网穿透只返回304,invalid host header 原因:新版的webpack-dev-server出于…

Visual Studio 15 Preview 5 发布 大幅提升性能

Visual Studio 15 Preview 5 发布了,该版本包括许多新的提升和 bug 修复。 微软发布了 Visual Studio 15 的第 5 个预览版本。据微软描述,Preview 5 的亮点是在性能和内存效率方面迈进了一大步,尤其是在加载一些插件方面,可以观看…

Spring Boot 单元测试详解+实战教程

转载自 Spring Boot 单元测试详解实战教程Spring Boot 的测试类库 Spring Boot 提供了许多实用工具和注解来帮助测试应用程序,主要包括以下两个模块。 spring-boot-test:支持测试的核心内容。spring-boot-test-autoconfigure:支持测试的自动…

oracle修改filesystem,(转):oracle、filesystem、backup日常巡检脚本

1.总脚本xunjian.codeexport PS1"hostname$"[$PWD] umask 022cd /u02/xunjian#######################xunjian check##################################################----1. filesystem check 文件系统检查rm -f /u02/xunjian/devdb2_xunjian.txtecho "1.fi…

华为校招2019

面试是在一个酒店里面的,人很多,面试和流水线一样有20-30个面试官同时进行,面试分成2轮一轮是技术面,一轮是主面。 一面是技术面是一个比较年轻的面试官,面试时间在30-60分钟,先自我介绍,问了…

EQueue 2.3.2版本发布(支持高可用)

前言 前段时间针对EQueue的完善终于告一段落了,实在值得庆祝,自己的付出和坚持总算有了成果。这次新版本主要为EQueue实现了集群功能,基本实现了Broker的高可用。另外还增加了很多实用的功能,对性能也做了很多优化。总之&#xff…

oracle spacial,Oracle Spacial(空间数据库)geometry元数据结构

geometry元数据内容每一维的名称、上下限和容差值存放在系统表中,用户不能直接访问,通过三个视图来存取:USER_SDO_GEOM_METADATA,可以更新ALL_SDO_GEOM_METADATA,只可以查询DBA_SDO_GEOM_METADATA,DBA可查询…

银行营业网点管理系统——dao包(BranchesDao)

package BranchesMgr.dao;import java.util.List;import BranchesMgr.entity.Branches;/*** 网点信息表的借口* author Administrator**/ public interface BranchesDao {//查询所有网点信息List<Branches> getBranches();//根据id查询指定的网点信息Branches BranchesIn…

这 30 个常用的 Maven 命令你必须熟悉

转载自 这 30 个常用的 Maven 命令你必须熟悉maven 命令的格式为 mvn [plugin-name]:[goal-name]&#xff0c;可以接受的参数如下。-D 指定参数&#xff0c;如 -Dmaven.test.skiptrue 跳过单元测试&#xff1b; -P 指定 Profile 配置&#xff0c;可以用于区分环境&#xff1b…

阿里云服务器本地连接(windows) 阿里云服务器和本地的磁盘共享数据

一、向Windows服务器上传下载文件方式 方法有很多种&#xff0c;此处介绍远程桌面的本地资源共享方法。 1、运行mstsc&#xff0c;连接远程桌面的时候&#xff0c;点“选项>>” 2、“本地资源”-->详细信息。 3、“磁盘驱动器”前面打钩。 4、连接远程电脑后&#…

10月15日 2016中国开源年会期待您的参与

由开源社主办的中国开源年会2016 (COSCon16 - China Open Source Conference 2016) 即将于今年10月15日-16日在北京举办。 这是一场-- 跨社区&#xff0c;跨技术领域&#xff0c;跨国度的年度盛会&#xff01; 您可以与真正的开源贡献者和参与者&#xff0c;直接互动&#xff0…

eclipse 创建ssm spring+springmvc+mybatis 实现登录注册

首先找到菜单栏中的Window 下的Preference 然后找到Server 下的 Runtime Environment 然后点击左侧的Add,因为小编用的是Tomcat 9.0 的&#xff0c;你的就要看自己的了&#xff0c;然后Next 然后找到自己存放Tomcat 的路径&#xff0c;然后Finish &#xff0c;最后Apply…

oracle 10741 trace,RedHat5.3上安装Oracle 10.2.0.1

RedHat 5.3上安装Oracle 10.2.0.11、系统环境&#xff1a;RedHat 5.3内存16G交换分区8G2、必须安装如下包&#xff0c;版本可不一样gcc-3.2.3-2make-3.79binutils-2.11openmotif-2.2.2-16setarch-1.3-1compat-gcc-7.3-2.96.122compat-gcc-c-7.3-2.96.122compat-libstdc-7.3-2.9…