zookeeper

zookeeper是什么

Apache ZooKeeper是Apache软件基金会的一个软件项目,他为大型分布式计算提供开源的分布式配置服务、同步服务和命名注册。ZooKeeper曾经是Hadoop的一个子项目,但现在是一个独立的顶级项目。

ZooKeeper的架构通过冗余服务实现高可用性。因此,如果第一次无应答,客户端就可以询问另一台ZooKeeper主机。ZooKeeper节点将它们的数据存储于一个分层的命名空间,非常类似于一个文件系统或一个前缀树结构。客户端可以在节点读写,从而以这种方式拥有一个共享的配置服务。

使用ZooKeeper的公司包括Rackspace、雅虎和eBay,以及类似于像Solr这样的开源企业级搜索系统。

zookeeper提供了什么

  • 文件系统:zookeeper维护一个类似文件系统的数据结构,每个子目录项如 NameService 都被称作为 znode,和文件系统一样,自由增加及删除,唯一不同其可存储数据。Znode分为四种类型

    • PERSISTENT-持久化目录节点。(客户端与zookeeper断开连接后,该节点依旧存在)。

    • PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点。(客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号)

    • EPHEMERAL-临时目录节点(客户端与zookeeper断开连接后,该节点被删除)

    • EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点。(客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号)

  • 通知机制:客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。

zookeeper能为我们做什么?

  • 命名服务:在zookeeper的文件系统里创建一个目录,即有唯一的path。在我们使用tborg无法确定上游程序的部署机器时即可与下游程序约定好path,通过path即能互相探索发现。

  • 配置管理:把应用配置放置zookeeper上去,保存在 Zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中就好。

  • 集群管理:节点(机器)增删及Master选取。节点增删:所有机器约定在父目录GroupMembers下创建临时目录节点,然后监听父目录节点的子节点变化消息。一旦有机器挂掉,该机器与 zookeeper的连接断开,其所创建的临时目录节点被删除,所有其他机器都收到通知:某个兄弟目录被删除,于是,所有人都知道:它上船了。新机器加入 也是类似,所有机器收到通知:新兄弟目录加入,highcount又有了。Master选取:所有机器创建临时顺序编号目录节点,每次选取编号最小的机器作为master就好。

  • 分布式锁:基于zookeeper一致性文件系统,实现锁服务。锁服务分为保存独占及时序控制两类。保存独占:将zookeeper上的一个znode看作是一把锁,通过createznode的方式来实现。所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁。用完删除自己创建的distribute_lock 节点就释放锁。时序控制:基于/distribute_lock锁,所有客户端在它下面创建临时顺序编号目录节点,和选master一样,编号最小的获得锁,用完删除,依次方便。

  • 队列管理:分同步队列,FIFO队列(入队与出队),同步队列:当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达。在约定目录下创建临时目录节点,监听节点数目是否是我们要求的数目。FIFO队列:和分布式锁服务中的控制时序场景基本原理一致,入列有编号,出列按编号。

  • 分布式与数据复制:Zookeeper作为一个集群提供一致的数据服务,必然在所有机器间做数据复制。数据复制好处:(1)容错:一个节点出错,不致于让整个系统停止工作,别的节点可以接管它的工作。(2)提高系统的扩展能力:把负载分布到多个节点上,或者增加节点来提高系统的负载能力;(3)性能提升:让客户端本地访问就近节点,提高用户访问速度。

zookeeper基本概念

角色简介

Zookeeper角色分为三类,领导者:负责进行投票的发起和决议,更新系统状态。跟随者:Follower用于接收客户请求并向客户端返回结果,在选中过程中参与投票。观察者:Observer可以接收客户端连接,将写请求转发给leader节点。但不参加投票过程,只同步leader状态。Observer目的在于扩展系统,提高读取速度。

设计目的

  • 一致性:client不论连接到哪个Server,展示给它都是同一个视图,这是zookeeper最重要的性能。

  • 可靠性:具有简单、健壮、良好的性能,如果消息m被到一台服务器接受,那么它将被所有的服务器接受。

  • 实时性:Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网络延时等原因,Zookeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。

  • 等待无关(wait-free):慢的或者失效的client不得干预快速的client的请求,使得每个client都能有效的等待。

  • 原子性:更新只能成功或者失败,没有中间状态。

  • 顺序性:包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息a在消息b前发布,则在所有Server上消息a都将在消息b前被发布;偏序是指如果一个消息b在消息a后被同一个发送者发布,a必将排在b前面。

选主流程

当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的Server都恢复到一个正确的状态。Zk的选举算法有两种:一种是基于basic paxos实现的,另外一种是基于fast paxos算法实现的。系统默认的选举算法为fast paxos。先介绍basic paxos流程:

选举线程由当前Server发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的Server;

选举线程首先向所有Server发起一次询问(包括自己);

选举线程收到回复后,验证是否是自己发起的询问(验证zxid是否一致),然后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(id,zxid),并将这些信息存储到当次选举的投票记录表中;

