Zookeeper

Zk概述

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

zookeeper=文件系统+通知机制

特点
  • Zookeeper:一个领导者,多个跟随着组成的集群。

  • 集群中只要有半数以上节点存活,Zookeeper集群就能正常服务。所以Zookeeper适合安装奇数台服务器

  • 全局数据一致:每个Server保存一份相同的数据副本,Client无论连接到哪个Server,数据都是一致的。

  • 更新请求顺序执行,来自同一个Client的更新请求按其发送顺序依次执行

  • 数据更新原子性次数据更新要么成功,要么失败

  • 实时性,在一定时间范围内,Client能读到最新的数据

解决问题
  • 统一命名服务
  • 统一配置管理
  • 同意集群管理
  • 服务器的动态上下线
选举机制
  1. 服务器1启动,发起一次选举此时服务器1票数一票,不够半数以上(3票),选举无法完成,服务器1状态保LOOKING;

  2. 服务器2启动,再发起一次选举。服务器1和2分别投自己一票并交换选票信息:此时服务器1发现服务器2的myid比自己目前投票推举的(服务器1)大,更改选票为推举服务器2。此时服务器1票数0票,服务器2票数2票,没有半数以上结果,选举无法完成,服务器1,2状态保持LOOKING

  3. 服务器3启动,发起一次选举。此时服务器1和都会更改选票为服务器3。此次投票结果:服务器1为0票,服务器2为0票,服务器3为3票。此时服务器3的票数已经超过半数,服务器3当选Leader。服务器1,2更改状态FOLLOWING,服务器3更改状态为LEADING:

  4. 服务器4启动,发起一次选举。此时服务器1,2,3已经不是LOOKING状态,不会更改选票信息。交换选票信息结果:服务器3为3票,服务器4为1票。此时服务器4服从多数,更改选票信息为服务器3,并更改状态为FOLLOWING;

非第一次启动:

在这里插入图片描述

public class zkClient {
    //一开始sessionTimeout=2000  怎么实验都失败设置成
    private String connectString="10.5.150.38:2181,10.5.82.210:2181,10.5.150.53:2181";
    private int sessionTimeout=80000;
    ZooKeeper zkClient;
    @Before
    public void init() throws IOException {
            zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
                //监听器
            @Override
            public void process(WatchedEvent watchedEvent) {
                System.out.println("----------");
                List<String> children = null;
                try {
                    children = zkClient.getChildren("/", true);
                    for (String child:children) {
                        System.out.println(child);
                    }
                    System.out.println("----------");
                } catch (KeeperException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }
    //TODO 创建节点
    @Test
    public void create() throws KeeperException,InterruptedException{
        String nodeCreated = zkClient.create("/atguigu", "ss.avi".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

    }
    //TODO 监听节点变化
    @Test
    public void getChildren() throws InterruptedException, KeeperException {
        List<String> children = zkClient.getChildren("/", true);
        for (String child:children) {
            System.out.println(child);
        }
        //延时
        Thread.sleep(Long.MAX_VALUE);
    }
    //TODO 判断节点是否存在
    @Test
    public void exist() throws InterruptedException, KeeperException {
        Stat stat = zkClient.exists("/atguigu", false);
        System.out.println(stat==null?"not exist":"exist");
    }
}

服务器动态上下线

服务端:

public class DistributeServer {
    private String connectString="10.5.150.38:2181,10.5.82.210:2181,10.5.150.53:2181";
    private int sessionTimeout=60000;
    private ZooKeeper zk;

    public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
        DistributeServer server = new DistributeServer();
        //1. 获取zk连接
        server.getConnect();
        //2.注册服务器到zk集群
        server.regist(args[0]);
        //3.启动业务逻辑(睡觉)
        server.busniess();

    }
    private void busniess() throws InterruptedException {
        Thread.sleep(Long.MAX_VALUE);
    }

    private void regist(String hostname) throws InterruptedException, KeeperException {
        String s = zk.create("/servers/"+hostname, hostname.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        System.out.println(hostname+"is online");
    }

    private void getConnect() throws IOException {

        zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {

            }
        });
    }
}

客户端:

public class DistributeClient {
    private String connectString="10.5.150.38:2181,10.5.82.210:2181,10.5.150.53:2181";
    private int sessionTimeout=80000;
    private ZooKeeper zk;

    public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
        DistributeClient client = new DistributeClient();
        //1.获取zk连接
        client.getConnect();
        //2.监听servers下面子节点的增加删除
        client.getServerList();
        //3.业务逻辑(睡觉)
        client.business();
    }

    private void business() throws InterruptedException {
        Thread.sleep(Long.MAX_VALUE);
    }

    private void getServerList() throws InterruptedException, KeeperException {
        List<String> children = zk.getChildren("/servers", true);
        ArrayList<Object> servers = new ArrayList<>();
        for (String child : children) {
            byte[] data = zk.getData("/servers/" + child, false, null);
            servers.add(new String(data));

        }
        System.out.println(servers);
    }

    private void getConnect() throws IOException {
        zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                try {
                    getServerList();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (KeeperException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

分布式锁案例

在这里插入图片描述

public class CuratorLockTest {
    public static void main(String[] args) {
        //创建分布式锁1
        InterProcessMutex lock1 = new InterProcessMutex(getCuratorFramework(), "/locks");
        //创建分布式锁2
        InterProcessMutex lock2 = new InterProcessMutex(getCuratorFramework(), "/locks");
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    lock1.acquire();
                    System.out.println("线程1 获取到锁");

                    lock1.acquire();
                    System.out.println("线程1 再次获取到锁");
                    Thread.sleep(5*1000);
                    lock1.release();
                    System.out.println("线程1 释放锁");
                    System.out.println("线程1 再次释放了锁");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    lock2.acquire();
                    System.out.println("线程2 获取到锁");

                    lock1.acquire();
                    System.out.println("线程2 再次获取到锁");
                    Thread.sleep(5*1000);
                    lock1.release();
                    System.out.println("线程2 释放锁");
                    System.out.println("线程2 再次释放了锁");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private static CuratorFramework getCuratorFramework() {
        //创建客户端
        ExponentialBackoffRetry policy = new ExponentialBackoffRetry(3000, 3);
        CuratorFramework client = CuratorFrameworkFactory.builder().connectString("10.5.150.38:2181,10.5.82.210:2181,10.5.150.53:2181")
                .connectionTimeoutMs(40000)
                .sessionTimeoutMs(2000)
                .retryPolicy(policy).build();

        //创建客户端
        client.start();
        System.out.println("zookeeper 启动成功");
        return client;
    }
}
  • 13
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值