ZooKeeper。它是Apache Hadoop的一个子项目,它主要用来解决分布式集群中应用系统的一致性问题
这个一致性可以是数据,可以是程序,可以是配置文件
ZooKeeper数据节点,就是znode
Zookeeper 并不是用来专门存储数据的,它的作用主要是用来维护和监控你存储的数据的状态变化
从设计模式角度来看,zookeeper是一个观察者模式设计,负责存储和管理被关心的数据,然后接受观察者的注册和订阅,一旦数据发生变化,zk就负责同志观察者,并作出相应动作
关于zk的安装和配置
从官网将zk下载,并解压,配置好环境变量,
1.在zookeeper根目录需要自己手动mkdir添加一个data目录,并在下面的2.1中设置好,用于存放zk管理的(元)数据。
里面包含了2类文件,一类是myid – 这个文件只包含一个数字,和server id(0,1,2, ...)对应,还有一类是snapshot. – 按zxid先后顺序的生成的数据快照
2.在zoo.cfg中
2.1 指定datadir是这个目录,这个目录中存放的是整个zk集群的快照snapshot,默认情况下,ZK的事务日志也会存储在这个目录中,也可以通过dataLogDir来指定事物日志的存放地点
什么是snapshot:Zookeeper的数据在内存中是以DataTree为数据结构存储的,而快照就是每间隔一段时间Zookeeper就会把整个DataTree的数据序列化然后把它存储在磁盘中,这就是Zookeeper的快照文件
2.2 指定zookeeper集群由哪几台机器构成server.0,server.1,server.2,一般三台,这个和具体需要做ha的机器无关
格式是这样:server.A=B:C:D:
其中 A 是一个数字,表示这个是第几号服务器;
B 是这个服务器的 ip 地址;
C 表示的是这个集群中,Flower和 Leader 之间交换信息的端口;
D 表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口
2.3
tickTime |
ZK中的一个时间单元。ZK中所有时间都是以这个时间单元为基础,进行整数倍配置的。例如,session的最小超时时间是2*tickTime。 |
initLimit |
启动时间限制。Follower在启动过程中,会从Leader同步所有最新数据,然后确定自己能够对外服务的起始状态。Leader允许F在initLimit时间内完成这个工作。通常情况下,我们不用太在意这个参数的设置。如果ZK集群的数据量确实很大了,F在启动的时候,从Leader上同步数据的时间也会相应变长,因此在这种情况下,有必要适当调大这个参数了。(No Java system property) |
syncLimit |
心跳检测时间限制。在运行过程中,Leader负责与ZK集群中所有机器进行通信,例如通过一些心跳检测机制,来检测机器的存活状态。如果L发出心跳包在syncLimit之后,还没有从F那里收到响应,那么就认为这个F已经不在线了。注意:不要把这个参数设置得过大,否则可能会掩盖一些问题。(No Java system property) |
在各个节点上启动zookeeper,
zkServer.sh start 成功表示zookeeper集群成功安装下面是将spark和zookeeper结合,
典型应用场景
zk的统一命名服务(name service) :
在分布式集群环境中,拥有一套完整的命名规则,和JNDI差不多,需要一个唯一的key
配置管理:
在分布式集群中,做多台机器的配置同步:比如将配置信息保存到zk的某个目录节点中,然后如果有更改,就会通知所有注册的机器,机器从zk上面读取配置,进行本地更新
http://www.cnblogs.com/cobbliu/archive/2011/11/04/2389009.html
![](https://images2015.cnblogs.com/blog/987383/201607/987383-20160705230945046-2074022114.gif)
zk的client端是不需要安装zk的,只需要有zk的jar文件就可以进行通信
连接ZK host来检验部署是否成功。
->Java语言的话,可以通过运行这个命令来检测:
$ java -cp zookeeper.jar:lib/slf4j-api-1.6.1.jar:lib/slf4j-log4j12-1.6.1.jar:lib/log4j-1.2.15.jar:conf:src/java/lib/jline-0.9.94.jar \ org.apache.zookeeper.ZooKeeperMain -server 127.0.0.1:2181
->如果是C语言的话,方法如下:
$ make cli_st
$ make cli_mt
然后按照的这样的方式连接ZK:$ cli_mt 127.0.0.1:2181。无论运行哪种客户端,最终都是一个类似于文件系统的命令行操作。
集群管理:
这个是我们最关心的典型场景,就是用于spark,hadoop的方式,帮助master节点做HA的,
在spark集群中,3个master,被zookeeper管理,一个active(叫做leader),另外两个standby状态叫follower
整个集群的元数据都保存在zookeeper中,如果当前active挂了,新选出的leader会去zookeeper中去同步集群的数据,元数据包括worker,driver,applicatiin
在zk对master进行切换的时候,master是不提供服务的,但是正在集群运行的程序是不受影响的,因为driver在之前已经向master申请过计算资源了,计算程序只需要driver和具体的executor进行通信,除非executor挂掉了,再需要master介入,这是粗粒度的资源使用分配策略,好处就是在计算没开始的时候,就规划好了计算资源,不需要像细粒度那样一边计算一边分配资源,很慢,粗粒度的弊端就是如果有一个长任务一直没完成,那么其他的已经完成的任务所占用的资源不会被释放,而是一直占用着。
spark-env.sh文件
export SPARK_DAEMON_JAVA_OPTS="-Dspark.deploy.recoveryMode=ZOOKEEPER -Dspark.deploy.zookeeper.url=192.168.1.117:2181,192.168.1.118:2181,192.168.1.119:2181 -Dspark.deploy.zookeeper.dir=/spark"
整个spark的恢复模式,采用的是zk,也可以是FILESYSTEM,这种方式就是丢失所有的
并且提供zk服务的集群是由3台2181端口的机器组成,然后spark的元数据,存放在zk的/spark位置(/spark是放spark的元数据的,保存spark作业运行的状态之类的东西)
参数 |
默认值 |
含义 |
spark.deploy.recoveryMode |
NONE |
恢复模式(Master重新启动的模式),有三种:1, ZooKeeper, 2, FileSystem, 3 NONE |
spark.deploy.zookeeper.url |
|
ZooKeeper的Server地址 |
spark.deploy.zookeeper.dir |
/spark |
ZooKeeper 保存集群元数据信息的文件目录,包括Worker,Driver和Application。 |
当然,如果zk是为了给kafka,hbase做HA,那么需要到这些组件的配置文件中,指定一个目录存放其元数据,上面的是指定了spark的元数据的存放地址
关于选举功能
zk为每个集群中的zk server创建一个 死了就删并且编号自增长的目录节点(EPHEMERAL_SEQUENTIAL ), 这样当当前的leader挂掉,其余standby的肯定有一个是数字最小的,就把这个数字最小的作为新leader
![](https://images2015.cnblogs.com/blog/987383/201607/987383-20160705232631811-731603713.png)