zookeeper介绍

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了zookeeper介绍相关的知识,希望对你有一定的参考价值。

ZooKeeper的简介

ZooKeeper简介

ZooKeeper是一个为分布式应用提供分布式协调功能的开源(github)服务。

其主要应用在数据公布与订阅(配置中心),命名服务、分布式锁、集群管理与Master选举、分布式通知等。


在ZooKeeper官网是这样介绍ZooKeeper的:

ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. All of these kinds of services are used in some form or another by distributed applications. Each time they are implemented there is a lot of work that goes into fixing the bugs and race conditions that are inevitable. Because of the difficulty of implementing these kinds of services, applications initially usually skimp on them ,which make them brittle in the presence of change and difficult to manage. Even when done correctly, different implementations of these services lead to management complexity when the applications are deployed.
上述描写叙述说明像配置管理、命名等这些服务一般被分布式应用程序以某种形式使用,而在使用这些服务时,都会花费大量时间在修复bug和处理竞争条件上。同一时候也可能发送下述情况:
1. 当有变化发送时,难以调整,管理。


2. 这些服务的实现方式不同导致难以部署。
而ZooKeeper就是为了解决上述问题存在的。

它提供了一个统一、简洁的分布式协调服务,同一时候差点儿可在不论什么平台使用,可參考ZooKeeper管理员指南——部署与管理ZooKeeper

就像它所提供服务的对象是分布式应用。它自身也是分布式的。ZooKeeper通常会搭建成集群模式来提供服务,其节点个数一般为奇数个。这是因为其有一个重要特性,即:集群中仅仅有有过半机器是正常工作的,对外即是可用的(过半存活就可以用)。

数据模型

ZooKeeper数据模型的结构与文件系统十分类似,因此能够看成是一棵树。以下为其结构图
ZooKeeper\'s Hierarchical Namespace
当中每一个节点可称为ZNode,每一个节点都通过其路径唯一标识,如上图所看到的。每一个节点都能够存储数据,它被设计用来存储协同数据。如:状态信息。配置,本地信息等。所以存储的数据不多。

ZNode

ZNode能够分为两类:永久节点和暂时性节点(Ephemeral node)。
- 永久节点:须要显式创建和删除,在会话(session。在以下介绍)结束后仍然存在。


- 暂时节点:须要显式创建,在删除时,它能够被显式删除。但在使用时,我们一般使用它的特性:在session结束后自己主动删除。如在集群中可通过这特性推断机器是否宕机断开连接(无法维持session)。
同一时候另一个sequential的特性,通过设置此特性,在ZNode的名字后会自己主动加入自增数字sequenceNo。

每一个ZNode都由3部分组成:
1. 状态stat
2. 数据data
3. 孩子节点children

stat

节点状态,对节点的每次改变都会使状态改变,可由状态得知创建顺序等信息。
以下为灾zookeeper.jute中Stat结构

// information shared with the client
    class Stat {
        long czxid;      // created zxid
        long mzxid;      // last modified zxid
        long ctime;      // created
        long mtime;      // last modified
        int version;     // version
        int cversion;    // child version
        int aversion;    // acl version
        long ephemeralOwner; // owner id if ephemeral, 0 otw
        int dataLength;  //length of the data in the node
        int numChildren; //number of children of this node
        long pzxid;      // last modified children
}

可參考
znode的stat数据结构
http://coolxing.iteye.com/blog/1871328

session

client与zk集群通话时须要创建一个session,而每一个session都有一个超时时间t(

The current implementation requires that the timeout be a minimum of 2 times the tickTime (as set in the server configuration) and a maximum of 20 times the tickTime.

)。若zk在t内看不到与此session相关的信息,那么zk定义此session失效,而对于暂时节点这也意味着节点的删除,若设置了监控,那么设置监控的client就可以接受到消息。

监控

zk可对每一个节点设置监控,监视事件有:
- ZOO_CHANGED_EVENT 当前节点改变时触发,zoo_exists()和zoo_get()设置。


- ZOO_CHILD_EVENT 当前节点的子节点改变时触发。zoo_get_children() 和 zoo_get_children2()设置。
- ZOO_CREATED_EVENT 当前节点创建时触发,zoo_exists()设置。


