用zookeeper实现分布式共享锁
什么是zookeeper以及它有什么功能
Zookeeper是一个分布式协调服务,就是为用户的分布式应用程序提供协调服务。
事物的出现肯定是有需求,zookeeper的需求是:当我们要向外部服务器采集数据时,我们是客户端,外部是服务端。4台客户端服务器需要实时采集来自4台服务端服务器的数据,数据量很大。
1.如果客户端一台服务器宕机了,那么继续采集的时候,服务器已经有很多数据了,无法跟上服务器步骤。新数据太多,还要补充下载老数据,就会一直下载不到最新进度。
这时候可以怎么做,keepalived是用在服务端的东西,保证服务器高可用。zookeeper和keepalived的区别就是zookeeper可以保存一些元数据,并且可以监听服务器的状态,当服务器宕机之后,更改该服务器在zookeeper中的状态,然后应用中访问的时候则不会访问这个状态的服务器。而keepalived只能做ip的自动切换,服务器的自动切换,保证服务高可用,它是自动切换服务器,zookeeper则使应用中根据服务器状态自主选择服务器。
1.如果配置客户端主从,则还需要自己去实现主从之间的心跳监听,记录该客户机下载到的位置,从机继续从这个位置开始下载。但是记录这个状态是记录在哪里呢?记录在第三方。
2.zookeeper就是这个第三方,当一台服务器挂掉之后,可以发出一个事件通知其他节点。
zookeeper做了什么?
1.保管数据
2.提供节点监听
zookeeper的数据特点:
* 永久数据PERSITEMT
* 永久序列数据PERSISTENT_SQUENCE
* 临时数据EPHEMERAL
* 临时序列数据EPHEMERAL_SQUENCE
* 序列数据:创建该名称的znode则会创建为递增的序列。set get /vc 只能操作序列最大的那个。
* 序列数据不能拥有子节点。Znode
zkCli.sh 客户端命令
|
|
分布式共享锁
分布式共享锁,是指在集群环境中使用一个锁来控制不同机器上的线程的顺序执行
在单机模式下,线程之间的同步可以通过jdk的lock对象或者synchronized来控制顺序执行。但是在分布式环境中,这种方式是行不通的。所以这时候就用一个第三方来存错锁,让第三方告诉你现在有没有使用锁的权利。
基于zk的分布式共享锁,主要是使用zk的临时序列节点类型。这种节点类型,当客户端会话结束后自动删除,多次创建这个节点它会在节点后增加数字,并且这个数字会增长。比如客户端1创建/a/b节点,则生成的是/a/b000,客户端2再创建/a/b节点,则生成的是/a/b001
zk提供了watch方法,用于监控某个节点是否发生改变。它也可以监控一个父节点下的子节点是否改变过,如/a下的子节点是否有过改变。
根据zookeeper的这两个功能可以想到分布式共享锁的两种实现方式:
1. 分布式环境中每个线程在启动时向zk中注册一条信息,生成一个序列号。然后每个线程判断自己是不是zk中序列号最小的那个(最先注册),序列号最小的获取到线程锁,如果是最小的,那么执行自己的业务逻辑,执行完毕之后删除自己的注册序列。如果不是序列最小的,那么获取到自己的前一个序列,并对这个序列进行监控(也就是对自己的前一个线程进行监控,它执行完毕后自己就该拥有锁了)。**此时直接在监控回调中执行本线程的业务逻辑即可,执行完毕删除本序列,方便下个线程执行**
2.分布式共享锁还可以利用监控父节点的子节点变化情况。同样的每一个线程启动时先注册信息到zookeeper,生成一个序列。当所有的线程注册完毕之后,开始监听子节点的变化情况,当子节点有变化,则判断是不是本线程在所有的子线程中序列号最小。如果是最小,则获取到锁,开始执行自己的逻辑,执行完毕删除本线程的注册信息。此时又触发了子节点变化事件,周而复始,最终到zk中没有子节点了 则执行完毕。
java代码展示zk分布式共享锁的使用
|
|