收到所有Server回复以后,就计算出zxid最大的那个Server,并将这个Server相关信息设置成下一次要投票的Server;

线程将当前zxid最大的Server设置为当前Server要推荐的Leader,如果此时获胜的Server获得n/2 + 1的Server票数, 设置当前推荐的leader为获胜的Server,将根据获胜的Server相关信息设置自己的状态,否则,继续这个过程,直到leader被选举出来。

通过流程分析我们可以得出:要使Leader获得多数Server的支持,则Server总数必须是奇数2n+1,且存活的Server的数目不得少于n+1.

每个Server启动后都会重复以上流程。在恢复模式下,如果是刚从崩溃状态恢复的或者刚启动的server还会从磁盘快照中恢复数据和会话信息,zk会记录事务日志并定期进行快照,方便在恢复时进行状态恢复。

fast paxos流程是在选举过程中,某Server首先向所有Server提议自己要成为leader,当其它Server收到提议以后,解决epoch和zxid的冲突,并接受对方的提议,然后向对方发送接受提议完成的消息,重复这个流程,最后一定能选举出Leader。

zookeeper的安装使用

wget http://mirrors.cnnic.cn/apache/zookeeper/zookeeper-3.4.8/zookeeper-3.4.8.tar.gz

tar zxvf zookeeper-3.4.8.tar.gz -C /usr/local/

cd $ZOOKEEPER_HOME

cp conf/zoo_sample.cfg conf/zoo.cfg

# 集群需要在zoo.cfg配置

server.1=192.168.1.148:2888:3888
server.2=192.168.1.149:2888:3888
server.3=192.168.1.150:2888:3888 # 在zookeeper的临时目录创建myid
mkdir -p /tmp/zookeeper # 分别在不同节点创建myid文件里面的数字对应节点的编号比如server.1就对应1,server.2就对应2
echo 1 > /tmp/zookeeper/myid # 最后分别启动集群上的节点
$ZOOKEEPER_HOME/bin/zkServer.sh start # 查看zookeeper的状态
$ZOOKEEPER_HOME/bin/zkServer.sh status # 停止zookeeper服务
$ZOOKEEPER_HOME/bin/zkServer.sh stop

zookeeper命令行操作

启动zookeeper服务后到bin目录启动zookeeper的客户端$ZOOKEEPER_HOME/bin/zkCli.sh

# 输入help

[zk: localhost:2181(CONNECTED) 0] help
ZooKeeper -server host:port cmd args
stat path [watch]
set path data [version]
ls path [watch]
delquota [-n|-b] path
ls2 path [watch]
setAcl path acl
setquota -n|-b val path
history
redo cmdno
printwatches on|off
delete path [version]
sync path
listquota path
rmr path
get path [watch]
create [-s] [-e] path data acl
addauth scheme auth
quit
getAcl path
close
connect host:port

创建节点

[zk: localhost:2181(CONNECTED) 14] create /test test-data
Created /test

查看节点

[zk: localhost:2181(CONNECTED) 1] ls /
[abc, zookeeper, eclipse]

获取节点

[zk: localhost:2181(CONNECTED) 10] get /test
test-update
cZxid = 0x38
ctime = Sat Dec 22 10:11:46 CST 2018
mZxid = 0x39
mtime = Sat Dec 22 10:12:05 CST 2018
pZxid = 0x38
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 11
numChildren = 0

修改节点

[zk: localhost:2181(CONNECTED) 11] set /test test-update
cZxid = 0x38
ctime = Sat Dec 22 10:11:46 CST 2018
mZxid = 0x3a
mtime = Sat Dec 22 10:15:04 CST 2018
pZxid = 0x38
cversion = 0
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 11
numChildren = 0

删除节点

[zk: localhost:2181(CONNECTED) 13] delete /test

zookeeper java 客户端操作

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.util.List; /**
* @author leone
* @since 2018-06-16
**/
public class ZkClient { private final static Logger logger = LoggerFactory.getLogger(ZkClient.class); private final static String ZK_URL = "xxx.xxx.xxx.xxx:2181"; private final static int TIME_OUT = 5000; private static ZooKeeper zkClient = null; @Before
public void init() throws Exception {
zkClient = new ZooKeeper(ZK_URL, TIME_OUT, (WatchedEvent event) -> {
// 收到事件通知后的回调函数(应该是我们自己的事件处理逻辑)
logger.info(event.getType() + "---" + event.getPath());
try {
zkClient.getChildren("/", true);
} catch (Exception e) {
e.printStackTrace();
}
});
} /**
* 设置值
*
* @throws Exception
*/
@Test
public void testSetData() throws Exception {
zkClient.setData("/eclipse", "world".getBytes(), -1);
byte[] data = zkClient.getData("/eclipse", false, null);
System.out.println(new String(data));
} /**
* 创建节点
*
* @throws Exception
*/
@Test
public void testCreate() throws Exception {
// 参数1:要创建的节点的路径 参数2:节点数据 参数3:节点的权限 参数4:节点的类型
zkClient.create("/eclipse/aaa", "aaaData".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
} /**
* 测试某节点是否存在
*
* @throws Exception
*/
@Test
public void testExists() throws Exception {
Stat stat = zkClient.exists("/eclipse", false);
System.out.println(stat == null ? "not exist" : "exist");
} /**
* 获取子节点
*
* @throws Exception
*/
@Test
public void testGetChild() throws Exception {
List<String> children = zkClient.getChildren("/", true);
for (String child : children) {
System.out.println(child);
}
} /**
* 删除节点
*
* @throws Exception
*/
@Test
public void testDelete() throws Exception {
// 参数2:指定要删除的版本,-1表示删除所有版本
zkClient.delete("/abc", -1);
} /**
* 获取节点的数据
*
* @throws Exception
*/
@Test
public void testGetDate() throws Exception {
byte[] data = zkClient.getData("/eclipse", false, null);
System.out.println(new String(data));
} }

Zookeeper 入门详解的更多相关文章

