zookeeper

zookeeper是Apache Hadoop 项目下的一个子项目
是一个树型目录服务,是一个开源的分布式的分布式应用程序协调服务
zookeeper的主要功能: 配置管理 分布式锁 集群管理

zookeeper是一个树型目录服务 它的每一个节点都被称作ZNode,每个节点都会保存数据及节点信息(不仅可以当做一个目录,也可以当做一个文件,它即可以有自己的子节点,也可以存储少量数据1MB)
ZNode可以分为四种
persistent 持久化节点
ephemeral 临时节点 -e
persistent_sequential 持久化顺序节点 -s
ephemeral_sequential 临时顺序节点 -es

zookeeper服务器端的命令 进入bin 目录 ./zkServer.sh start 开启 stop 关闭 restart重启
zookeeper使用客户端连接服务器命令 ./zkCli.sh -server localhost:2181 就在本机的话直接 ./zkCli.sh 也可以
增删改查
create /app 123 在/节点下增加一个app节点 同时设置内容为123
create /app2 在/节点下增加一个app2节点
delete /app 删除/节点下的app 节点 如果里面还有子节点则 deleteall /app 或rmr /app
ls /app 查看/app 节点下的子节点
get /app 查看/app节点的数据内容
set /app 456 修改/app节点的内容为456

create 创建的节点默认是持久化节点
create -e 临时节点 当前会话关闭后,节点就消失了
create -s 创建顺序化节点
create -es 创建临时顺序化节点

curator是 zookeeper的java客户端
一般使用的构建者的方式来创建客户端,并且指定它的命名空间,这样以后在zookeeper的操作都默认是在 /命名空间 下操作,即创建的节点都是在/名称空间 节点下.

//重试策略 重试最多10次,每3秒一次
  RetryPolicy policy=new ExponentialBackoffRetry(3000,10);
//        CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient("192.168.111.30:2181", policy);

        CuratorFramework client = CuratorFrameworkFactory.builder()
                .connectString("192.168.111.30:2181")
                .retryPolicy(policy)
                .namespace("curator")
                .build();

        client.start();//建立连接
		client.close();//最后记得关闭连接
		

创建节点,如果没有设置数据则默认将客户端的ip地址设置为数据
切记java代码中zookeeper的版本和服务器的保持一致,否则可能报错

 //创建带数据的节点,不带数据的节点默认存储客户端的ip
        client.create().forPath("/app2","呵呵".getBytes());
        //创建什么类型的节点
        client.create().withMode(CreateMode.PERSISTENT).forPath("/app2","呵呵".getBytes());
        //删除节点
        client.delete().forPath("/app1");
        //创建多级节点
        client.create().creatingParentsIfNeeded().forPath("/app3/data1");
        //删除包含子节点的节点
        client.delete().deletingChildrenIfNeeded().forPath("/app3");
        //修改数据
        client.setData().forPath("/app3/data1","zhen".getBytes());
        //获取数据
        byte[] bytes = client.getData().forPath("/app3/data1");
        //获取数据及节点状态
        Stat status=new Stat();
        client.getData().storingStatIn(status).forPath("/app3/data1");
        int version = status.getVersion();
        //根据版本修改数据,如果版本不一致则修改失败,为了使其他客户端不干扰我们
        client.setData().withVersion(version).forPath("/app3/data1","zhen".getBytes());
		//guaranteed必须删除,本质就是不断重试,直到成功
		client.delete().guaranteed().deletingChildrenIfNeeded().forPath("/app3");
		
		//inBackground回调,可以在任意操作后面加
		   client.delete().guaranteed().deletingChildrenIfNeeded().inBackground(new BackgroundCallback() {
            public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
                System.out.println("我被删除了");
            }
        }).forPath("/app3");

zookeeper watch事件监听,核心功能. 可以实现发布订阅功能. 多个订阅者可以同时监听某一对象,当对象自身状态发生变化时,会通知所有订阅者

