zookeeper的部署和使用
1.1 zookeeper 的部署和使用 1.1.1系统描述

ZooKeeper是一个高可用、高可靠的协同工作系统,分布式程序可以用ZooKeeper保存并更新关键共享状态。

Katta使用zookeeper保证主节点和搜索节点的有效性,指派索引文件给搜索节点,察觉搜索节点的失效等。

1.1.2 安装和配置

安装zookeeper也很简单,下载zookeeper-3.1.1.tar.gz,解压到/home/hezhiming/zookeeper-3.1.1。zookeeper要部署到各台机器的相同目录下,且具有相同的配置文件。

Zookeeper 的配置文件主要有以下两个:

1、/zookeeper -3.1.1/conf/zoo.cfg:

# The number of milliseconds of each tick

tickTime=2000

# The number of ticks that the initial

# synchronization phase can take

initLimit=10

# The number of ticks that can pass between

# sending a request and getting an acknowledgement

syncLimit=5

# the directory where the snapshot is stored.

dataDir=/home/nutch/zookeeper-3.1.1/zookeeper-data

# the port at which the clients will connect

clientPort=3355

# 2888,3888 are election port

server.1=devcluster01:2555:3555

server.2=devcluster05:2555:3555

server.3=devcluster06:2555:3555

注明:2555端口号是zookeeper服务之间通信的端口,而3555是zookeeper与其他应用程序通信的端口。

2、myid(在zoo.cfg 配置的dataDir目录下,此处为/home/nutch/zookeeper-3.1.1/zookeeper-data)

注意: Myid中的值与server的编号相同:

devcluster01上的myid:

1

devcluster05上的myid:

2

devcluster06上的myid:

3

1.1.3 启动 zookeeper

到每台zookeeper server的目录下,执行:

启动 ./bin/zkServer.sh start

关闭 ./bin/zkServer.sh start

1.1.4zookeeper 的使用

zookeeper启动之后,不需要执行命令,只需查看批准的状况,命令如下:

1、ruok - The server will respond with imok if it is running. Otherwise it will not respond at all.

2、kill - When issued from the local machine, the server will shut down.

3、dump - Lists the outstanding sessions and ephemeral nodes. This only works on the leader.

4、stat - Lists statistics about performance and connected clients.

例如:

$echo ruok | nc 127.0.0.1 3355

Imok$

2.1 Katta 和zookeeper的关系 2.4.1 什么是zookeeper?

zookeeper是针对分布式应用的分布式协作服务,它的目的就是为了减轻分布式应用从头开发协作服务的负担。

它的基本功能是命名服务(naming),配置管理(configuration management),同步(synchronization)和组服务 (group services)。在此基础上可以实现分布式系统的一致性,组管理,Leader选举等功能。

一个zookeeper机群包含多个zookeeper服务器,这些Server彼此都知道对方的存在。 Zookeeper系统结构图如图2所示:

图2 zookeeper系统结构图

l、所有的Server都保存有一份目前zookeeper系统状态的备份;

2、在zookeeper启动的时候,会自动选取一个Server作为Leader,其余的Server都是Follower;

3、作为Follower的Server服务于Client,接受Client的请求,并把Client的请求转交给Leader,由Leader提交请求。

4、Client只与单个的zookeeper服务器连接。Client维护一个持久TCP连接,通过其发送请求, 获取响应和事件,并发送心跳信息。如果Client到Server的TCP连接中断, Client将会连接到另外一个Server。

5、zookeeper集群的可靠性是我们使用它的原因,只要不超过半数的服务器当机(如果正常服务的服务器数目不足一半,那么原有的机群将可能被划分成两个信息无法一致的zookeeper服务),该服务就能正常运行。

2.4.2 zookeeper 的虚拟文件系统

Zookeeper允许多个分布在不同服务器上的进程基于一个共享的、类似标准文件系统的树状虚拟文件系统来进行协作。虚拟文件系统中的每个数据节点都称作一个znode。每个znode都可以把数据关联到它本身或者它的子节点.如图3所示:

图3 zookeeper的虚拟文件系统目录结构

1、每个znode的名称都是绝对路径名来组成的,如“/katta/index/index_name”等。

2、读取或写入znode中的数据都是原子操作,read会获取znode中的所有字节, write会整个替换znode中的信息.每个znode都包含一个访问控制列表(ACL)以约束该节点的访问者和权限.

