zookeeper机制的原理是什么

17次阅读
没有评论

今天就跟大家聊聊有关 zookeeper 机制的原理是什么,可能很多人都不太了解,为了让大家更加了解,丸趣 TV 小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

zookeeper 机原理(长连接):

Zookeeper  并不是用来专门存储数据的,它的作用主要是用来维护和监控你存储的数据的状态变化。通过监控这些数据状态的变化,从而可以达到基于数据的集群管。当对目录节点监控状态打开时,一旦目录节点的状态发生变化,Watcher  对象的  process  方法就会被调用。

(任何实现 org.apache.zookeeper.Watcher 类,持有 zookeeper 实例对象,只要调用 zookeeper 的方法,并且监控相应节点类型,

  那么 zookeeper 服务端该节点发生变化会通知到观察者(观察者重写方法 process 会被调用))

zk = new ZooKeeper(zookeeperQuorum, sessionTimeout, this); 

zookeeperQuorum=IP+ 端口(xxx.xxx.xxx.xxx:2181,xxx.xxx.xxx.xxx:2181,xxx.xxx.xxx.xxx:2181)多个逗号隔开

可以设置观察的操作:exists,getChildren,getData

可以触发观察的操作:create,delete,setData

zookeeper 观察机制;

服务端只存储事件的信息, 客户端存储事件的信息和 Watcher 的执行逻辑.ZooKeeper 客户端是线程安全的每一个应用只需要实例化一个 ZooKeeper 客户端即可,同一个 ZooKeeper 客户端实例可以在不同的线程中使用。ZooKeeper 客户端会将这个 Watcher 对应 Path 路径存储在 ZKWatchManager 中, 同时通知 ZooKeeper 服务器记录该 Client 对应的 Session 中的 Path 下注册的事件类型。当 ZooKeeper 服务器发生了指定的事件后,ZooKeeper 服务器将通知 ZooKeeper 客户端哪个节点下发生事件类型,ZooKeeper 客户端再从 ZKWatchManager 中找到相应 Path,取出相应 watcher 引用执行其回调函数 process。

源码分析如:

zookeeper.java

 wcb = new DataWatchRegistration(watcher, clientPath);// 将观察者引用和节点路径绑定

ZKWatchManager.java

 public void register(int rc) {

            if (shouldAddWatch(rc)) {

                Map String, Set Watcher watches = getWatches(rc);

                synchronized(watches) {

                    Set Watcher watchers = watches.get(clientPath);

                    if (watchers == null) {

                        watchers = new HashSet Watcher

                        watches.put(clientPath, watchers);//key 为 path,value 为 watcher 引用

                    }

                    watchers.add(watcher);

                }

            }

        }

znode 存储数据量最大:jute.maxbuffer 默认 1M

通知注意点:

1. 一次性触发器(可以通过定时调用方法 get() 或者 exists()获取触发事件,手动访问触发,)
client 在一个节点上设置 watch,随后节点内容改变,client 将获取事件。当节点内容再次改变,client 不会获取这个事件,除非它又执行了一次读操作并设置 watch

2. 发送至 client,watch 事件延迟
watch 事件异步发送至观察者。比如说 client 执行一次写操作,节点数据内容发生变化,操作返回后,而 watch 事件可能还在发往 client 的路上。这种情况下,zookeeper 提供有序保证:client 不会得知数据变化,直到它获取 watch 事件。网络延迟或其他因素可能导致不同 client 在不同时刻获取 watch 事件和操作返回值。

循环调用:

Watcher watcher = loopWatch?this:null;

byte[] newdata = keeper.getData(path, watcher, null);// 实现改变再次提醒!!

应用场景:

Zookeeper  从设计模式角度来看,是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper  就将负责通知已经在  Zookeeper  上注册的那些观察者做出相应的反应。

通知者模式:

发布者持有订阅者的句柄引用,一单状态变化,调用订阅者接口,实现通知模式调用。

zookeeper 操作 API:

客户端要连接  Zookeeper  服务器可以通过创建  org.apache.zookeeper. ZooKeeper  的一个实例对象,然后调用这个类提供的接口来和服务器交互