curator引入了cache来实现对zk服务端事件的监听
三种监听机制:
NodeCatch:只是监听某一特定的节点
PathChildrenCatch:监听某一ZNode的子节点
TreeCatch:监听整个树上的所有节点(不是整个zookeeper树,而是要监听的节点及其子节点),等于NodeCatch+PathChildrenCatch

	NodeCatch监听代码示例:
	  //创建监听对象
	  final NodeCache nodeCache=new NodeCache(client,"/app2");
	  //注册监听
    nodeCache.getListenable().addListener(new NodeCacheListener() {
        public void nodeChanged() throws Exception {
            System.out.println("发生了变化");
            ChildData currentData = nodeCache.getCurrentData();
            byte[] data = currentData.getData();

            System.out.println(new String(data));
        }
    });
	nodeCache.start(); //开启监听
	
	
	PathChildrenCatch监听代码示例:
	//创建监听对象
    PathChildrenCache pathChildrenCache=new PathChildrenCache(client,"/app2",true);
    //注册监听器
    pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
        public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
            System.out.println("监听到了变化");
            PathChildrenCacheEvent.Type type = event.getType();//获取子节点的状态
            if (PathChildrenCacheEvent.Type.CHILD_UPDATED.equals(type)){
                byte[] data = event.getData().getData();//获取子节点的内容
                System.out.println("子节点数据发生了修改,新数据为:"+new String(data));
            }

        }
    });
    //开启监听
    pathChildrenCache.start();

单机应用开发,涉及并发同步的时候,我们可以使用synchronized 或 lock,多机器涉及同步并发的时候就需要引入分布式锁
分布式锁解决的就是 跨机器的进程之间数据同步问题

分布式锁实现方式有多种
常见的有三种
1.基于缓存实现 利用redis Memcache redis性能比较高,但比起zk相对不太可靠 redis集群中一旦master挂掉,可能获取多个锁
2.基于zookeeper 性能较高且比较可靠
3.基于数据库的 悲观锁 乐观锁 性能太低,不建议使用

zookeeper分布式锁实现原理:
获取锁时,每个客户端会在指定的节点下创建一个临时顺序节点,并且与指定节点下的所有临时顺序节点比较顺序大小,最小的获取到锁.其它未获取到锁的客户端则对比自己小的相邻的顺序节点进行删除事件监听,一旦监听到则继续比较大小,自己最小则获取锁,大则继续监听比自己小且和自己相邻的节点删除事件.
释放锁则是将自己创建的临时顺序节点删除.
临时节点是为了保障即使客户端挂掉等异常情况,也能删除节点. 因为临时节点在客户端断开连接时会自动删除.
顺序节点是为了比较大小.

	InterProcessMutex 可重入互斥锁模拟卖票
	public class TickitSevice implements Runnable {
private int num=10;
private  InterProcessMutex lock;

public TickitSevice() {
    RetryPolicy policy=new ExponentialBackoffRetry(3000,10);
    CuratorFramework client = CuratorFrameworkFactory.builder()
            .connectString("192.168.111.30:2181")
            .retryPolicy(policy)
            .build();
    client.start();
    lock=new InterProcessMutex(client,"/lock");
}

public void run() {

    
    try {
		//获取锁
            lock.acquire(3, TimeUnit.SECONDS);
        if (num>0) {
            System.out.println(Thread.currentThread().getName()+"正在卖的票是:"+num);
            num--;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }finally {
        try {
            //释放锁
            lock.release();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

zookeeper集群 leader的选举,超过集群半数的投票则当选为leader,一旦选出leader则不再选举 其它的机器是 follower
投票原则有Serverid(服务器ID越大权重越大)及Zxid(数据ID,即服务器中存放的最大数据ID.值越大说明数据 越新,在选举算法中数据越新权重越大)
集群leader挂掉会自动选举新的leader. 但是前提是集群有半数以上机器存活,否则集群不可用,但是只要恢复到半数以上就可以马上选举出新的leader并恢复服务
集群的搭建,最少3台机器 3个zookeeper安装在3台服务器上,
与一台的区别是:
1.在每一个的配置文件里dataDir目录下创建一个myid文件,里面加入每个机器的id
2.在每个的zoo.cfg配置文件里配置上集群机器的列表
server.1=192.168.149.135:2881:3881
server.2=192.168.149.135:2882:3882
server.3=192.168.149.135:2883:3883
解释:server.服务器ID=服务器IP地址:服务器之间通信端口:服务器之间投票选举端口

zookeeper集群角色有三种
leader 领导者 处理事务性请求(增删改)并同步至其它机器,转发非事务性请求给其它机器,集群内部各服务器的调度者
follower 跟随者 处理非事务性请求,转发事务性请求给leader,参与leader选举
observer 观察者 处理非事务性请求,转发事务性请求给leader

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值