所有客户端都往一个节点注册master节点,只有注册成功的可以成为master。
package master_slave;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.exception.ZkNodeExistsException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class MasterSelector {
private ZkClient zkClient;
private final static String MASTER_PATH = "/master";
private IZkDataListener dataListener;//注册节点变化的信息
private UserCenter server;//其他节点
private UserCenter master;//master服务器
private static boolean isRunning = false;
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
public MasterSelector(UserCenter server,ZkClient zkClient) {
System.out.println(server.toString());
this.server = server;
this.zkClient = zkClient;
this.dataListener = new IZkDataListener() {
@Override
public void handleDataChange(String s, Object o) throws Exception {
}
@Override
public void handleDataDeleted(String s) throws Exception {
//节点如果被删除,触发选举操作
chooseMaster();
}
};
}
public void start(){
//开始选举
if(!isRunning){
isRunning=true;
zkClient.subscribeDataChanges(MASTER_PATH,dataListener);
chooseMaster();
}
}
public void stop(){
//停止选举
if(isRunning){
scheduledExecutorService.shutdown();
zkClient.unsubscribeDataChanges(MASTER_PATH,dataListener);
releaseMaster();
}
}
//具体选主节点实现
private void chooseMaster(){
if (!isRunning) {
System.out.println("当前服务没有启动。");
return;
}
try {
zkClient.createEphemeral(MASTER_PATH,server);
master = server;
System.out.println(master.getMc_name());
//模拟master出现故障
scheduledExecutorService.schedule(()->{
releaseMaster();
}, 5,TimeUnit.SECONDS);
}catch (ZkNodeExistsException e){
//表示master已经存在
UserCenter userCenter = zkClient.readData(MASTER_PATH);
if(userCenter==null) {
chooseMaster();//再次获取master
}else{
master=userCenter;
}
}
}
private void releaseMaster(){
//释放锁
//判断当前是否为master
if(checkIsMaster()){
zkClient.delete(MASTER_PATH);
}
}
private boolean checkIsMaster(){
//判断是不是master
UserCenter userCenter = zkClient.readData(MASTER_PATH);
if(userCenter.getMc_name().equals(server.getMc_name())){
master=server;
return true;
}
return false;
}
}