zookeeper的基础使用

要面试才学的zookeeper+dubbo,搞起

Zookeeper

ZooKeeper是一种为分布式应用所设计的高可用、高性能且一致的开源协调服务,它提供了一项基本服务:分布式锁服务。由于ZooKeeper的开源特性,后来我们的开发者在分布式锁的基础上,摸索了出了其他的使用方法:配置维护、组服务、分布式消息队列、分布式通知/协调等

基础数据有4种类型:(-s 有序 -e 临时)

长久有序节点
临时有序节点
长久无序节点
临时有序节点

客户端基础命令

./zkServer.sh start 启动

./zkServer.sh restart  重启

./zkServer.sh stop 关闭

./zkCli.sh -server 127.0.0.1:2182  客户端通过ip连接服务器


addauth scheme(digest|auth) auth  //输入认证授权信息  添加用户以及密码到认证库

close
config [-c] [-w] [-s]
connect host:port

create [-s] [-e] [-c] [-t ttl] path [data] [acl] //创建节点

#默认创建的就是持久节点
create /test

#创建序号节点
create -s /test

#创建临时节点, 断开会话 在连接将会自动删除
create -e /temp

#临时序号节点
create -e -s /temp/seq

delete [-v version] path  //删除版本号为xx的节点

deleteall path [-b batch size]
delquota [-n|-b] path
get [-s] [-w] path   // get -w /xx  给xx节点设置watch时间  get -s /xx   获取xx详情  父节点添加watch时间
getAcl [-s] path  //获取节点得acl权限信息
getAllChildrenNumber path
getEphemerals path
history
listquota path

ls [-s] [-w] [-R] path  //查看下面的节点   子节点添加watch时间

printwatches on|off
quit
reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
redo cmdno
removewatches path [-c|-d|-a] [-l]

set [-s] [-v version] path data  //更新版本号为xx的节点

setAcl [-s] [-v version] [-R] path acl   设置节点得acl权限信息
setquota -n|-b val path

stat [-w] path  //获取节点信息状态

sync path
version

zookeeper提供的Java原生API(复制自己玩一下)

package com.exampletext.demo.zookeeper;


import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooKeeper;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.CountDownLatch;

/**
 * zookeeper原生API
 */
public class zookeeperTest {




    public static void main(String[] args) throws IOException, InterruptedException, KeeperException, NoSuchAlgorithmException {
        CountDownLatch countDownLatch = new CountDownLatch(1);

        String path="192.168.9.148:2181";
        //String path="192.168.43.46";
        ZooKeeper zooKeeper=new ZooKeeper(path, 2000000,new myWatcher());
        Thread.sleep(2000);
        long sessionId = zooKeeper.getSessionId();
        byte[] sessionPasswd = zooKeeper.getSessionPasswd();
        System.out.println(zooKeeper.getSessionId());
        System.out.println(zooKeeper.getState());
        Thread.sleep(2000);
        //zooKeeper.create("/zookeeper/java","123".getBytes(), Arrays.asList(), CreateMode.PERSISTENT);
//        System.out.println("准备重连");
//        ZooKeeper zooKeepe2r=new ZooKeeper(path, 2000000,new myWatcher(),sessionId,sessionPasswd);
//        Thread.sleep(2000);
//        System.out.println(zooKeeper.getSessionId());
//        System.out.println(zooKeeper.getState());


        //1.创建节点
//        zooKeeper.create("/zookeeper/mycallback",   //节点
//                "123".getBytes(),//数据
//                ZooDefs.Ids.OPEN_ACL_UNSAFE,//权限
//                CreateMode.PERSISTENT,new myZKCallback(),//回调函数
//                "传给你回调");//传给回调函数的值
//        Thread.sleep(2000);

        //2.获取节点
//        byte[] data = zooKeeper.getData("/zookeeper/callback", new myWatcher(countDownLatch), new Stat());
//
//        System.out.println(new String(data));
//        countDownLatch.await();


//        //3.修改节点
//        Stat stat = zooKeeper.setData("/zookeeper/callback", "bbb".getBytes(), 3);
//        System.out.println(stat.getVersion());


//        //4.删除节点
//        zooKeeper.delete("/zookeeper/callback",stat.getVersion());

        //5、获取子节点
//        List<String> childrens = zooKeeper.getChildren("/zookeeper",true);
//        for (String children : childrens) {
//            System.out.println(children);
//        }
        //List<String> children = zooKeeper.getChildren("/zookeeper/callback", new myWatcher(countDownLatch), new Stat());

        //6、判断节点是否存在
//        Stat stat = zooKeeper.exists("/zookeeper/nnnn", true);
//        if(stat==null){
//            System.out.println("是空!!!");
//        }
//        System.out.println(stat);
        
        
        //创建用户权限节点
//        List<ACL> aclList = new ArrayList<>();
//        String adminPassword = DigestAuthenticationProvider.generateDigest("admin:admin");
//        ACL acl = new ACL(ZooDefs.Perms.ALL,new Id("digest",adminPassword ));
//        aclList.add(acl);
//        String s = zooKeeper.create("/zookeeper/myuser", "2121".getBytes(), aclList, CreateMode.PERSISTENT);
//        zooKeeper.addAuthInfo("digest","admin:admin".getBytes());
//        byte[] data = zooKeeper.getData("/zookeeper/myuser", new myWatcher(), new Stat());
//
//        System.out.println(new String(data));

    }
}

重点使用 apache封装的curator命令

public class curatorTest {

    private  CuratorFramework curatorFramework;
    //private static final String path="192.168.43.46";
    private static final String path="192.168.9.148:2181";
    public  CuratorFramework client=null;