3、有些znode是临时节点.临时节点在创建它的session的生命周期内存活, 当其session终止时,此类节点将会被删除.

4、zookeeper提供znode监听器的概念. Client可以在某个znode上设置监听器以监听该znode的变更. 当znode有变更时, 这些Client将会收到通知,并执行预先敲定好的函数。

那么Zookeeper能为我们做什么事情呢?简单的例子:假设这样一个系统:

1) 20个搜索引擎的服务器(每个服务器负责一部分索引的搜索任务),每个搜索引擎的服务器有时提供搜索服务有时生成索引,但不能同时做这两件事;

2) 一个总服务器(负责向这20个搜索引擎的服务器发出搜索请求并合并结果集) ;

3) 一个备用的总服务器(负责当总服务器宕机时替换总服务器) ;

4) 一个web的cgi(向总服务器发出搜索请求) 。

使用Zookeeper可以保证:

1. 总服务器自动感知有多少台服务器可以提供搜索服务,并向这些服务器发出搜索请求;

2. 总服务器当机时自动启用备用的总服务器;

3. Web的cgi能够自动地获知总服务器的网络地址变化。

这些都可以通过zookeeper的虚拟文件系统来实现,把这些状态信息,配置,位置等信息都保存于znode中,znode是被所有服务器共享的,通过znode及其数据的变化来完成服务器之间的协作。

2.4.3 Katta 与zookeeper的关系

l、Katta使用zookeeper保证Master主节点和Node子节点的有效性,在Master主节点和Node子节点之间传递消息,保存一些配置信息,保证文件读取的一致性等。

2、Master管理服务器, Node检索服务器和Client服务器之间的通信就是通过zookeeper来实现的。

3、Client服务器可以直接从zookeeper服务中读取Node检索服务器列表,并向Node检索服务器发送检索请求,最后从Node检索服务器得到结果,不必经过Master管理服务器。

Zookeeper分布式安装手册
一、安装准备

1、下载zookeeper-3.3.1,地址:http://www.apache.org/dist/hadoop/zookeeper/zookeeper-3.3.1/

2、JDK版本:jdk-6u20-linux-i586.bin

3、操作系统:Linux

4、默认前提是安装完hadoop 0.20.2版本:

    192.168.3.131 namenode

    192.168.3.132 datanode

    192.168.3.133 datanode

二、操作步骤(默认在namenode上进行)


1、拷贝以上文件到Linux的“/usr/”目录下。同时新建目录“/zookeeper-3.3.1”。

2、安装JDK,此步省略...

3、解压zookeeper到/zookeeper-3.3.1目录下。tar -zxvf zookeeper-3.3.1.tar.gz -C /
 zookeeper-3.3.1 
4、将“/zookeeper-3.3.1/conf”目录下zoo_sample.cfg修改名称为“zoo.cfg”

5、打开zoo.cfg文件,修改配置如下:

dataDir=/usr/zookeeper-3.3.1/data

dataLogDir=/usr/zookeeper-3.3.1/log

clientPort=2181 
initLimit=10 
syncLimit=5 
tickTime=2000 
server.1=192.168.3.131:2888:3888 
server.2=192.168.3.132:2888:3888 
server.3=192.168.3.133:2888:3888

6、创建dataDir参数指定的目录(这里指的是“/zookeeper-3.3.1/data”),并在目录下创建文件,命名为“myid”。

7、编辑“myid”文件,并在对应的IP的机器上输入对应的编号。如在192.168.3.131上,“myid”文件内容就是1,

在192.168.3.132上,内容就是2

8、在profile.d下面生成zookeeper.sh文件设置如下:

 # zookeeper path

ZOOKEEPER=/usr/zookeeper-3.3.2

PATH=$PATH:$ZOOKEEPER/bin

export PATH

然后应用  . ./zookeeper.sh

9、将 “/usr/zookeeper-3.3.1” 目录分别拷贝到192.168.3.132和192.168.3.133下。同时修改对应的“myid”文件内容。

10、至此,安装步骤结束,接下来启动zookeeper。

三、启动zookeeper

1、在三台机器上分别执行shell脚本。“sh /jz/zookeeper-3.3.1/bin/zkServer.sh start”

2.启动客户端脚本:“zkCli.sh -server 192.168.1.132:2181”

