Zookeeper 是一个分布式调度服务,用来解决分布式系统中的统一调度问题。开发一个分布式系统是一件很困难的事情,主要缘由就是由于咱们没办法去颇有效的处理分布式系统中部分服务失败的问题。在一个分布式系统中,不一样机器间是须要互相通讯的,而且由通讯方发起到被通讯方,而后结果要由被通讯方回应。这时候假如被通讯方由于机房故障或者断电网络等一些因素,没办法通知,这样通讯方就不知道发生了什么,这样整个集群就发生了部分失败的故障。Zookeeper 提供了一些工具可以让分布式应用安全合理的处理部分失败的问题。php
Zookeeper 的运行有两种方式,一种是 Standalone,还有一个就是 Replicated。这两种的区别就是第一种只部署了单个节点,并且第二种就是以集群的方式来部署。当以集群来部署的时候,客户端不须要链接全部的服务端,只须要链接其中一个就能够得到一致性的读写服务。node
到 Apache Zookeeper 的下载页面下载安装包,而且解压出来:shell
wget https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.4.11/zookeeper-3.4.11.tar.gz tar -xzvf zookeeper-3.4.11.tar.gz cd zookeeper-3.4.11
启动一个 Standalone 的服务很简单,只须要一个配置文件而且放到 conf/zoo.cfg 下面便可,在 conf 目录下 Zookeeper 已经有一个默认的文件了,直接复制过来便可,内容大概是这样:apache
tickTime=2000 dataDir=/var/lib/zookeeper clientPort=2181
其中 tickTime 是基本时间单元,以毫秒为单位,用来控制心跳和超时,默认状况下最小的会话超时时间为两倍的 tickTime 。而后启动:安全
bin/zkServer.sh start
每一个程序的第一步都是跑一个 HelloWorld,Zookeeper 也不例外,输入如下的命令:服务器
echo ruok | nc localhost 2181
你应该会看到:网络
imok
Zookeeper 的数据存储就相似是一个文件系统,可是没有文件和文件夹的概念,取而代之的是以 znode 来标示的。这个 znode 既是数据的容器,也是其余节点的容器,也就是说 znode 能够存储数据和其余 znode (能够理解为文件和文件夹,znode 就是文件夹,里面的数据就是文件,惟一不一样的是一个 znode 只能有一个数据,可是能够有多个其余的 znode),能够看一下图:分布式
Zookeeper 自带了一个命令行的客户端,咱们能够经过该命令行来操做一下,首先链接到 Zookeeper:工具
bin/zkCli.sh -server 127.0.0.1:2181
你应该能够看到如下,而且光标一直在闪烁等待输入,可使用 ls /
命令简单操做一下。测试
Welcome to ZooKeeper! [zk: 127.0.0.1:2181(CONNECTED) 0]
在 Zookeeper 中,ZNode 能够分为持久节点和临时节点两类。持久节点是指一旦这个 ZNode 被建立了,除非主动进行删除操做,不然将一直保存在ZooKeeper上;临时节点就是和客户端会话绑定,一旦客户端断开连接,那么这个客户端建立的全部临时节点都会被移除。
[zkshell: 9] create /zk_test my_data Created /zk_test
其中的/zk_test
是 znode 的名字,my_data
是具体存储的数据,建立成功以后能够用 ls /
来查看一下:
[zkshell: 11] ls / [zookeeper, zk_test]
接下来,经过运行get命令来验证数据是否与znode相关联,以下所示:
[zkshell:12] get / zk_test my_data cZxid = 5 ctime = Fri Jun 05 13:57:06 PDT 2009 mZxid = 5 mtime = Fri Jun 05 13:57:06 PDT 2009 pZxid = 5 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0 dataLength = 7 numChildren = 0
[zkshell:14] set / zk_test junk [zkshell:15] get / zk_test junk
为了方便阅读,去除掉了部分无关的数据显示。
接下来删除掉刚才建立的 znode,注意若是该 znode 下有其余的 znode,则没法删除,必需要先把其余的删除了。
[zkshell:16] delete / zk_test [zkshell:17] ls / [zookeeper]
在开发和测试环境中咱们能够以 Standalone 的方式来运行,可是若是要部署到生产环境那么就应用以 Replicated 的方式来部署以得到更高的可用性。在该模式下至少须要三台服务器,而且强烈建议要有一个奇数的服务器。若是你只有两台服务器,那么就会有这样一种状况,若是其中一台服务器出现故障,就会没有足够的机器来造成大多数投票决策,两台服务器本质上不如 一台服务器稳定,由于有两个单点故障。修改配置文件:
tickTime = 2000 dataDir = /var/lib/zookeeper clientPort = 2181 initLimit = 5 syncLimit = 2 server.1 = zoo1:2888:3888 server.2 = zoo2:2888:3888 server.3 = zoo3:2888:3888
若是有三台机器的话,每台机器都要这样的配置。而后还要到/var/lib/zookeeper
新建一个myid
的文本文件,内容就是server.X
中的X
。接下来就能够按照正常方式启动了,启动以后 Zookeeper 会自动投票选举出一个 Leader,其余的机器就是 Follower
在 Linux 的文件系统中,权限是以组和用户来表示的,在 Zookeeper 有他本身的一套 ACL 权限用来控制客户端的访问权限(相似用户对资源是否有读写权限),经过鉴权来得到客户端的身份(相似帐号密码登陆)。它自己的 ACL 机制是以 schemepermissions来表示的,第一个字段表示采用哪一种机制,第二个 id 表示用户,permissions表示相关权限(如只读,读写,管理等)。Zookeeper 总共提供了五中的 scheme :
只是 ACL 毕竟是简单的访问控制,并不是完整的权限管理,仍是有不少局限性。好比 ACL 没有继承机制,全部的 ZNode 建立后都须要从新设置 ACL 而没法继承上一级的。
在对 ZooKeeper 有了一个简单的了解之后,咱们就能够用 Zookeeper 来构建一个简单的配置管理服务。集群中的机器能够经过 ZooKeeper 共享一个通用的配置数据,而且能够提供检索和更新配置的服务,咱们会用 PHP 语言来实现。
PHP 在操做 Zookeeper 的时候是须要安装一个扩展的,咱们能够到 PECL 上面去下载。要注意的是该扩展要依赖一个 C 语言编写的客户端,Zookeeper 已经内置好了,进去 zookeeper-3.4.11/src/c
的目录下,编译安装便可。
接下来咱们要新建一个 /config
的节点,把全部的配置都放到该节点下,很简单:
[zkshell: 9] create /config my_data Created /config
咱们设计用 ZNode 来存储配置的 key-value 键值对,咱们在 ZNode 中存储一个 String 类型的数据做为 value,用 ZNode 的 path 来表示 key。定义一个客户端来读取数据,而且经过 CLI 的方式运行起来,代码不能再简单了:
$zc = new Zookeeper(); $zc->connect('localhost:2181'); $path = '/config/key1'; $zc->get($path, function($i, $type, $key) use ($zc, $path){ echo $key."\n"; echo $zc->get($path); }); while(true){ echo ".\n"; sleep(1); }
而后经过 Zookeeper 自带的命令行客户端来修改一下配置:
切换回去 PHP CLI 的控制台终端窗口应该就能够看到:
咱们所实现的程序目前都是假设网络稳定的状况下实现的,可是一个真实的状况是,网络环境是会有不少缘由致使不稳定的。这里不会讲述如何正确的处理这些失败,会在接下来的高级篇里面在阐述。
欢迎关个人我的公众号:左手代码