zkClient实现master选举

master选举

master选举

master选举

zkClient实现maste选举

public class MasterServer {

    private ZkClient zkClient;
    //争抢的一个master节点
    private final String MASTER_NODE = "/master";
    //server链接字符串
    private static final String CONNECTION_STRING = "139.199.182.26:5000,139.199.182.26:5001,139.199.182.26:5002";
    //超时时间
    private static final int SESSION_TIMEOUT = 5000;
    //争抢master节点服务器信息
    private ServerData serverData;
    //争抢到的master节点服务器信息
    private ServerData masterData;
    //服务器是否启动
    private volatile boolean running = false;
    //master节点的监听事件
    IZkDataListener dataListener;

    private ScheduledExecutorService scheService = Executors.newScheduledThreadPool(1);


    public MasterServer(ZkClient zkClient, ServerData serverData) {
        this.zkClient = zkClient;
        this.serverData = serverData;//标识来争抢master节点的服务
        dataListener = new IZkDataListener() {
            @Override
            public void handleDataChange(String dataPath, Object data) throws Exception {

            }

            @Override
            public void handleDataDeleted(String dataPath) throws Exception {
                //监听节点删除时间
                scheService.schedule(new Runnable() {
                    @Override
                    public void run() {
                        takeMaster();
                    }
                }, 5, TimeUnit.SECONDS);
            }
        };
    }

    //开始争抢master的方法
    public void start() {
        if (running) {
            throw new RuntimeException("服务已经启动了");

        }
        running = true;
        zkClient.subscribeDataChanges(MASTER_NODE, dataListener);
        takeMaster();
    }

    //停止
    public void stop() {
        if (!running) {
            throw new RuntimeException("服务已经停止了");
        }
        running = false;
        zkClient.subscribeDataChanges(MASTER_NODE, dataListener);
        releaseMaster();
    }

    private void takeMaster() {
        if (!running) {
            return;
        }
        try {
            System.out.println(serverData.getServerName() + "来抢master节点");
            //用到了一个临时节点的特性
            zkClient.createEphemeral(MASTER_NODE, serverData);
            masterData = serverData;
            System.out.println(serverData.getServerName() + "争抢到了master节点");
            scheService.schedule(new Runnable() {
                @Override
                public void run() {
                    if (checkMaster()) {
                        zkClient.delete(MASTER_NODE);
                    }
                }
            }, 5, TimeUnit.SECONDS);
        } catch (ZkNodeExistsException e) {
            //如果节点创建过程中提示节点已经存在的异常,那这个时候意味着master节点是存在的(特性,节点唯一性)
            //读取当前master节点的服务器信息
            ServerData serverData = zkClient.readData(MASTER_NODE);

            if (serverData == null) {
                //在读取过程中,发现master节点已经被释放
                takeMaster();
            } else {
                masterData = serverData;
            }
        }

    }

    //释放master
    private void releaseMaster() {
        if (checkMaster()) {
            zkClient.delete(MASTER_NODE);
        }
    }

    //校验当前的服务器是不是master
    private boolean checkMaster() {
        try {
            //读取当前master节点的数据,并赋值给masterdata
            ServerData ms = zkClient.readData(MASTER_NODE);
            masterData = ms;
            //这个时候,如果master节点的数据和当前过来争抢master节点的服务器的数据是一样的话,那么意味
            //当前的serverData就是master
            if (masterData.getServerName().equals(serverData.getServerName())) {
                return true;
            }
            return false;
        } catch (ZkNoNodeException e) {
            return false;
        } catch (ZkInterruptedException e) {
            return checkMaster();
        } catch (ZkException e) {
            return false;
        }
    }

    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        Semaphore semaphore = new Semaphore(10);
        for (int i = 0; i < 10; i++) {
            final int idx = i;
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    try {
                        semaphore.acquire();
                        //初始化一个zkclient的连接
                        ZkClient zk = new ZkClient(CONNECTION_STRING,
                                SESSION_TIMEOUT, SESSION_TIMEOUT,
                                new SerializableSerializer());
                        //定义一台争抢master节点的服务器
                        ServerData serverData = new ServerData();
                        serverData.setServerId(idx);
                        serverData.setServerName("#server-" + idx);
                        //初始化一个争抢master节点的服务
                        MasterServer ms = new MasterServer(zk, serverData);
                        ms.start();
                        semaphore.release();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            service.execute(runnable);
        }
        service.shutdown();
    }
}

/**
 * 每台服务器自身属性
 *@author hao.wang
 *@date 2017/1/20 15:37
 */
public class ServerData implements Serializable{

    private int serverId;

    private String serverName;

    public int getServerId() {
        return serverId;
    }

    public void setServerId(int serverId) {
        this.serverId = serverId;
    }

    public String getServerName() {
        return serverName;
    }

    public void setServerName(String serverName) {
        this.serverName = serverName;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Elasticsearch中,当一个节点被选作主节点时,它就负责管理集群状态,并协调节点之间的通信。当主节点不可用时,需要通过重新选举来选择新的主节点节点选举过程如下: 1.每个节点都有一个唯一的ID,称为节点ID。 2.每个节点都有一个优先级,称为节点优先级。节点优先级越高,就越有可能成为主节点。默认情况下,节点优先级为1。 3.当一个节点启动时,它将向其他节点发送一个加入请求,并等待其他节点的响应。 4.节点收到加入请求后,将检查请求中的节点ID和节点优先级,以决定是否接受该节点的加入请求。 5.如果节点被接受,则将其添加到集群中,并将其视为潜在的主节点。 6.如果当前主节点不可用,则其他节点将开始选举新的主节点。 7.选举过程分为两个阶段:预选和选举。 8.在预选阶段,每个节点将向其他节点发送一个预选请求,并等待其他节点的响应。如果一个节点收到了超过一半的响应,则它将进入下一阶段。 9.在选举阶段,每个节点将向其他节点发送一个选举请求,并等待其他节点的响应。如果一个节点收到了超过一半的响应,并且收到的响应中有一个节点的优先级比它自己高,则它将成为新的主节点。 10.如果没有节点成为新的主节点,则重新开始选举过程。 总之,Elasticsearch通过节点ID和节点优先级来确定主节点,并通过预选和选举过程来选举新的主节点。如果您需要进一步了解节点选举的细节,请参考Elasticsearch官方文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值