3、执行完成之后输入“jps”命令,查看进程如下:

namenode上显示如下:

29844 JobTracker 
29583 NameNode 
31477 HMaster 
29762 SecondaryNameNode 
32356 Jps 
31376 HQuorumPeer


datanode:

16812 DataNode 
17032 HRegionServer 
17752 HQuorumPeer 
16921 TaskTracker 
18461 Jps


3、通过输入“sh /jz/zookeeper-3.3.1/bin/zkServer.sh status”检查是否启动,一般返回内容如下:

leader:

JMX enabled by default 
Using config: /jz/zookeeper-3.3.1/bin/../conf/zoo.cfg 
Mode: leader

follower:

JMX enabled by default 
Using config: /jz/zookeeper-3.3.1/bin/../conf/zoo.cfg 
Mode: follower

4、通过在控制台输入命令检查集群zookeeper启动状态。命令如“echo ruok | nc 192.168.3.131 2181”,

控制台输出“imok”

四、注意事项
     通过shell脚本在每个机器上启动zookeeper的时候,可能会显示错误信息“Cannot open channel to X at election address”。

这是由于zoo.cfg文件中指定的其他zookeeper服务找不到所导致。所有机器的zookeeper服务启动之后该错误提示将会消失。

Zookeeper入门

ZooKeeper 是什么?

ZooKeeper 顾名思义 动物园管理员,他是拿来管大象(Hadoop) 、 蜜蜂(Hive) 、 小猪(Pig) 的管理员, Apache Hbase和 Apache Solr 以及LinkedIn sensei 等项目中都采用到了 Zookeeper。ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,ZooKeeper是以Fast Paxos算法为基础,实现同步服务,配置维护和命名服务等分布式应用。

ZooKeeper 如何工作?

ZooKeeper是作为分布式应用建立更高层次的同步(synchronization)、配置管理 (configuration maintenance)、群组(groups)以及名称服务(naming)。在编程上,ZooKeeper设计很简单,所使用的数据模型风格很像文件系统的目录树结构,简单来说,有点类似windows中注册表的结构,有名称,有树节点,有Key(键)/Value(值)对的关系,可以看做一个树形结构的数据库,分布在不同的机器上做名称管理。

Zookeeper分为2个部分:服务器端和客户端,客户端只连接到整个ZooKeeper服务的某个服务器上。客户端使用并维护一个TCP连接,通过这个连接发送请求、接受响应、获取观察的事件以及发送心跳。如果这个TCP连接中断,客户端将尝试连接到另外的ZooKeeper服务器。客户端第一次连接到ZooKeeper服务时,接受这个连接的 ZooKeeper服务器会为这个客户端建立一个会话。当这个客户端连接到另外的服务器时,这个会话会被新的服务器重新建立。

启动Zookeeper服务器集群环境后,多个Zookeeper服务器在工作前会选举出一个Leader,在接下来的工作中这个被选举出来的Leader死了,而剩下的Zookeeper服务器会知道这个Leader死掉了,在活着的Zookeeper集群中会继续选出一个Leader,选举出leader的目的是为了可以在分布式的环境中保证数据的一致性。如图所示:

另外,ZooKeeper 支持watch(观察)的概念。客户端可以在每个znode结点上设置一个观察。如果被观察服务端的znode结点有变更,那么watch就会被触发,这个watch所属的客户端将接收到一个通知包被告知结点已经发生变化。若客户端和所连接的ZooKeeper服务器断开连接时,其他客户端也会收到一个通知,也就说一个Zookeeper服务器端可以对于多个客户端,当然也可以多个Zookeeper服务器端可以对于多个客户端,如图所示:

你还可以通过命令查看出,当前那个Zookeeper服务端的节点是Leader,哪个是Follower,如图所示:

我通过试验观察到 Zookeeper的集群环境最好有3台以上的节点,如果只有2台,那么2台当中不管那台机器down掉,将只会剩下一个leader,那么如果有再有客户端连接上来,将无法工作,并且剩下的leader服务器会不断的抛出异常。内容如下:
java.net.ConnectException: Connection refused
at sun.nio.ch.Net.connect(Native Method)
at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:507)
at java.nio.channels.SocketChannel.open(SocketChannel.java:146)
at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectOne(QuorumCnxManager.java:347)
at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectAll(QuorumCnxManager.java:381)
at org.apache.zookeeper.server.quorum.FastLeaderElection.lookForLeader(FastLeaderElection.java:674)
at org.apache.zookeeper.server.quorum.QuorumPeer.run(QuorumPeer.java:611)
2010-11-15 00:31:52,031 – INFO [QuorumPeer:/0:0:0:0:0:0:0:0:2181:FastLeaderElection@683] – Notification time out: 12800

