2019独角兽企业重金招聘Python工程师标准>>>

master选举

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

架构图

左边是ZooKeeper集群,右边是3台工作服务器。工作服务器启动时,会去ZooKeeper的Servers节点下创建临时节点,并把基本信息写入临时节点。这个过程叫服务注册,系统中的其他服务可以通过获取Servers节点的子节点列表,来了解当前系统哪些服务器可用,这该过程叫做服务发现。接着这些服务器会尝试创建Master临时节点,谁创建成功谁就是Master,其他的两台就作为Slave。所有的Work Server必需关注Master节点的删除事件。通过监听Master节点的删除事件,来了解Master服务器是否宕机(创建临时节点的服务器一旦宕机,它所创建的临时节点即会自动删除)。一旦Master服务器宕机,必需开始新一轮的Master选举。

流程图

核心类图

WorkServer对应架构图的WorkServer,是主工作类;
RunningData用来描述WorkServer的基本信息;
LeaderSelectorZkClient作为调度器来启动和停止WorkServer;

代码实现

/*** 工作服务器信息*/
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();}// 争抢Masterprivate 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 stubif (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);}}// 检测自己是否为Masterprivate 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;}}}
/*** 调度器*/
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个服务器并启动//创建zkClientZkClient client = new ZkClient(ZOOKEEPER_SERVER, 5000, 5000, new SerializableSerializer());clients.add(client);//创建serverDataRunningData 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();}               }}        }
}
/*** 工作服务器信息*/
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();}// 争抢Masterprivate 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 stubif (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);}}// 检测自己是否为Masterprivate 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;}}}
/*** 调度器*/
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个服务器并启动//创建zkClientZkClient client = new ZkClient(ZOOKEEPER_SERVER, 5000, 5000, new SerializableSerializer());clients.add(client);//创建serverDataRunningData 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();}               }}        }
}

zookeeper系列(一)zookeeper必知
zookeeper系列(二)实战master选举
zookeeper系列(三)实战数据发布订阅
zookeeper系列(四)实战负载均衡
zookeeper系列(五)实战分布式锁
zookeeper系列(六)实战分布式队列
zookeeper系列(七)实战分布式命名服务
zookeeper系列(八)zookeeper运维

master选举

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

架构图

左边是ZooKeeper集群,右边是3台工作服务器。工作服务器启动时,会去ZooKeeper的Servers节点下创建临时节点,并把基本信息写入临时节点。这个过程叫服务注册,系统中的其他服务可以通过获取Servers节点的子节点列表,来了解当前系统哪些服务器可用,这该过程叫做服务发现。接着这些服务器会尝试创建Master临时节点,谁创建成功谁就是Master,其他的两台就作为Slave。所有的Work Server必需关注Master节点的删除事件。通过监听Master节点的删除事件,来了解Master服务器是否宕机(创建临时节点的服务器一旦宕机,它所创建的临时节点即会自动删除)。一旦Master服务器宕机,必需开始新一轮的Master选举。

流程图

核心类图

WorkServer对应架构图的WorkServer,是主工作类;
RunningData用来描述WorkServer的基本信息;
LeaderSelectorZkClient作为调度器来启动和停止WorkServer;

代码实现

/*** 工作服务器信息*/
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();}// 争抢Masterprivate 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 stubif (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);}}// 检测自己是否为Masterprivate 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;}}}
/*** 调度器*/
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个服务器并启动//创建zkClientZkClient client = new ZkClient(ZOOKEEPER_SERVER, 5000, 5000, new SerializableSerializer());clients.add(client);//创建serverDataRunningData 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();}               }}        }
}

转载于:https://my.oschina.net/u/164027/blog/1923921

