zookeeper分布式服务中选主的应用
通常zookeeper在分布式服务中作为注册中心,实际上它还可以办到很多事。比如分布式队列、分布式锁
由于公司服务中有很多定时任务,而这些定时任务由于一些历史原因暂时不能改造成框架调用
于是想到用zookeeper特性来实现
首先我们先了解下zk工作原理

结构图解释:左侧树状结构为zookeeper集群,右侧为程序服务器。所有的服务器在启动的时候,都会订阅zookeeper中master节点的删除事件,以便在主服务器挂掉的时候进行抢主操作;所有服务器同时会在servers节点下注册一个临时节点(保存自己的基本信息),以便于应用程序读取当前可用的服务器列表。
选主原理介绍:zookeeper的节点有两种类型,持久节点跟临时节点。临时节点有个特性,就是如果注册这个节点的机器失去连接(通常是宕机),那么这个节点会被zookeeper删除。选主过程就是利用这个特性,在服务器启动的时候,去zookeeper特定的一个目录下注册一个临时节点(这个节点作为master,谁注册了这个节点谁就是master),注册的时候,如果发现该节点已经存在,则说明已经有别的服务器注册了(也就是有别的服务器已经抢主成功),那么当前服务器只能放弃抢主,作为从机存在。同时,抢主失败的当前服务器需要订阅该临时节点的删除事件,以便该节点删除时(也就是注册该节点的服务器宕机了或者网络断了之类的)进行再次抢主操作。从机具体需要去哪里注册服务器列表的临时节点,节点保存什么信息,根据具体的业务不同自行约定。选主的过程,其实就是简单的争抢在zookeeper注册临时节点的操作,谁注册了约定的临时节点,谁就是master。
到此我们就可以着手实现了
public class ZkMasterChooseUtil {
public static final Map<String,ZkClient > map = new ConcurrentHashMap<>();
public static final Map<String,String > pathMap = new ConcurrentHashMap<>();
public static final Map<String,List<String>> childMap = new ConcurrentHashMap<>();
public static final String IP = getServerIp();
public static final boolean isMaster(String zkServer,String path){
try {
if (!map.containsKey(zkServer)){
reconnect(zkServer);
}
}catch (Exception e){
reconnect(zkServer);
}
String seq = null;
if (!pathMap.containsKey(path)){
if (!map.get(zkServer).exists(path)){
map.get(zkServer).createPersistent(path,true);
}
map.get(zkServer).subscribeChildChanges(path, (parentPath, currentChilds) -> {
childMap.put(parentPath,resetList(currentChilds != null? currentChilds : new ArrayList<>()));
});
pathMap.remove(path);
seq = map.get(zkServer).createEphemeralSequential(path+"/",IP);
pathMap.put(path,seq);
List<String> list = map.get(zkServer).getChildren(path);
childMap.put(path,resetList(list != null ? list : new ArrayList<>()));
}
seq = pathMap.get(path);
List<String> list = childMap.get(path);
if(list.size()>0){
if ((path+"/"+list.get(0)).equals(seq)){
return true;
}
System.out.println("path = "+(path+"/"+list.get(0)) +" seq = "+seq);
}
return false;
}
private static void reconnect(String zkServer){
ZkClient zkClient = new ZkClient(new ZkConnection(zkServer,10000),10000);
map.put(zkServer,zkClient);
}
private static String getServerIp() {
try {
InetAddress i = getLocalHostLANAddress();
return i != null ? i.getHostAddress() : null;
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public static InetAddress getLocalHostLANAddress() {
try {
InetAddress candidateAddress = null;
// 遍历所有的网络接口
for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements(); ) {
NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
// 在所有的接口下再遍历IP
for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements(); ) {
InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();
// 排除loopback类型地址
if (!inetAddr.isLoopbackAddress()) {
if (inetAddr.isSiteLocalAddress()) {
// 如果是site-local地址,就是它了
return inetAddr;
} else if (candidateAddress == null) {
// site-local类型的地址未被发现,先记录候选地址
candidateAddress = inetAddr;
}
}
}
}
if (candidateAddress != null) {
return candidateAddress;
}
// 如果没有发现 non-loopback地址.只能用最次选的方案
InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
return jdkSuppliedAddress;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static List<String> resetList(List<String> list){
if (list.size() == 0){
return list;
}
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
Long l1 = Long.valueOf(o1.substring(o1.lastIndexOf("/")+1));
Long l2 = Long.valueOf(o2.substring(o2.lastIndexOf("/")+1));
return l1.compareTo(l2);
}
});
return list;
}
}
注:传入path即为要抢注的节点
zookeeper分布式服务中选主的应用的更多相关文章
- Hadoop Zookeeper 分布式服务框架
what is Zookeeper? 1,开源的分布式的,为分布式应用提供协调服务的Apache项目2,提供一个简单原语集合,以便于分布式应用可以在它之上构建更高层次的同步服务3,设计非常易于编程,它 ...
- Zookeeper分布式服务协调组件
1.简介 Zookeeper是一个分布式服务协调组件,是Hadoop.Hbase.Kafka的重要组件,它是一个为分布式应用提供一致性服务的组件. Zookeeper的目标就是封装好复杂易出错的服 ...
- Java学习之Dubbo+ZooKeeper分布式服务Demo
背景:在之前的一个<Java学习之SpringBoot整合SSM Demo>分享中说到搭建ZooKeeper和Dubbo分布式框架中遇到了一些技术问题没能成功,只分享了其中的一个中间产物, ...
- 分布式服务框架Zookeeper
协议介绍 zookeeper协议分为两种模式 崩溃恢复模式和消息广播模式 崩溃恢复协议是在集群中所选举的leader 宕机或者关闭 等现象出现 follower重新进行选举出新的leader 同时集群 ...
- 分布式服务框架 Zookeeper -- 管理分布式环境中的数据
转自:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/index.html Zookeeper 分布式服务框架是 Apa ...
- 分布式服务框架 Zookeeper(转)
分布式服务框架 Zookeeper -- 管理分布式环境中的数据 Zookeeper 分布式服务框架是 Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题 ...
- 分布式服务框架 Zookeeper -- 管理分布式环境中的数据(转载)
本文转载自:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/ Zookeeper 分布式服务框架是 Apache Had ...
- 分布式服务框架 Zookeeper -- 管理分布式环境中的数据--转载
原文:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/ Zookeeper 分布式服务框架是 Apache Hadoop ...
- 分布式服务框架 Zookeeper — 管理分布式环境中的数据
本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它涉及到了paxos算法.Zab协议.通信协议等相关知识,理解起来比较抽象所以还需要借助一些应用场景,来帮我们理解. ...
随机推荐
- Python入门(二)列表、字典、字符串、元组、集合
列表list什么是列表:Python内置的一种数据类型是列表,list是一种有序的集合,可以随时添加和删除其中的元素 创建List列表的方法 L = ['杨俊辰',‘啦啦啦’,'Tom'] empty ...
- Vnpy官网汇总
Vnpy首页:http://www.vnpy.cn/ Vnpy社区:https://www.vnpy.com/ Vnpy论坛:http://www.vnpie.com/forum.php Github ...
- 亚马逊促销活动Promotion②:Money Off(满减折扣)的设置教程
满减.折扣是放之四海皆有效的促销手段,虽然亚马逊对卖家有诸多限制,但这个促销方式却是允许的,对亚马逊的卖家而言,这对提升商品销量.打造爆款都是极好的.今天小编来讲讲亚马逊的Money Off要怎么设置 ...
- python-获取URL中的json数据
数据源为某系统提供的URL,打开是json文件,python代码获取如下: URL替换成自己的即可. import urllib.request def get_record(url): resp = ...
- 『高性能模型』Roofline Model与深度学习模型的性能分析
转载自知乎:Roofline Model与深度学习模型的性能分析 在真实世界中,任何模型(例如 VGG / MobileNet 等)都必须依赖于具体的计算平台(例如CPU / GPU / ASIC 等 ...
- document.body.scrollTop和document.documentElement.scrollTop 以及值为0的问题
转自http://wo13145219.iteye.com/blog/2001598 一.先遇到document.body.scrollTop值为0的问题 做页面的时候可能会用到位置固定的层,读取do ...
- 爬坑!OpenCV打开双目摄像头
1.首先找到双目摄像头的VideoCapture的设备号,记住定义时要采用降序的方法定义:cv::VideoCapture Rcap(1); cv::VideoCapture Lcap(0); 2.分 ...
- oracle存储过程出现ORA-01403: 未找到数据 问题解决方法
这段时间在做一个业务,需要用到存储过程处理业务逻辑,但是出现一个ORA-01403: 未找到数据 问题, 那么这个应该如何解决这个问题 declare mixType integer; begin - ...
- .net项目dll内嵌加载
1.将dll文件作为嵌入资源添加到项目: 2.程序入口增加以下代码: public partial class App : Application { private void Application ...
- ES6的let
1.let声明的变量只在它所在的代码块有效. 例子: var a = [];for (var i = 0; i < 10; i++) {a[i] = function () {console.l ...