并且客户端连接时还会抛出这样的异常,说明连接被拒绝,并且等待一个socket连接新的连接,这里socket新的连接指的是zookeeper中的一个Follower。
org.apache.zookeeper.ClientCnxn$SendThread.startConnect(ClientCnxn.java:1000) Opening socket connection to server 192.168.50.211/192.168.50.211:2181 
org.apache.zookeeper.ClientCnxn$SendThread.primeConnection(ClientCnxn.java:908) Socket connection established to 192.168.50.211/192.168.50.211:2181, initiating session 
org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1118) Unable to read additional data from server sessionid 0×0, likely server has closed socket, closing socket connection and attempting reconnect 
org.apache.zookeeper.ClientCnxn$SendThread.startConnect(ClientCnxn.java:1000) Opening socket connection to server localhost/127.0.0.1:2181 
2010-11-15 13:31:56,626 WARN org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1120) Session 0×0 for server null, unexpected error, closing socket connection and attempting reconnect 

记得在大约在2006年的时候Google出了Chubby来解决分布一致性的问题(distributed consensus problem),所有集群中的服务器通过Chubby最终选出一个Master Server ,最后这个Master Server来协调工作。简单来说其原理就是:在一个分布式系统中,有一组服务器在运行同样的程序,它们需要确定一个Value,以那个服务器提供的信息为主/为准,当这个服务器经过n/2+1的方式被选出来后,所有的机器上的Process都会被通知到这个服务器就是主服务器 Master服务器,大家以他提供的信息为准。很想知道Google Chubby中的奥妙,可惜人家Google不开源,自家用。

但是在2009年3年以后沉默已久的Yahoo在Apache上推出了类似的产品ZooKeeper,并且在Google原有Chubby的设计思想上做了一些改进,因为ZooKeeper并不是完全遵循Paxos协议,而是基于自身设计并优化的一个2 phase commit的协议,如图所示:

ZooKeeper跟Chubby一样用来存放一些相互协作的信息(Coordination),这些信息比较小一般不会超过1M,在zookeeper中是以一种hierarchical tree的形式来存放,这些具体的Key/Value信息就store在tree node中,如图所示:

当有事件导致node数据,例如:变更,增加,删除时,Zookeeper就会调用 triggerWatch方法,判断当前的path来是否有对应的监听者(watcher),如果有watcher,会触发其process方法,执行process方法中的业务逻辑,如图所示:

应用实例
ZooKeeper有了上述的这些用途,让我们设想一下,在一个分布式系统中有这这样的一个应用:
2个任务工厂(Task Factory)一主一从,如果从的发现主的死了以后,从的就开始工作,他的工作就是向下面很多台代理(Agent)发送指令,让每台代理(Agent)获得不同的账户进行分布式并行计算,而每台代理(Agent)中将分配很多帐号,如果其中一台代理(Agent)死掉了,那么这台死掉的代理上的账户就不会继续工作了。
上述,出现了3个最主要的问题
1.Task Factory 主/从一致性的问题
2.Task Factory 主/从心跳如何用简单+稳定 或者2者折中的方式实现。
3.一台代理(Agent)死掉了以后,一部分的账户就无法继续工作,需要通知所有在线的代理(Agent)重新分配一次帐号。

怕文字阐述的不够清楚,画了系统中的Task Factory和Agent的大概系统关系,如图所示:

OK,让我们想想ZooKeeper是不是能帮助我们去解决目前遇到的这3个最主要的问题呢?
解决思路
1. 任务工厂Task Factory都连接到ZooKeeper上,创建节点,设置对这个节点进行监控,监控方法例如:
event= new WatchedEvent(EventType.NodeDeleted, KeeperState.SyncConnected, "/TaskFactory");
这个方法的意思就是只要Task Factory与zookeeper断开连接后,这个节点就会被自动删除。