- ZOO_DELETED_EVENT 当前节点删除时触发,zoo_exists()和zoo_get()。zoo_get_children() 和 zoo_get_children2()设置。
- ZOO_NOTWATCHING_EVENT 取消监控时触发
- ZOO_SESSION_EVENT 会话丢失触发

当监控事件发生便会调用监控回调函数,监控回调有2种:
一为全局监控回调,在调用zookeeper_init时设置。当调用上述函数并设置启用监控,当事件发生时便会调用此函数。
二为局部监控回调。仅仅与当前节点有关。

通过形如zoo_wget()设置(加入w)。

监控回调函数模式例如以下:

typedef void (*watcher_fn)(zhandle_t *zh, int type, int state, const char *path,void *watcherCtx);

note

  1. watcher被触发过一次即会被取消。要又一次设置。

    要实现持续watch,可通过在回调函数中又一次设置watch来实现。但在获得事件与再次设置watcher之间的那段时间,节点改变不可知。


    Because watches are one time triggers and there is latency between getting the event and sending a new request to get a watch you cannot reliably see every change that happens to a node in ZooKeeper. Be prepared to handle the case where the znode changes multiple times between getting the event and setting the watch again. (You may not care, but at least realize it may happen.)

  2. 在异步模式下提供其他回调函数。用于在异步请求完毕时调用

应用

以下对zk的应用进行一些简介: 參考[ZooKeeper原理及使用 ](http://blog.csdn.net/xinguan1267/article/details/38422149) [ZooKeeper典型应用场景一览](http://www.cnblogs.com/tommyli/p/3766189.html)

数据公布与订阅(配置中心)

数据公布与订阅即是通过把数据发送到zookeeper上,供订阅者动态获取数据。来实现数据的统一管理。如今的使用数据一般为配置信息。事实上现一般例如以下: 1. 把配置写入zookeeper; 2. 应用启动时读取配置并watch。 3. 当配置改变。触发事件,调用回调改动各应用配置。并继续watch。

分布式锁

排它锁

最简单排它锁实现
即在全部试图获取锁的client中,仅仅有一个能够成功获得锁。事实上现例如以下: 1. 全部client都去创建同一个ZNode(lock),类型EPHEMERAL,创建成功的那个client即获得锁。

2. 其他clientwatch那个ZNode。

3. 当ZNode删除。其他client在创建。 但此方法会有羊群效应。

羊群效应
当ZNode删除时,全部其他client都会收到此事件,但却仅仅有仅仅有一个节点获得锁。

排它锁改进
实现: 1. 创建锁节点/lock 2. 全部client都去创建锁节点的子节点。类型为EPHEMERAL_SEQUENCE。 3. 使lock下序号最小节点获取锁。 4. 其他节点watch比它小的节点。 5. 锁释放。则那个唯一监控节点被激活获得锁。 **note:查找资料后发现对于分布式锁的羊群效应用有着不同说法。另一种中羊群效应是因为在推断本节点是否是最小节点时每一个其他节点都需推断(在上级节点设置watch,导致都收到事件)而导致。故改为watch前一节点,可參考[shared locks](http://zookeeper.apache.org/doc/trunk/recipes.html#sc_recipes_Locks)**

共享锁

可參考[shared locks](http://zookeeper.apache.org/doc/trunk/recipes.html#Shared+Locks)

集群管理与Master选举

集群管理是利用暂时节点的特性和watch机制。**通过把机器注冊为某一永久节点的暂时子节点并watch永久节点**,则当机器宕机或因其他原因断开连接。session超时后,节点删除触发事件,或加入新节点也会触发事件,就可以知机器变化。 master选举实现方法与上述锁实现方法类似。仅仅是把获得锁的节点改为了成为master的节点。

參考资料

  1. Zookeeper C API 指南
  2. ZooKeeper管理员指南——部署与管理ZooKeeper
  3. ZooKeeper原理及使用
  4. 官方文档

以上是关于zookeeper介绍的主要内容,如果未能解决你的问题,请参考以下文章

Android课程---Android Studio使用小技巧:提取方法代码片段

Zookeeper源码阅读 Server端Watcher

[高级]Zookeeper介绍——Zookeeper概述

[高级]Zookeeper介绍——Zookeeper中的基本概念

VS code自定义用户代码片段snippet

zookeeper介绍