    curatorTest()   {
        //初始sleep时间,最大重试次数,最大重试时间
        //RetryPolicy retryPolicy=new ExponentialBackoffRetry(1000,3,5000);


        //重试3次,最大
        RetryPolicy retryPolicy=new RetryNTimes(3,5000);
        //curatorFramework.create().forPath(path)


        this.client = CuratorFrameworkFactory.builder()
                .connectString(path)
                .sessionTimeoutMs(10000)
                .retryPolicy(retryPolicy)
                //.namespace("curatorFather")   //命名空间 指定头节点,如果不指定,后面创建的节点都是以头节点开始
                .build();
        this.client.start();
    }


    public static void main(String[] args) throws Exception {
        curatorTest a=new curatorTest();
        System.out.println("连接---------");
        System.out.println(a.client.getState());
        boolean started = a.client.isStarted();
        System.out.println("状态"+started);

        //增
//        a.client.create()
//                .creatingParentsIfNeeded()
//                .withMode(CreateMode.PERSISTENT)
//                .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
//                .forPath("/mycurator/testa/a/b/c/1/2/3","123".getBytes());


        //改
//        a.client.setData()
//                .withVersion(0) //版本
//                .forPath("/mycurator/testa","456".getBytes());


        //删除
        a.client.delete()
                .guaranteed() //确保能删除
                .deletingChildrenIfNeeded()
                .withVersion(0) //版本
                .forPath("/dubbo");

       //读取节点信息
//        Stat stat=new Stat();
//        byte[] data = a.client.getData()
//                .storingStatIn(stat)
//                .forPath("/mycurator");
//        System.out.println("-----------"+new String(data));
//        System.out.println(stat.getVersion());



        //读取子节点
//        List<String> childNodes = a.client.getChildren().forPath("/mycurator");
//        System.out.println("打印子节点------------");
//        for (String childNode : childNodes) {
//            System.out.println(childNode);
//        }

        //判断是否存在
//        Stat stat = a.client.checkExists().forPath("/mycurator/c");
//        if(stat==null){
//            System.out.println("不存在");
//        }
//        System.out.println(stat);



        //设置监听  和原生API一样  只监听一次
       // a.client.getData().usingWatcher(new myWatcher()).forPath("/mycurator");


        //curator提供一次注册,n次监听
//        NodeCache nodeCache=new NodeCache(a.client, "/mycurator");
//        nodeCache.start(true);//是否获取该节点的值
//        if(nodeCache.getCurrentData()!=null){
//            System.out.println("初始化节点为:"+new String(nodeCache.getCurrentData().getData()));
//        }else {
//            System.out.println("初始化节点为空");
//        }
//        nodeCache.getListenable().addListener(new NodeCacheListener() {
//            @Override
//            public void nodeChanged() throws Exception {
//                if(nodeCache.getCurrentData()!=null){
//                    System.out.println("节点路径:"+nodeCache.getPath()+new String(nodeCache.getCurrentData().getData()));
//                }else {
//                    System.out.println("节点不存在了");
//                }
//            }
//        });

        //监听父节点
        //StartMode 初始化方式
        /**
         * POST_INITIALIZED_EVENT :异步初始化,初始化之后会触发
         * NORMAL:异步初始化
         * BUILD_INITIAL_CACHE:同步初始化
         */
//


        Thread.sleep(10000000);
        System.out.println("关闭---------");
        a.client.close();
        System.out.println("状态"+a.client.isStarted());


    }
}

自己的watcher类

public class myWatcher implements Watcher {

    private CountDownLatch countDownLatch;

    public myWatcher( ){
    }

    public myWatcher(CountDownLatch countDownLatch){
        this.countDownLatch=countDownLatch;
    }

    @Override
    public void process(WatchedEvent event) {
        System.out.println("watcher获取状态"+event.getState());
        System.out.println("watcher获取状态"+event);
        System.out.println("收到回调函数!!!!!!!!!!");
        if(Event.EventType.NodeCreated.equals(event.getType()) ){
            System.out.println("是创建新的节点"+ event.getPath());

        }else if(Event.EventType.NodeDataChanged.equals(event.getType())){
            System.out.println("是更改节点"+ event.getPath());

        }else if(Event.EventType.NodeChildrenChanged.equals(event.getType())){
            System.out.println("是更改子节点"+ event.getPath());

        }else if(Event.EventType.NodeDeleted.equals(event.getType())){
            System.out.println("节点被删除"+ event.getPath());
        }

        if(countDownLatch!=null){

            countDownLatch.countDown();
        }

    }
}

自己的回调函数(java基础API有提供回调函数 )

public class myZKCallback implements AsyncCallback.StringCallback {
    @Override
    public void processResult(int rc, String path, Object ctx, String name) {
        System.out.println("回调函数!!!"+rc);
        System.out.println("回调函数!!!"+path);
        System.out.println("回调函数!!!"+ctx);
        System.out.println("回调函数!!!"+name);
    }
}

重点提一下

zookeeper中watcher机制在zookeeper中只能触发一次。但是apache封装的curator提供了一次注册,多次监听的方式。包括 NodeCache 以及子节点 PathChildrenCache的方式。正因为机制,我们可以通过监听一个节点得变化,可以实现zookeeper动态更新配置的,分布式锁等等。

分布式锁

锁服务可以分为两类,一个是保持独占,另一个是控制时序。
对于第一类,我们将zookeeper上的一个znode看作是一把锁,通过createznode的方式来实现。所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁。用完删除掉自己创建的distribute_lock 节点就释放出锁。
对于第二类, /distribute_lock 已经预先存在,所有客户端在它下面创建临时顺序编号目录节点,和选master一样,编号最小的获得锁,用完删除,依次方便

zookeeper的ZAB协议(恢复模式和广播模式)

Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。
恢复模式:当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和leader的状态同步以后,恢复模式就结束了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值