1.Zookeeper介绍:

(1)Zookeeper 作为一个分布式的服务框架,主要用来解决分布式集群中应用系统的一致性问题,它能提供基于类似于文件系统的目录节点树方式的数据存储,但是 Zookeeper 并不是用来专门存储数据的,它的作用主要是用来维护和监控你存储的数据的状态变化。通过监控这些数据状态的变化,从而可以达到基于数据的集群管理.

(2)Zookeeper典型的应用场景:

(1)统一命名服务:分布式应用中,通常需要有一套完整的命名规则,既能够产生唯一的名称又便于人识别和记住,通常情况下用树形的名称结构是一个理想的选择
(2)配置管理:配置的管理在分布式应用环境中很常见,多台机器配置不同,可以用zookeeper监控配置并触发配置变化事件。
(3)集群管理:如有多台 Server 组成一个服务集群,那么必须要一个“总管”知道当前集群中每台机器的服务状态,一旦有机器不能提供服务,集群中其它集群必须知道,从而做出调整重新分配服务策略。
(4)共享锁(Locks):共享锁在同一个进程中很容易实现,但是在跨进程或者在不同 Server 之间就不好实现了。Zookeeper 却很容易实现这个功能。
(5)队列管理:分布式队列,当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达,这种是同步队列。
(6)分布式通知/协调:ZooKeeper中特有watcher注册与异步通知机制,能够很好的实现分布式环境下不同系统之间的通知与协调,实现对数据变更的实时处理。

(3)节点类型

持久:创建之后一直存在,除非有删除操作,创建节点的客户端会话失效也不影响此节点。
持久顺序:跟持久一样,就是父节点在创建下一级子节点的时候,记录每个子节点创建的先后顺序,会给每个子节点名加上一个数字后缀。
临时:创建客户端会话失效(注意是会话失效,不是连接断了),节点也就没了。不能建子节点。

2.Zookeeper使用

节点增删的典型案例代码:

public class testhello {

    public static void main(String [] args) {
      try {
         // 创建一个与服务器的连接
         /**
         * 使用的参数含义如下:
         * 1.connectString:以逗号分隔的主机:端口号列表,每个对应一个ZooKeeper服务器。
         *   例如,10.0.0.1:2001,10.0.0.2:2002和10.0.0.3:2003表示三个节点的ZooKeeper ensemble的有效的主机:端口匹配对。
         * 2.sessionTimeout:这是以毫秒为单位的会话超时时间。这是ZooKeeper在宣布session结束之前,没有从客户端获得心跳的时间。
         * 3.watcher:一个watcher对象,如果创建,当状态改变和发生节点事件时会收到通知。这个watcher对象需要通过一个用户定义的类单独创建,
         *   通过实现Watcher接口并将实例化的对象传递给ZooKeeper构造方法。客户端应用程序可以收到各种类型的事件的通知,例如连接丢失、会话过期等。  
         * 
         * */
         ZooKeeper zk = new ZooKeeper("localhost:" + 2181, 
                1000, new Watcher() { 
                    // 监控所有被触发的事件
                    public void process(WatchedEvent event) { 
                        System.out.println("已经触发了" + event.getType() + "事件!"); 
                    } 
                }); 
         //创建一个目录节点
         zk.create("/testRootPath", "testRootData".getBytes(), Ids.OPEN_ACL_UNSAFE,
           CreateMode.PERSISTENT); 
         // 创建一个子目录节点
         zk.create("/testRootPath/testChildPathOne", "testChildDataOne".getBytes(),
           Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT); 
         System.out.println(new String(zk.getData("/testRootPath",false,null))); 
         // 取出子目录节点列表
         System.out.println(zk.getChildren("/testRootPath",true)); 
         // 修改子目录节点数据
         zk.setData("/testRootPath/testChildPathOne","modifyChildDataOne".getBytes(),-1); 
         System.out.println("目录节点状态:["+zk.exists("/testRootPath",true)+"]"); 
         // 创建另外一个子目录节点
         zk.create("/testRootPath/testChildPathTwo", "testChildDataTwo".getBytes(), 
           Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT); 
         System.out.println(new String(zk.getData("/testRootPath/testChildPathTwo",true,null))); 
         // 删除子目录节点
         zk.delete("/testRootPath/testChildPathTwo",-1); 
         zk.delete("/testRootPath/testChildPathOne",-1); 
         // 删除父目录节点
         zk.delete("/testRootPath",-1); 
         // 关闭连接
         zk.close();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (KeeperException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } 
    }
}