同步实现主节点选举
为了确保同一时间只有一个主节点进程处于活跃状态,我们使用ZooKeeper来实现简单的群首选举算法。这个算法中,所有的节点都尝试创建/master节点,但是只有一个成功,这个成功的进程成为主节点。接下来是代码实现
package com.my.service;
import java.io.IOException;
import java.util.Random;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.KeeperException.NoNodeException;
import org.apache.zookeeper.KeeperException.NodeExistsException;
import org.apache.zookeeper.data.Stat;
public class MyZookeeper {
private ZooKeeper zooKeeper;
private String hostPort;
private Random random = new Random(47);
private String serverId = Integer.toString(random.nextInt());
boolean isMaster = false;
public MyZookeeper(String hostPort) {
this.hostPort = hostPort;
}
// 创建一个zk连接监视点,打印断开连接日志信息
Watcher watcher = new Watcher() {
public void process(WatchedEvent event) {
// 如果监控到与服务端连接断开,打印日志
if (KeeperState.Disconnected.equals(event.getState())) {
System.out.println("Zookeeper Disconnected!客户端与ZooKeeper服务器连接断开!");
}
}
};
// 连接到zk服务端
public void startZk() throws IOException {
zooKeeper = new ZooKeeper(hostPort, 15000, watcher);
}
public void stopZk() throws InterruptedException {
zooKeeper.close();
}
public boolean checkMaster() {
while (true) {
try {
Stat stat = new Stat();
//通过获取/master节点的数据来检查活动主节点
byte data[] = zooKeeper.getData("/master", false, stat);
isMaster = new String(data).equals(serverId);
return true;
} catch (NoNodeException e) {
return false;
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void runForMaster() throws InterruptedException {
while (true) {
try {
//创建成功,将会成为主节点
zooKeeper.create("/master", serverId.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
isMaster = true;
break;
} catch (NodeExistsException e) {
isMaster = false;
} catch (KeeperException e) {
e.printStackTrace();
}
if (checkMaster()) {
break;
}
}
}
public static void main(String[] args) throws IOException, InterruptedException {
MyZookeeper myZookeeper = new MyZookeeper("127.0.0.1:2181");
myZookeeper.startZk();
myZookeeper.runForMaster();
if (myZookeeper.isMaster) {
System.out.println("我是主节点");
Thread.sleep(60000);
} else {
System.out.println("其他节点已经成为了主节点");
}
myZookeeper.stopZk();
}
}