  1. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  2. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  3. SQL注入攻防入门详解

    =============安全性篇目录============== 本文转载 毕业开始从事winfrm到今年转到 web ,在码农届已经足足混了快接近3年了,但是对安全方面的知识依旧薄弱,事实上是没机 ...

  4. SQL注入攻防入门详解(2)

    SQL注入攻防入门详解 =============安全性篇目录============== 毕业开始从事winfrm到今年转到 web ,在码农届已经足足混了快接近3年了,但是对安全方面的知识依旧薄弱 ...

  5. Quartz 入门详解

    Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用.Quartz可以用来创建简单或为运行十个,百个, ...

  6. Redis快速入门详解

    Redis入门详解 Redis简介 Redis安装 Redis配置 Redis数据类型 Redis功能 持久化 主从复制 事务支持 发布订阅 管道 虚拟内存 Redis性能 Redis部署 Redis ...

  7. [转]SQL注入攻防入门详解

    原文地址:http://www.cnblogs.com/heyuquan/archive/2012/10/31/2748577.html =============安全性篇目录============ ...

  8. zookeeper使用详解(命令、客户端、源码)

    1. zookeeper使用详解(命令.客户端.源码) 1.1. 前言   zookeeper我们常用来做分布式协调中间件,很多时候我们都接触不到它的原理和用法,我对他的了解也仅限于知道它可以做分布式 ...

  9. [置顶] xamarin android toolbar(踩坑完全入门详解)

    网上关于toolbar的教程有很多,很多新手,在使用toolbar的时候踩坑实在太多了,不好好总结一下,实在浪费.如果你想学习toolbar,你肯定会去去搜索androd toolbar,既然你能看到 ...

随机推荐

  1. web前端——Vue.js基础学习之class与样式绑定

    打着巩固 css 知识的旗号开始了对 vue 样式绑定的研究,相比前一篇的 demo,本次内容多了各种样式在里面,变得稍微花哨了些,话不多说,直接上代码吧: <html> <head ...

  2. 用JS判断号码

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. jmeter连接oracle数据库

    == 下载及添加这个文件到 这个路径下 连接设置: 测试连接 链接: https://pan.baidu.com/s/1W0YcVf4VLdsjnxv5umKngQ 提取码: np7j

  4. XML解析思想

    获取文档中的数据: 反序列化[巧记:反读] 把内存中的数据存储到文档中: 序列化[巧记:序写] XML解析思想 DOM: 就是将文档中的数据全部加载到内存,在内存中形成DOM树,然后对数据进行增删改查 ...

  5. c++ 容器中元素计数

    #include <iostream>#include <algorithm>#include <vector>#include <functional> ...

  6. 如何不让Excel图表随源数据改变而改变

    如何不让Excel图表随源数据改变而改变 一般我们在用Excel时,经常会碰到一些问题,比如,如何才能不让Excel图表随源数据改变而改变呢,下面就谈一下,一般在默认情况下,Excel的图表在一个区域 ...

  7. 一个数独引发的惨案:零知识证明(Zero-Knowledge Proof)

    导言:原文的作者是著名的Ghost和Spectre 这两个协议的创始团队的领队Aviv Zohar.原文作者说他的这篇原文又是引用了以下这两篇学术论文: How to Explain Zero Kno ...

  8. 超详细的EM算法理解

    众所周知,极大似然估计是一种应用很广泛的参数估计方法.例如我手头有一些东北人的身高的数据,又知道身高的概率模型是高斯分布,那么利用极大化似然函数的方法可以估计出高斯分布的两个参数,均值和方差.这个方法 ...

  9. ffmpeg 使用 gdb 调试相关技巧

    本文说明了,在ffmpeg二次开发或调用库的过程,如何借助于ffmpeg源码进行调试. 注:ffmpeg版本是4.0. 1. 编写代码 编写将pcm数据转换为mp2的代码 pcm_to_mp2.c # ...

  10. 最新 三七互娱java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.三七互娱等10家互联网公司的校招Offer,因为某些自身原因最终选择了三七互娱.6.7月主要是做系统复习.项目复盘.Leet ...