java架构之路-(分布式zookeeper)zookeeper集群配置和选举机制详解
上次博客我们说了一下zookeeper的配置文件,以及命令的使用https://www.cnblogs.com/cxiaocai/p/11597465.html。我们这次来说一下我们的zookeeper的集群配置和java的API相关操作。
集群:
一般情况下我们用zookeeper来做任务调度中心的,所以一定要做到高可用的,单机的不可能做到永不宕机,我们也不会信任他单机的永不宕机,这时我们就需要做集群处理,来实现我们的高可用。
配置集群时,我们尽可能采用奇数的服务器来配置,什么意思呢?尽力采用3,5,7,9台服务器来配置,原因是zookeeper会默认识别半数以上服务器正常运行,才认为zookeeper是正常运行的,比如我们现在部署4台zookeeper服务器,这时其中两台宕机了,这时zookeeper会认为这个集群时不可用的,同理我们如果是5台服务器的情况,有两台宕机了,可以正常运行,三台宕机了,才被认为是不可用的,这个很重要,包括后面的选举机制也是这样的。资金有限啊,我先用3台服务器搭建一下zookeeper集群。
1.集群配置
下载解压什么的就不说了啊,上次都说过了,我们直接看下配置文件吧。和单机配置基本一致,我们看到dataDir=/tmp/zookeeper,也就是我们的数据存储路径,分别建立三个文件myid,内部输入1-255的数字
每台服务器别重复,切记一定建立在配置文件dataDir对应的目录下,不然启动会报找不到myid文件的错误,没有对应/tmp/zookeeper目录的,可以启动一下zookeeper再关闭就有文件夹了,或者自己手动创建也行。
再每一个配置文件内加入配置
server.1=172.16.140.106:2888:3888
server.2=172.16.140.105:2888:3888
server.3=172.16.214.74:2888:3888
server.myid(myid文件的数字)=ip(与myid相对应的IP):集群之间相互通讯的IP:选举时通讯的IP。三分配置文件都是一样的。
我们来分别启动一下。说到这里我们的集群配置也就成功了。
启动成功以后,我们分别输入./bin/zkServer.sh status 我们可以看到我们的服务器角色
2.角色:
leader 主节点,又名领导者。用于写入数据,通过选举产生,如果宕机将会选举新的主节点。
follower 子节点,又名追随者。用于实现数据的读取。同时他也是主节点的备选节点,并用拥有投票权。
observer 次级子节点,又名观察者。用于读取数据,与fllower区别在于没有投票权,不能选为主节点。并且在计算集群可用状态时不会将observer计算入内。也就是我们的半数原则计算。
observer配置:
只要在集群配置中加上observer后缀即可,示例如下:
server.3=127.0.0.1:2889:3889:observer
选举机制:
先说一个简单的,投票机制的。假设我们现在有1,2,3,4,5五个follower要进行选举。
简单流程就是这样的,第一轮都认为自己很可以,自己要当选leader,但是选举流程失败了,还得继续,接下来会把自己的票全盘拖出给自己临近的id,1就会给2一票,2现在有了两票了,发现还是不够半数啊,半数是2.5啊,算了还得继续,2又把自己的两票都给了3,3这时获得了3票了,大于半数了,当选leader。
每轮选举结束后都会统一来处理,如果一轮投票就发现server1的zxid较大,那么直接server1会当选leader。
优先检查ZXID。ZXID比较大的服务器优先作为Leader。
如果ZXID相同,那么就比较myid。myid较大的服务器作为Leader服务器。
留下一个思考题,5台服务器,如果启动可以指定 4号为leader服务 。
javaAPI相关操作
maven的pom文件内加入
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.5</version>
</dependency>
首先我们先初始化我们的Zookeeper的连接
connectString ->连接String连接串,包括ip+端口 ,集群模式下用逗号隔开192.168.0.149:2181,192.168.0.150:2181
sessionTimeout ->会话超时时间,类型int,该值不能超过服务端所设置的minSessionTimeout(默认2s)和maxSessionTimeout(默认60s),单位毫秒
watcher -> 会话监听器Watcher,服务端事件将会触该监听
sessionId -> 自定义会话ID long
sessionPasswd ->byte[] 会话密码
canBeReadOnly ->boolean该连接是否为只读的
hostProvider ->HostProvider 服务端地址提供者,指示客户端如何选择某个服务来调用,默认采用StaticHostProvider实现
@Before
public void init() throws IOException {
String conn = "47.111.109.3:2181"; // 连接字符串
int sessionTimeout = 4000; //连接超时时间
zooKeeper = new ZooKeeper(conn, sessionTimeout, new Watcher() {
public void process(WatchedEvent watchedEvent) { }
});
}
我们先来看看我们的新增节点,删除节点等操作吧。
查看节点:
我们使用getData方法,添加三个参数,分别是路径,是否监听,和返回值(状态stat)。
/**
* 获取数据
*
* @throws KeeperException
* @throws InterruptedException
*/
@Test
public void getData() throws KeeperException, InterruptedException {
byte[] data = zooKeeper.getData("/root", false, null);
System.out.println(new String(data));
}
添加监听:
/**
* 添加监听,结果在初始化里
*
* @throws KeeperException
* @throws InterruptedException
*/
@Test
public void getWatchData() throws KeeperException, InterruptedException {
byte[] data = zooKeeper.getData("/root", true, null);
System.out.println(new String(data));
Thread.sleep(Long.MAX_VALUE);
}
这个监听是一次性的,而且结果在我们的初始化的watch里,初始化方法改为
@Before
public void init() throws IOException {
String conn = "47.111.109.3:2181"; // 连接字符串
int sessionTimeout = 4000; //连接超时时间
zooKeeper = new ZooKeeper(conn, sessionTimeout, new Watcher() {
public void process(WatchedEvent watchedEvent) {
System.out.println(watchedEvent.getPath());
}
});
}
永久监听设置,我们只要将Watcher新建一下就可以了吗...我们来看一下实现
/**
* 永久监听
*
* @throws KeeperException
* @throws InterruptedException
*/
@Test
public void getWatchDataForever() throws KeeperException, InterruptedException {
byte[] data = zooKeeper.getData("/root", new Watcher() {
public void process(WatchedEvent watchedEvent) {
try {
zooKeeper.getData(watchedEvent.getPath(),this,null);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(watchedEvent.getPath());
}
}, null);
System.out.println(new String(data));
Thread.sleep(Long.MAX_VALUE);
}
stat:
/**
* Stat
*
* @throws KeeperException
* @throws InterruptedException
*/
@Test
public void getDataStat() throws InterruptedException, KeeperException {
Stat stat = new Stat();
zooKeeper.getData("/root",false, stat);
System.out.println(stat);
}
输出结果和我们命令stat的输入其实是完全一致的,只不过一个事16进制,一个事10进制的,可以自己对比一下。
获取子节点 :
/**
* 获取子节点
*
* @throws KeeperException
* @throws InterruptedException
*/
@Test
public void getWatchChildDataForever() throws KeeperException, InterruptedException {
List<String> children = zooKeeper.getChildren("/root", false);
for (int i = 0; i < children.size(); i++) {
System.out.println(children.get(i));
}
}
删除节点:
/**
* 删除节点
*
* @throws KeeperException
* @throws InterruptedException
*/
@Test
public void deletePath() throws KeeperException, InterruptedException {
zooKeeper.delete("/root/d2", 0);
}
创建节点:
/**
* 创建节点
*
* @throws KeeperException
* @throws InterruptedException
*/
@Test
public void createPath() throws KeeperException, InterruptedException {
List<ACL> acl = new ArrayList<ACL>();
int perm = ZooDefs.Perms.ADMIN | ZooDefs.Perms.CREATE | ZooDefs.Perms.READ;
ACL aclObj = new ACL(perm, new Id("world", "anyone"));
acl.add(aclObj);
zooKeeper.create("/root/d4", "hello".getBytes(), acl, CreateMode.CONTAINER);
}
说到这我们的API和集群操作就差不多说完了。
这次代码不多,就先不上传了,写完下次博客再一起上传。
最进弄了一个公众号,小菜技术,欢迎大家的加入
java架构之路-(分布式zookeeper)zookeeper集群配置和选举机制详解的更多相关文章
- java架构之路(mysql底层原理)Mysql之Explain使用详解
上篇博客,我们详细的说明了mysql的索引存储结构,也就是我们的B+tree的变种,是一个带有双向链表的B+tree.那么我今天来详细研究一下,怎么使用索引和怎么查看索引的使用情况. 我们先来简单的建 ...
- 使用 ZooKeeper 同步集群配置
用 ZooKeeper 同步集群配置,当需要修改所有节点配置时,将配置更新到 ZooKeeper 的一个节点,引起这个节点数据发生变化, 其他所有需要同步配置的节点上的本地 Watcher 会立即发现 ...
- Zookeeper的集群配置和Java测试程序
Zookeeper是Apache下的项目之一,倾向于对大型应用的协同维护管理工作.IBM则给出了IBM对ZooKeeper的认知: Zookeeper 分布式服务框架是 Apache Hadoop 的 ...
- Zookeeper的集群配置和Java测试程序 (一)
概述 Zookeeper是Apache下的项目之一,倾向于对大型应用的协同维护管理工作.IBM则给出了IBM对ZooKeeper的认知: Zookeeper 分布式服务框架是 Apache Hadoo ...
- Hadoop入门 完全分布式运行模式-集群配置
目录 集群配置 集群部署规划 配置文件说明 配置集群 群起集群 1 配置workers 2 启动集群 总结 3 集群基本测试 上传文件到集群 查看数据真实存储路径 下载 执行wordcount程序 配 ...
- Linux 下Redis集群安装部署及使用详解(在线和离线两种安装+相关错误解决方案)
一.应用场景介绍 本文主要是介绍Redis集群在Linux环境下的安装讲解,其中主要包括在联网的Linux环境和脱机的Linux环境下是如何安装的.因为大多数时候,公司的生产环境是在内网环境下,无外网 ...
- dubbo+zookeeper伪集群配置
zookeeper作为注册中心,服务器和客户端都要访问,如果有大量的并发,肯定会有等待.所以可以通过zookeeper集群解决. 一.为什么需要zookeeper呢? 大部分分布式应用需要一个主控.协 ...
- 分布式缓存Redis集群配置使用
Redis 简介 redis是一种开源的.基于内存的.可持久化的.高性能的Key-Value数据存储系统. redis能做什么? 持久化存储 高速缓存 消息中间件 ...
- hadoop分布式安装及其集群配置笔记
各机器及角色信息: 共10台机器,hostname与ip地址映射在此不做赘述.此为模拟开发环境安装,所以不考虑将NameNode和SecondaryNameNode安装在同一台机器. 节点 角色 na ...
随机推荐
- python 12 生成器
目录 1. 生成器 yeild 2. 推导式 2.1 列表推导式: 2.2 生成器推导式: 2.3 字典推导式: 2.4 集合推导式: 3. 内置函数(一) 1. 生成器 yeild 生成器的本质就是 ...
- Leetcode之深度优先搜索(DFS)专题-199. 二叉树的右视图(Binary Tree Right Side View)
Leetcode之深度优先搜索(DFS)专题-199. 二叉树的右视图(Binary Tree Right Side View) 深度优先搜索的解题详细介绍,点击 给定一棵二叉树,想象自己站在它的右侧 ...
- [Python] Django框架入门4——深入模板
说明: 本文主要深入了解模板(templates),主要涉及模板编写步骤.定义模板.模板继承.HTML转义.CSRF等. 一.模板 动态生成HTML.表达外观.实现业务逻辑(view)与显示内容(te ...
- Windows GIT SSH 免密教程
Windows GIT SSH 免密教程 安装git客户端,最新下载地址如下 https://github.com/git-for-windows/git/releases/download/v2.2 ...
- 多线程编程学习六(Java 中的阻塞队列).
介绍 阻塞队列(BlockingQueue)是指当队列满时,队列会阻塞插入元素的线程,直到队列不满:当队列空时,队列会阻塞获得元素的线程,直到队列变非空.阻塞队列就是生产者用来存放元素.消费者用来获取 ...
- Java集合:LinkedList (JDK1.8 源码解读)
LinkedList介绍 还是和ArrayList同样的套路,顾名思义,linked,那必然是基于链表实现的,链表是一种线性的储存结构,将储存的数据存放在一个存储单元里面,并且这个存储单元里面还维护了 ...
- XML的相关基础知识分享
XML和Json是两种最常用的在网络中数据传输的数据序列化格式,随着时代的变迁,XML序列化用于网络传输也逐渐被Json取代,前几天,单位系统集成开发对接接口时,发现大部分都用的WebService技 ...
- RHEL7破解密码操作步骤
首先查看系统是什么版本 cat /etc/redhat-release 第1步:然后重启Linux系统并出现引导界面时,按下键盘上的e键进入内核编辑界面. 第2步:在Linux16 参数这行的最后面追 ...
- 【LeetCode】105#从前序与中序遍历序列构造二叉树
题目描述 根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 例如,给出 前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9 ...
- ubuntu命令行配置静态IP
(1)首先我们使用ifconfig命令查询一下网卡名称 提示:如果提示没有ifconfig命令,首先应该下载一个net-tools 仅需执行命令:apt install net-tools (2)编辑 ...