赞
踩
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。Zookeeper是Apache的一个java项目,属于Hadoop系统,扮演管理员的角色。它为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。ZooKeeper提供一种集中式服务,用于维护配置信息,命名,提供分布式同步和提供组服务。所有这些类型的服务都以分布式应用程序的某种形式使用。每次实施它们都需要做很多工作来修复不可避免的错误和竞争条件,ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
ZooKeeper用于分布式应用程序的分布式开源协调服务。它公开了一组简单的原语,分布式应用程序可以构建这些原语,以实现更高级别的服务,以实现同步,配置维护以及组和命名。它被设计为易于编程,并使用在熟悉的文件系统目录树结构之后设计的数据模型。它在Java中运行,并且具有Java和C的绑定,ZooKeeper包含一个简单的原语集,提供Java和C的接口。ZooKeeper背后的动机是减轻分布式应用程序从头开始实施协调服务的责任。
ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services.
Zookeeper设计目标:
ZooKeeper允许分布式进程通过共享的分层命名空间相互协调,该命名空间的组织方式与标准文件系统类似。名称空间由数据寄存器组成 - 在ZooKeeper用语中称为znodes,zookeeper名字空间由节点znode构成 - 这些与文件和目录类似。znode是一个跟Unix文件系统路径相似的节点,可以往这个节点存储或获取数据。如果在创建znode时Flag设置为EPHEMERAL(临时节点,znode有2种类型),那么当创建这个znode的节点和Zookeeper失去连接后,这个znode将不再存在在Zookeeper里,与专为存储而设计的典型文件系统不同,ZooKeeper数据保存在内存中,这意味着ZooKeeper可以实现高吞吐量和低延迟数量。
Zookeeper实现过程中非常重视高性能,高可用性,严格有序的访问。ZooKeeper的性能方面意味着它可以在大型分布式系统中使用。可靠性方面使其不会成为单点故障。严格的排序意味着可以在客户端实现复杂的同步原语。越来越多的分布式计算开始强依赖ZK,比如Storm、Hbase等;
使用场景:
集群管理、统一命名服务、分布式配置管理、分布式消息队列、分布 式锁、分布式通知协调等。
zookeeper与它协调的分布式进程一样,ZooKeeper本身也可以在称为集合的一组主机上进行复制。组成ZooKeeper服务的服务器必须彼此了解。它们维护内存中的状态图像,以及持久性存储中的事务日志和快照。只要大多数服务器可用,ZooKeeper服务就可用。
客户端连接到单个ZooKeeper服务器。客户端维护TCP连接,通过该连接发送请求,获取响应,获取监视事件以及发送心跳。如果与服务器的TCP连接中断,则客户端将连接到其他服务器;
架构解析:
Zookeeper Server数目一般为奇数 ;Leader选举算法采用了Paxos协议;Paxos核心思想:当多数Server写成功,则任务数据写 成功。也就是说: 如果有3个Server,则两个写成功即可; 如果有4或5个Server,则三个写成功即可。 如果有3个Server,则最多允许1个Server挂掉; 如果有4个Server,则同样最多允许1个Server挂掉,既然如此,为啥要用4个Server,3个已经足够?Server数目一般为奇数(3、5、7) 。
ZooKeeper提供的名称空间非常类似于标准文件系统。名称是由斜杠(/)分隔的路径元素序列。ZooKeeper名称空间中的每个节点都由路径标识。与标准文件系统不同,ZooKeeper命名空间中的每个节点都可以包含与之关联的数据以及子项。这就像拥有一个既是文件也是目录的文件系统。(ZooKeeper旨在存储协调数据:状态信息,配置,位置信息等,因此存储在每个节点的数据通常很小,在字节到千字节范围内。)我们使用术语znode来表明ZooKeeper的数据节点。
Znodes维护一个stat结构,其中包括数据更改,ACL更改和时间戳的版本号,以允许缓存验证和协调更新。每次znode的数据更改时,版本号都会增加。例如,每当客户端检索数据时,它也接收数据的版本。存储在命名空间中每个znode的数据以原子方式读取和写入。读取获取与znode关联的所有数据字节,写入替换所有数据。每个节点都有一个访问控制列表(ACL),限制谁可以做什么。
ZooKeeper也有短暂(临时)节点的概念。只要创建znode的会话处于活动状态,就会存在这些znode。会话结束时,znode将被删除。当您想要实现[tbd(?)时,短暂节点很有用。
zookeeper中支持watches的概念,客户端可以在znode上设置一个watch,当znode被更新时watch会被触发或删除;当watch被触发时,客户端会收到znode更新的反馈包,如客户端与zookeeper服务集群中的一个服务端中断连接,则客户端将收到本地通知。
Observer :
Zookeeper需保证高可用和强一致性; 当集群节点数目逐渐增大为了支持更多的客户端,需要增加更多Server,然而Server增多,投票阶段延迟增大,影响性能。为了权衡伸缩性和高吞吐率,故引入Observer: Observer不参与投票; Observers接受客户端的连接,并将写请求转发给leader节点;
加入更多Observer节点,提高伸缩性,同时不影响吞吐率。
组织结构:
zookeeper采用层次化的目录结构,命名符合常规文件系统规范;
每个目录在zookeeper中叫做znode,并且其有一个唯一的路径标识;
Znode:
Znode可以包含数据和子znode(ephemeral类型的节点不能有子znode);
Znode中的数据可以有多个版本,比如某一个znode下存有多个数据版本,那么查询这个路径下的数据需带上版本;
客户端应用可以在znode上设置监视器(Watcher)
znode不支持部分读写,而是一次性完整读写
Znode类型:
Znode有两种类型,短暂的(ephemeral)和持久的(persistent);
Znode的类型在创建时确定并且之后不能再修改;
ephemeral znode的客户端会话结束时,zookeeper会将该ephemeral znode删除,ephemeralzn ode不可以有子节点;
persistent znode不依赖于客户端会话,只有当客户端明确要删除该persistent znode时才会被删除;
Znode有四种形式的目录节点,PERSISTENT、PERSISTENT_SEQUENTIAL、EPHEMERAL、PHEMERAL_SEQUENTIAL。
ZooKeeper的设计目标之一是提供一个非常简单的编程接口。因此,它仅支持以下操作:
create:在树中的某个位置创建一个节点
delete:删除节点
exists:测试某个位置是否存在节点
获取数据:从节点读取数据
设置数据:将数据写入节点
get children:检索节点的子节点列表
sync:等待传播数据
zookeeper集群部署如下:
server1:192.168.0.1
server2:192.168.0.2,
server3:192.168.0.3.
1)下载zookeeper
到http://zookeeper.apache.org/releases.html去下载最新版本Zookeeper-3.4.5的安装包zookeeper-3.4.5.tar.gz.将文件保存server1的~目录下
2)安装zookeeper
先在服务器分别执行a-c步骤
a)解压
tar -zxvf zookeeper-3.4.5.tar.gz
解压完成后在目录~下会发现多出一个目录zookeeper-3.4.5,重新命令为zookeeper
b)配置
cp zoo_sample.cfg zoo.cfg
vi /opt/zookeeper/zoo.cfg
#将conf/zoo_sample.cfg拷贝一份命名为zoo.cfg,也放在conf目录下。然后按照如下值修改其中的配置:
# The number of milliseconds of each tick
tickTime=2000 ##这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。用于客户端与服务器或者服务器与服务器之间维持心跳,也就是每个tickTime时间就会发送一次心跳。通过心跳不仅能够用来监听机器的工作状态,还可以通过心跳来控制Flower跟Leader的通信时间,默认情况下FL的会话时常是心跳间隔的两倍。
# The number of ticks that the initial
# synchronization phase can take
initLimit=10 ##集群中的follower服务器(F)与leader服务器(L)之间初始连接时能容忍的最多心跳数(tickTime的数量),Zookeeper 接受(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。这个配置项是用来配置 当已经超过 5个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5*2000=10 秒;
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5 ##标识 Leader 与Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是2*2000=4 秒;集群中flower服务器(F)跟leader(L)服务器之间的请求和答应最多能容忍的心跳数
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/home/wwb/zookeeper/data ##是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。该属性对应的目录是用来存放myid信息跟一些版本,日志,跟服务器唯一的ID信息等。注意不要使用默认的/tmp来做存储快照的目录
dataLogDir=/home/wwb/zookeeper/logs
##dataDir,dataLogDir中的wwb是当前登录用户名,data,logs目录开始是不存在,需要使用mkdir命令创建相应的目录。并且在data 目录下创建文件myid文件,且serve1,server2,server3该文件内容分别为1,2,3。针对服务器server2,server3可以将server1复制到相应的目录,不过dataDir,dataLogDir目录下的文件myid内容分别为2,3
# the port at which the clients will connect
clientPort=2181 ##客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#http://zookeeper.apache.org/doc/ ... html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
server.1=192.168.0.1:3888:4888
##3888是服务器与集群中的 Leader 服务器交换信息的端口,4888表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。
server.2=192.168.0.2:3888:4888
server.3=192.168.0.3:3888:4888
##如是单击多实例部署的伪集群方式,Zookeeper 各实例通信端口号不能一样
关于在各服务器上创建myid标识文件,在dataDir配置项指定的目录下创建myid文件,文件内容为当前节点在集群中的ID,在节点192.168.0.1上执行:
echo "1" > /home/wwb/zookeeper/data/myid
在节点192.168.0.2上执行:
echo "2" > /home/wwb/zookeeper/data/myid
在节点192.168.0.3上执行:
echo "3" > /home/wwb/zookeeper/data/myid
执行:/home/wwb/zookeeper/bin/zkServer.sh start,出现类似以下内容
JMX enabled by default
Using config: /home/wwb/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
执行:/home/wwb/zookeeper/bin/zkCli.sh -server 192.168.0.2:2181,出现类似以下内容
JLine support is enabled
2013-11-27 19:59:40,560 - INFO [main-SendThread(localhost.localdomain:2181):ClientCnxn$SendThread@736]- Session establishmentcomplete on localhost.localdomain/127.0.0.1:2181, sessionid = 0x1429cdb49220000, negotiatedtimeout = 30000
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
[zk: 127.0.0.1:2181(CONNECTED) 0] [root@localhostzookeeper2]#
如上述都正常,即代表zk集群构建成功了,如果出现错误那应该是第三步时没有启动好集群
5、验证
ps aux | grep zookeeper //查看是否有相应的进程, 没有话,说明集群启动出现问题,可以在每个服务器上尝试重启,执行:
/home/wwb/zookeeper/bin/zkServer.sh stop
/home/wwb/zookeeper/bin/zkServer.sh start
如果还是有问题,那么先stop再到bin的上级目录尝试执行
/bin/zkServer.sh start
注意:zookeeper集群启动运行时,zookeeper要求半数以上的机器可用,zookeeper才能提供服务。
/home/wwb/zookeeper/bin/zkServer.sh status
注意:需要启动至少两个节点以后,通过上述命令查看时才能看到正常的状态。由于没有指定日志输出目录,默认会在zookeeper安装目录下的bin目录里生成日志文件,名为zookeeper.out
6、配置使用systemd启停ZooKeeper
创建并编辑/usr/lib/systemd/system/zkServer.service文件,文件内容如下:
[Unit]
Description=ZooKeeper Server
Documentation=https://zookeeper.apache.org/
After=network-online.target
Wants=network-online.target
[Service]
Type=forking
User=zookeeper
Group=zookeeper
WorkingDirectory=/home/wwb/zookeeper
Environment=ZOO_LOG_DIR=/home/wwb/zookeeper/ogs
ExecStart=/home/wwb/zookeeper/bin/zkServer.sh start
ExecStop=/home/wwb/zookeeper/bin/zkServer.sh stop
Restart=on-failure
RestartSec=10s
[Install]
WantedBy=multi-user.target
配置简要说明:
Type: 这个配置项的值需要设置为“forking”,我一开始配置为“notify”,结果无法通过systemd启动。
User和Group: 指定启动zookeeper的用户和组,如果不指定,默认使用root用户启动。如果设置了用户和组,需要注意zookeeper相关目录和文件的权限问题,否则可能导致启动失败。
Environment: 定义环境变量,这里定义了环境变量“ZOO_LOG_DIR”,这个变量指定了zookeeper运行日志的输出目录。不指定也可以正常启动,配置了WorkingDirectory后,日志会生成在WorkingDirectory指定的目录下。
7、使用systemd启停zookeeper。
systemctl start zkServer //启动
systemctl stop zkServer
systemctl enable zkServer.service
注:zookeeper集群节点数推荐为奇数(2n+1)个,因为如果为偶数个节点,当有一半节点发生故障时,由于没有足够的节点数来选举新的leader节点(要求半数以上节点选举,不包含半数),会导致整个集群无法工作。如果只能部署两个节点,则不如使用单节点,因为两个节点的集群,只要任意一个节点发生故障,则集群无法工作。
8、客户端连接测试
在客户端电脑上,执行以下指令测试连接:
[hadoop@master ~]$ zkCli.sh -server server1:2181
#查看目录
[zk: slave1(CONNECTED) 0] ls /
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。