2.原来主的任务工厂断开了TCP连接,这个被创建的/TaskFactory节点就不存在了,而且另外一个连接在上面的Task Factory可以立刻收到这个事件(Event),知道这个节点不存在了,也就是说主TaskFactory死了。

3.接下来另外一个活着的TaskFactory会再次创建/TaskFactory节点,并且写入自己的ip到znode里面,作为新的标记。

4.此时Agents也会知道主的TaskFactory不工作了,为了防止系统中大量的抛出异常,他们将会先把自己手上的事情做完,然后挂起,等待收到Zookeeper上重新创建一个/TaskFactory节点,收到 EventType.NodeCreated 类型的事件将会继续工作。

5.原来从的TaskFactory 将自己变成一个主TaskFactory,当系统管理员启动原来死掉的主的TaskFactory,世界又恢复平静了。

6.如果一台代理死掉,其他代理他们将会先把自己手上的事情做完,然后挂起,向TaskFactory发送请求,TaskFactory会重新分配(sharding)帐户到每个Agent上了,继续工作。

上述内容,大致如图所示:

Zookeeper/Hbase/Hadoop三者之间的关系,在此我把三者之间的关系画在一张图上希望能表达的清楚一些。

Zookeeper用来同步Hbase服务状态、监控集群防止单点失效
HDFS是Hadoop中最核心的一部分,用来对Hbase的数据进行存储

1、Zookeeper客户端与服务端的大致结构
服务端
Zookeeper还是属于一个C/S的架构的应用服务,Zookeeper的服务器端分为2种运行模式:单台和集群多台的运行模式,通过conf/zoo.cfg中的配置判定你启用的运行模式,以及在群集模式中数据同步和心跳的频率等等。
Zookeeper集群中的Leader和Follower之间的选举通过Paxos算法来实现的,它是一个基于消息传递的一致性算法,这里讲述了http://zh.wikipedia.org/zh-cn/Paxos算法,传说中Paxos算法是分布式一致性算法中最有效的一种算法。
口水:在源代码中的通讯部分看见了大量采用NIO和concurrent的代码(例如:LinkedBlockingQueue/AtomicLong)。

客户端
ZooKeeper的Client由三个主要模块组成:
Zookeeper
Zookeeper是最主要的类,可以写入一个或者多个Zookeeper的服务器地址,例如:"127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002" ,当你new Zookeeper( ….)的时候会有两个线程被创建:SendThread和EventThread,会在Server端创建大量的Session。
WatcherManager
在Zookeeper类中还有一个WatcherManager,用来管理Watcher的,Watcher是ZK的一大特色功能,允许多个Client对一个或多个 ZNode进行监控,当ZNode有变化时能够通知到监控这个ZNode的各个Client,管理了ZK Client绑定的所有Watcher。
ClientCnxn
在Zookeeper类中还包含了对ClientCnxn类的调用,ClientCnxn这个类管理所有对Zookeeper服务器端的网络通讯,服务端和客户端所有交互的数据都要调用这个类,包括给ZK Server发送Request,从ZK Server接受Response,以及从ZK Server接受Watcher Event。

2、服务端运行模式
服务端单机模式
zoo.cfg文件配置参数详解
# 这个时间是被用来做服务器之间或客户端与服务器心跳和最低会话超时时间的基数。
tickTime=2000
# 存储在内存中数据快照的目录。
dataDir=d:/zookeeperdata/1
# 服务器端开启的监听端口,用来接受客户端访问请求的端口。
clientPort=2181

服务端集群模式
配置参数详解
#Zookeeper服务器集群中连接到Leader与Follower 服务器少次心跳时间间隔数,以及最大通讯的超时时间,总时间为 5(initLimit)*2000(tickTime)=10 秒
initLimit=5 
#Leader与Follower间请求/应答时间长度,这里总时间长度就是 2(syncLimit)*2000(tickTime)=4 秒
syncLimit=2 
#server是固定配置,1和2表示这个是第几号服务器,2888:3888表示服务器与集群中的 Leader 服务器的通讯端口
server.1=192.168.1.1:2888:3888 
server.2=192.168.1.2:2888:3888

另外,集群模式下还要在 dataDir 目录下创建一个myid文件,这个文件中写入的内容就是一个数字,这个数字就是和server.x中的x这个数字对应,Zookeeper 启动时会读取这个文件判定自己是谁,myid文件的编码格式是ANSI

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