zookeeper【4】master选举
考虑7*24小时向外提供服务的系统,不能有单点故障,于是我们使用集群,采用的是Master+Slave。集群中有一台主机和多台备机,由主机向外提 供服务,备机监听主机状态,一旦主机宕机,备机必需迅速接管主机继续向外提供服务。在这个过程中,从备机选出一台机作为主机的过程,就是Master选 举。
架构图:

左边是ZooKeeper集群,右边是3台工作服务器。工作服务器启动时,会去ZooKeeper的Servers节点下创建临时节点,并把基本信息写入 临时节点。这个过程叫服务注册,系统中的其他服务可以通过获取Servers节点的子节点列表,来了解当前系统哪些服务器可用,这该过程叫做服务发现。接 着这些服务器会尝试创建Master临时节点,谁创建成功谁就是Master,其他的两台就作为Slave。所有的Work Server必需关注Master节点的删除事件。通过监听Master节点的删除事件,来了解Master服务器是否宕机(创建临时节点的服务器一旦宕 机,它所创建的临时节点即会自动删除)。一旦Master服务器宕机,必需开始新一轮的Master选举。
实现代码:
/**
* 调度器
*/
public class LeaderSelectorZkClient { //启动的服务个数
private static final int CLIENT_QTY = 10;
//zookeeper服务器的地址
private static final String ZOOKEEPER_SERVER = "192.168.1.105:2181"; public static void main(String[] args) throws Exception {
//保存所有zkClient的列表
List<ZkClient> clients = new ArrayList<ZkClient>();
//保存所有服务的列表
List<WorkServer> workServers = new ArrayList<WorkServer>(); try {
for ( int i = 0; i < CLIENT_QTY; ++i ) { // 模拟创建10个服务器并启动
//创建zkClient
ZkClient client = new ZkClient(ZOOKEEPER_SERVER, 5000, 5000, new SerializableSerializer());
clients.add(client);
//创建serverData
RunningData runningData = new RunningData();
runningData.setCid(Long.valueOf(i));
runningData.setName("Client #" + i);
//创建服务
WorkServer workServer = new WorkServer(runningData);
workServer.setZkClient(client); workServers.add(workServer);
workServer.start();
} System.out.println("敲回车键退出!\n");
new BufferedReader(new InputStreamReader(System.in)).readLine(); } finally { System.out.println("Shutting down..."); for ( WorkServer workServer : workServers ) {
try {
workServer.stop();
} catch (Exception e) {
e.printStackTrace();
}
} for ( ZkClient client : clients ) {
try {
client.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
import java.io.Serializable; /**
* 工作服务器信息
*/
public class RunningData implements Serializable { private static final long serialVersionUID = 4260577459043203630L; private Long cid;
private String name;
public Long getCid() {
return cid;
}
public void setCid(Long cid) {
this.cid = cid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} }
/**
* 工作服务器
*/
public class WorkServer { // 记录服务器状态
private volatile boolean running = false; private ZkClient zkClient;
// Master节点对应zookeeper中的节点路径
private static final String MASTER_PATH = "/master";
// 监听Master节点删除事件
private IZkDataListener dataListener;
// 记录当前节点的基本信息
private RunningData serverData;
// 记录集群中Master节点的基本信息
private RunningData masterData; private ScheduledExecutorService delayExector = Executors.newScheduledThreadPool(1);
private int delayTime = 5; public WorkServer(RunningData rd) {
this.serverData = rd; // 记录服务器基本信息
this.dataListener = new IZkDataListener() { public void handleDataDeleted(String dataPath) throws Exception { //takeMaster(); if (masterData != null && masterData.getName().equals(serverData.getName())){
// 自己就是上一轮的Master服务器,则直接抢
takeMaster();
} else {
// 否则,延迟5秒后再抢。主要是应对网络抖动,给上一轮的Master服务器优先抢占master的权利,避免不必要的数据迁移开销
delayExector.schedule(new Runnable(){
public void run(){
takeMaster();
}
}, delayTime, TimeUnit.SECONDS);
} } public void handleDataChange(String dataPath, Object data)
throws Exception { }
};
} public ZkClient getZkClient() {
return zkClient;
} public void setZkClient(ZkClient zkClient) {
this.zkClient = zkClient;
} // 启动服务器
public void start() throws Exception {
if (running) {
throw new Exception("server has startup...");
}
running = true;
// 订阅Master节点删除事件
zkClient.subscribeDataChanges(MASTER_PATH, dataListener);
// 争抢Master权利
takeMaster(); } // 停止服务器
public void stop() throws Exception {
if (!running) {
throw new Exception("server has stoped");
}
running = false; delayExector.shutdown();
// 取消Master节点事件订阅
zkClient.unsubscribeDataChanges(MASTER_PATH, dataListener);
// 释放Master权利
releaseMaster(); } // 争抢Master
private void takeMaster() {
if (!running)
return; try {
// 尝试创建Master临时节点
zkClient.create(MASTER_PATH, serverData, CreateMode.EPHEMERAL);
masterData = serverData;
System.out.println(serverData.getName()+" is master"); // 作为演示,我们让服务器每隔5秒释放一次Master权利
delayExector.schedule(new Runnable() {
public void run() {
// TODO Auto-generated method stub
if (checkMaster()){
releaseMaster();
}
}
}, 5, TimeUnit.SECONDS); } catch (ZkNodeExistsException e) { // 已被其他服务器创建了
// 读取Master节点信息
RunningData runningData = zkClient.readData(MASTER_PATH, true);
if (runningData == null) {
takeMaster(); // 没读到,读取瞬间Master节点宕机了,有机会再次争抢
} else {
masterData = runningData;
}
} catch (Exception e) {
// ignore;
} } // 释放Master权利
private void releaseMaster() {
if (checkMaster()) {
zkClient.delete(MASTER_PATH);
}
} // 检测自己是否为Master
private boolean checkMaster() {
try {
RunningData eventData = zkClient.readData(MASTER_PATH);
masterData = eventData;
if (masterData.getName().equals(serverData.getName())) {
return true;
}
return false;
} catch (ZkNoNodeException e) {
return false; // 节点不存在,自己肯定不是Master了
} catch (ZkInterruptedException e) {
return checkMaster();
} catch (ZkException e) {
return false;
}
} }
zookeeper【4】master选举的更多相关文章
- 模拟使用zookeeper实现master选举
1.模拟选举机器类 package com.karat.cn.zookeeperAchieveLock.zkclient; import java.io.Serializable; /** * 选举的 ...
- Zookeeper实现master选举
使用场景 有一个向外提供的服务,服务必须7*24小时提供服务,不能有单点故障.所以采用集群的方式,采用master.slave的结构.一台主机多台备机.主机向外提供服务,备机负责监听主 ...
- Zookeeper实现Master选举(哨兵机制)
master选举使用场景及结构 现在很多时候我们的服务需要7*24小时工作,假如一台机器挂了,我们希望能有其它机器顶替它继续工作.此类问题现在多采用master-salve模式,也就是常说的主从模式, ...
- (原)3.1 Zookeeper应用 - Master选举
本文为原创文章,转载请注明出处,谢谢 Master 选举 1.原理 服务器争抢创建标志为Master的临时节点 服务器监听标志为Master的临时节点,当监测到节点删除事件后展开新的一轮争抢 某个服务 ...
- zookeeper典型应用场景之一:master选举
对于zookeeper这种东西,仅仅知道怎么安装是远远不够的,至少要对其几个典型的应用场景进行了解,才能比较全面的知道zk究竟能干啥,怎么玩儿,以后的日子里才能知道这货如何能为我所用.于是,有了如下的 ...
- 使用zookeeper实现分布式master选举(c 接口版本)
zookeeper,已经被很多人所熟知,主要应用场景有(数据订阅/发布 ,负载均衡, 命名服务, 分布式协调/通知,集群管理,Master选举,分布式锁,分布式队列). C接口的描述 主要参考 Ha ...
- ZooKeeper场景实践:(6)集群监控和Master选举
1. 集群机器监控 这通经常使用于那种对集群中机器状态,机器在线率有较高要求的场景,可以高速对集群中机器变化作出响应.这种场景中,往往有一个监控系统,实时检測集群机器是否存活. 利用ZooKeeper ...
- Zookeeper系列五:Master选举、ZK高级特性:基本模型
一.Master选举 1. master选举原理: 有多个master,每次只能有一个master负责主要的工作,其他的master作为备份,同时对负责工作的master进行监听,一旦负责工作的mas ...
- ZooKeeper 典型应用场景-Master选举
master选举 1.使用场景及结构 现在很多时候我们的服务需要7*24小时工作,假如一台机器挂了,我们希望能有其它机器顶替它继续工作.此类问题现在多采用master-salve模式,也就是常说的主从 ...
随机推荐
- OCP 052题库全变,最新052考试题及答案整理-第11题
11.Which three are true about UNDO data? A) It is used to roll back failed transactions. B) It is us ...
- P5030 长脖子鹿放置 最小割
$ \color{#0066ff}{ 题目描述 }$ 如图所示,西洋棋的"长脖子鹿",类似于中国象棋的马,但按照"目"字攻击,且没有中国象棋"别马腿& ...
- Alluxio学习
介绍 Alluxio(之前名为Tachyon)是世界上第一个以内存为中心的虚拟的分布式存储系统.它统一了数据访问的方式,为上层计算框架和底层存储系统构建了桥梁.应用只需要连接Alluxio即可访问存储 ...
- javascript canvas画订单
前段时间看了某个平台的后台,发现订单显示使用的canvas进行绘画(插件echarts),直观,明了的表达出了订单的走势如下 所以自己心痒痒的,就自己模仿了一个-->贴上代码 <style ...
- 北京DNS
202.106.0.20 202.106.196.115 202.106.46.151
- Java操作系统剪贴板(Clipboard)复制粘贴
Java操作系统剪贴板(Clipboard)复制粘贴
- myEclipse修改字体大小
- 《大数据日知录》读书笔记-ch2数据复制与一致性
CAP理论:Consistency,Availability,Partition tolerance 对于一个分布式数据系统,CAP三要素不可兼得,至多实现其二.要么AP,要么CP,不存在CAP.分布 ...
- 关于halo博客系统的使用踩坑——忘记登录密码
踩坑: halo系统可以直接通过运行jar -jar halo-0.0.3.jar跑起来,也可以通过导入IDE然后运行Application的main方法跑起系统. h2数据库访问路径:http:// ...
- Web性能优化之雅虎军规
相信互联网已经越来越成为人们生活中不可或缺的一部分.Ajax,flex等等富客户端的应用使得人们越加“幸福”地体验着许多原先只能在C/S实 现的功能. 比如Google机会已经把最基本的office应 ...