zookeeper系列(二)实战master选举相关推荐

  1. Zookeeper系列五:Master选举、ZK高级特性:基本模型

    一.Master选举 1. master选举原理: 有多个master,每次只能有一个master负责主要的工作,其他的master作为备份,同时对负责工作的master进行监听,一旦负责工作的mas ...

  2. zookeeper系列(二)实战master选举 1

    zookeeper系列(一)zookeeper必知 zookeeper系列(二)实战master选举 zookeeper系列(三)实战数据发布订阅 zookeeper系列(四)实战负载均衡 zooke ...

  3. [Perl系列二-实战] 1. Perl 读取代码的行数

    前言 有的时候有这些需求: 1. 统计一个文件的行数 2. 统计一个源代码的有效行数.排除空行和注释行 3. 统一一个目录下各种文件的数量和行数 要达成这些需求,很多语言多可以做到, 但是使用Perl ...

  4. Master选举原理

    为什么需要Zookeeper? 为了防止集群的主NameNode挂掉,再另创建一个辅NameNode,两个保持数据同步,一旦主NameNode挂掉,集群就会把辅NameNode节点作为整个集群的主Na ...

  5. ZooKeeper场景实践:(6)集群监控和Master选举

    1. 集群机器监控 这通经常使用于那种对集群中机器状态,机器在线率有较高要求的场景,可以高速对集群中机器变化作出响应.这种场景中,往往有一个监控系统,实时检測集群机器是否存活. 利用ZooKeeper ...

  6. Zookeeper实现Master选举(哨兵机制)

    master选举使用场景及结构 现在很多时候我们的服务需要7*24小时工作,假如一台机器挂了,我们希望能有其它机器顶替它继续工作.此类问题现在多采用master-salve模式,也就是常说的主从模式, ...

  7. xen虚拟化实战系列(二)之xen虚拟机安装

    xen虚拟化实战系列文章列表 xen虚拟化实战系列(一)之xen虚拟化环境安装 xen虚拟化实战系列(二)之xen虚拟机安装 xen虚拟化实战系列(三)之xen虚拟机复制 xen虚拟化实战系列(四)之 ...

  8. 利用Zookeeper实现 - Master选举

    原文始发于:利用Zookeeper实现 - Master选举 Zookeeper 是一个高可用的分布式数据管理与协调框架,基于ZAB协议算法的实现,该框架能够很好的保证分布式环境中数据的一致性.Zoo ...

  9. Zookeeper系列(二)、核心原理

    上一篇我们介绍了Zookeeper的一些基础知识,本篇来讲解zk内部的一些核心原理,帮助我们更好的理解zk的工作机制. 目录 选举机制 Leader选举流程 Leader选举原理 Watch机制 会话 ...

最新文章

  1. AndroidStudio 新建不同的Drawable文件夹
  2. 致命错误: zlib.h:没有那个文件或目录
  3. 突破:量子计算机首次实现简化逻辑门
  4. JavaWeb学习之路——SSM框架之Mybatis(二)
  5. python 计算累计人数_免费Python入门课程,看到就是赚到~
  6. 并发服务器设计思路,参考apache学习UDP和QoS,研究成果
  7. 网络流(最大流):CodeForces 499E Array and Operations
  8. OpenCV:读取与写入图片
  9. 图片轮播的JS写法,通用涉及多个轮播
  10. getParameter和getAttribute区别(超详细分析)
  11. 用Java写一个浪费cpu的程序_Java程序是如何浪费内存的
  12. 【C语言】猜拳小游戏代码实现
  13. 通俗易懂讲解javaSocket编程
  14. 算法竞赛---day2(等差素数列)
  15. 数据科学库(六)pandas中的时间序列
  16. 墨尔本大学 SWEN20003 Project2 课业解析
  17. 【JZOJ】3424. 粉刷匠
  18. ionic2开发环境 linux,安装ionic开发环境
  19. 西电计算机学院崔江涛,“师德标兵”崔江涛:人才培养的研究者与实践者
  20. 【BIOS】主板BIOS的两种启动模式,传统模式(Legacy)和UEFI模式

热门文章

  1. DIV布局之position详解
  2. 面向对象之__isset__unset
  3. 怎样把 Boot Camp 里 Windows 的色温调节得和 Mac OS X 一致
  4. mysql服务怎么改名字_MySQL数据库改名字
  5. ultraedit中文粘贴出去乱码_Windows系统-怎么搞定乱码
  6. MAC修改python和pip版本
  7. ICPC2008哈尔滨-A-Array Without Local Maximums
  8. 自定义博客园地址栏ico图标 标签logo
  9. Windows任务计划创建计划,定时执行PowerShell命令
  10. Burt’s Bees 小蜜蜂纯天然杏仁牛奶蜂蜡护手霜,56g*2罐,$13.92