ZooKeeper  主要是用来维护和监控一个目录节点树中存储的数据的状态。

目录节点类型:

PERSISTENT:持久化目录节点,这个目录节点存储的数据不会丢失

PERSISTENT_SEQUENTIAL:顺序自动编号的目录节点,这种目录节点会根据当前已近存在的节点数自动加  1

EPHEMERAL:临时目录节点,一旦创建这个节点的客户端与服务器端口也就是  session  超时或者断口,这种节点会被自动删除

EPHEMERAL_SEQUENTIAL:临时自动编号节点

节点状态(Stat):

  private long czxid;

  private long mzxid;

  private long ctime;

  private long mtime;

  private int version;

  private int cversion;

  private int aversion;

  private long ephemeralOwner;

  private int dataLength;

  private int numChildren;

  private long pzxid;

Watch 事件类型

ZOO_CREATED_EVENT:节点创建事件,需要 watch 一个不存在的节点,当节点被创建时触发,此 watch 通过 zoo_exists()设置
ZOO_DELETED_EVENT:节点删除事件,此 watch 通过 zoo_exists() 或 zoo_get()设置
ZOO_CHANGED_EVENT:节点数据改变事件,此 watch 通过 zoo_exists() 或 zoo_get()设置
ZOO_CHILD_EVENT:子节点列表改变事件,此 watch 通过 zoo_get_children() 或 zoo_get_children2()设置
ZOO_SESSION_EVENT:会话失效事件,客户端与服务端断开或重连时触发
ZOO_NOTWATCHING_EVENT:watch 移除事件,服务端出于某些原因不再为客户端 watch 节点时触发

一:集群管理:

1 监控服务器健康

它们的实现方式都是在  Zookeeper  上创建一个  EPHEMERAL  类型的目录节点,然后每个  Server  在它们创建目录节点的父目录节点上调用  getChildren(String path, boolean watch)  方法并设置  watch  为  true,由于是  EPHEMERAL  目录节点,当创建它的  Server  死去,这个目录节点也随之被删除,所以  Children  将会变化,这时  getChildren 上的  Watch  将会被调用,所以其它  Server  就知道已经有某台  Server  死去了。新增  Server  也是同样的原理。

2 Master 选举

Zookeeper  如何实现  Leader Election,也就是选出一个  Master Server。和前面的一样每台  Server  创建一个  EPHEMERAL  目录节点,不同的是它还是一个  SEQUENTIAL  目录节点,所以它是个  EPHEMERAL_SEQUENTIAL  目录节点。之所以它是  EPHEMERAL_SEQUENTIAL  目录节点,是因为我们可以给每台  Server  编号,我们可以选择当前是最丸趣 TV 小编号的  Server  为  Master,假如这个最丸趣 TV 小编号的  Server  死去,由于是  EPHEMERAL  节点,死去的  Server  对应的节点也被删除,所以当前的节点列表中又出现一个最丸趣 TV 小编号的节点,我们就选择这个节点为当前  Master。这样就实现了动态选择  Master,避免了传统意义上单  Master  容易出现单点故障的问题。

二:分布式锁

在同一个进程中很容易实现,但是在跨进程或者在不同  Server  之间就不好实现了。Zookeeper  却很容易实现这个功能,实现方式也是需要获得锁的  Server  创建一个  EPHEMERAL_SEQUENTIAL  目录节点,然后调用  getChildren 方法获取当前的目录节点列表中最小的目录节点是不是就是自己创建的目录节点,如果正是自己创建的,那么它就获得了这个锁,如果不是那么它就调用  exists(String path, boolean watch)  方法并监控  Zookeeper  上目录节点列表的变化,一直到自己创建的节点是列表中最丸趣 TV 小编号的目录节点,从而获得锁,释放锁很简单,只要删除前面它自己所创建的目录节点就行了  n Server 也是同样的原理。

看完上述内容,你们对 zookeeper 机制的原理是什么有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注丸趣 TV 行业资讯频道,感谢大家的支持。