zoukankan      html  css  js  c++  java
  • zk实现服务选举

    非公平选举算法
    1)首先通过zk创建一个 /server 的PERSISTENT节点
    2)多台机器同时创建 /server/leader EPHEMERAL子节点
    3)子节点只能创建一个,后创建的会失败。创建成功的节点被选为leader节点
    4)所有机器监听 /server/leader 的变化,一旦节点被删除,就重新进行选举,抢占式地创建 /server/leader节点,谁创建成功谁就是leader。

    public static void main(String[] args) throws Exception {
        zk = new ZooKeeper("127.0.0.1:2181", FairSelectDemo.SESSION_TIMEOUT, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                System.out.println(event.getType() + "---" + event.getPath() + "---" + event.getState());
            }
        });
        //zk启动后试着进行选举
        selection();
    
        TimeUnit.HOURS.sleep(1); //阻塞住
        zk.close();
    }
    
    private static void selection() throws Exception {
        try {
            //1、创建/server(这个通过zkCli创建好了),参数3表示公有节点,谁都可以改
            zk.create("/server/leader", "node1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
            //2、没有抛异常,表示创建节点成功了
            System.out.println("选举成功");
        } catch (KeeperException.NodeExistsException e) {
            System.out.println("选举失败");
        } finally {
            //3、监听节点删除事件,如果删除了,重新进行选举
            zk.getData("/server/leader", new Watcher() {
                @Override
                public void process(WatchedEvent event) {
                    System.out.println(event.getType() + "---" + event.getPath() + "---" + event.getState());
                    try {
                        if (Objects.equals(event.getType(), Event.EventType.NodeDeleted)) {
                            selection();
                        }
                    } catch (Exception e) {
                    }
                }
            }, null);
        }
    }

    公平选举算法
    1)首先通过zk创建一个 /server 的PERSISTENT节点
    2)多台机器同时创建 /server/leader EPHEMERAL_SEQUENTIAL子节点
    3)/server/leader000000xxx 后面数字最小的那个节点被选为leader节点
    4)所有机器监听 前一个 /server/leader 的变化,比如 (leader00001监听 leader00002) 一旦节点被删除,就获取/server下所有leader,如果自己的数字最小那么自己就被选为leader

    public static void main(String[] args) throws Exception {
        zk = new ZooKeeper("127.0.0.1:2181", UnFairSelectDemo.SESSION_TIMEOUT, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                System.out.println(event.getType() + "---" + event.getPath() + "---" + event.getState());
            }
        });
    
        String leaderPath = "/server/leader";
    
        //1、创建/server(这个通过zkCli创建好了),注意这里是EPHEMERAL_SEQUENTIAL的
        //2、和非公平模式不一样,只需要创建一次节点就可以了
        nodeVal = zk.create(leaderPath, "node1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
    
        //System.out.println(nodeVal);
    
        //启动后试着进行选举
        selection();
    
        TimeUnit.HOURS.sleep(1); //阻塞住
        zk.close();
    }
    
    private static void selection() throws Exception {
        //2、遍历/server下的子节点,看看自己的序号是不是最小的
        List<String> children = zk.getChildren("/server", null);
        Collections.sort(children);
    
        String formerNode = "";  //前一个节点,用于监听
        for (int i = 0; i < children.size(); i++) {
            String node = children.get(i);
            if (nodeVal.equals("/server/" + node)) {
                if (i == 0) {
                    //第一个
                    System.out.println("我被选为leader节点了");
                } else {
                    formerNode = children.get(i - 1);
                }
            }
        }
        if (!"".equals(formerNode)) {
                //自己不是第一个,如果是第一个formerNode应该没有值
            System.out.println("我竞选失败了");
            //3、监听前一个节点的删除事件,如果删除了,重新进行选举
            zk.getData("/server/" + formerNode, new Watcher() {
                @Override
                public void process(WatchedEvent event) {
                    System.out.println(event.getType() + "---" + event.getPath() + "---" + event.getState());
                    try {
                        if (Objects.equals(event.getType(), Event.EventType.NodeDeleted)) {
                            selection();
                        }
                    } catch (Exception e) {
                    }
                }
            }, null);
        }
        //System.out.println("children:" + children);
    }

     但是其实上述的写法不是很严谨,比如公平选举算法,如果中间一个节点挂掉了,假设有01,02,03,04节点 比如02挂掉了,03一直监听着02,那么这个时候03应该改为监听01,否则,当01挂了,没有任何节点能被选为leader。 除此之外,各种异常状态都需要我们自己处理。


    原文:https://blog.csdn.net/haizeihdj/article/details/80796227

  • 相关阅读:
    Mybatis完成CRUD(四)
    Log4j日志配置
    Mybatis学习笔记(二)配置文件
    Mybatis学习笔记(一)入门例子
    jquery自动将form表单封装成json
    SpringMVC学习笔记(六)
    springMVC学习笔记(五)
    Oracle 数据库语句大全
    J a v a 的“多重继承”
    接口--interface
  • 原文地址:https://www.cnblogs.com/wujf/p/11008273.html
Copyright © 2011-2022 走看看