zookeeper java代码实现master 选举

1,master选举使用场景及结构

现在很多时候我们的服务需要7*24小时工作,假如一台机器挂了,我们希望能有其它机器顶替它继续工作。此类问题现在多采用master-salve模式,也就是常说的主从模式,正常情况下主机提供服务,备机负责监听主机状态,当主机异常时,可以自动切换到备机继续提供服务(这里有点儿类似于数据库主库跟备库,备机正常情况下只监听,不工作),这个切换过程中选出下一个主机的过程就是master选举。
对于以上提到的场景,传统的解决方式是采用一个备用节点,这个备用节点定期给当前主节点发送ping包,主节点收到ping包后会向备用节点发送应答ack,当备用节点收到应答,就认为主节点还活着,让它继续提供服务,否则就认为主节点挂掉了,自己将开始行使主节点职责。如图1所示:

2,master 选择策略和zookeeper 分布式锁的思路大致一样

package com.aiyuesheng.controller;

import java.util.concurrent.CountDownLatch;

import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.exception.ZkException;
import org.I0Itec.zkclient.exception.ZkInterruptedException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationRunner implements ApplicationRunner {

    private CountDownLatch countDownLatch = null;

    String PATH = "/master";

    @Value("${server.port}")
    private String serverPort;

    ZkClient zkClient = new ZkClient("127.0.0.1:2181");

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("初始化.........");

        // 2,zookeeper实现监听功能,当主节点挂了之后,继续选举
        if (zkClient != null) {
            // 1,在初始化过程中创建一个临时节点,如果成功,则选为master节点
            election();
            // zookeeper 数据监听的接口
            IZkDataListener izkDataListener = new IZkDataListener() {
                public void handleDataChange(String arg0, Object arg1) throws Exception {

                }
                public void handleDataDeleted(String path) throws Exception {
                    // 一直在监听,节点有变化的时候原子量就是-1
                    if (countDownLatch != null) {
                        countDownLatch.countDown();
                    }
                }

            };
            //zkClient会去监听
            zkClient.subscribeDataChanges(PATH, izkDataListener);
            if (zkClient.exists(PATH)) {
                countDownLatch = new CountDownLatch(1);
                try {
                    // 一直进行等待,等待监听的路径有变化
                    countDownLatch.await();
                    election();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            // 删除监听
            zkClient.unsubscribeDataChanges(PATH, izkDataListener);

        }

    }

    private void election() {
        try {
            zkClient.createEphemeral(PATH, serverPort);
            System.out.println("选举成功");
            ZookeeperMaster.masterIsAlive = true;
        } catch (Exception e) {
            ZookeeperMaster.masterIsAlive = false;
        }
    }

}
public class ZookeeperMaster {
    
    public static boolean masterIsAlive = false;

}

 

posted @ 2019-08-12 17:38  Chris,Cai  阅读(1530)  评论(0编辑  收藏  举报