zookeeper 基本介绍+单机配置+指令+API代码 + 集群配置

一:     zookeeper概述

 

Zookeeper基本介绍

官方网址:http://zookeeper.apache.org/

Zookeeper是一个分布式的协调服务框架,Zookeeper可以解决分布式环境常见的问题:统一命名服务,信息配置管理,数据一致性,集群管理,分布式锁等等。

  

1分布式环境下带来的难题

1.容易出现死锁

2.容易活锁,处于活锁的线程都是非阻塞的,而且每个线程都抢不到资源,会造成cpu的耗费。线程在执行过程中产生了碰撞——再执行——再碰撞,如此循环往复,形成活锁。

3.集群的管理问题,比如某台的宕机需要能够检测到

4.集群配置文件的统一管理问题

5.集群中信息状态的更新通知问题

6.管理集群的选举问题

7.分布式锁的实现,这需要用新的机制和技术来实现

Zookeeper非常重要:后期Hadoop集群会通过Zookeeper,Hbase集群、Storm集群、Kafka集群都会用到Zookeeper。

 

二:    zookeeper单机模式安装配置

 

安装步骤:

0.       关闭虚拟机的防火墙  ,执行:service iptables stop

1.       准备虚拟机,安装并配置jdk 1.6以上

Jdk环境变量配置示例:

JAVA_HOME=/home/software/jdk1.8

CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

PATH=$JAVA_HOME/bin:$PATH

exportJAVA_HOME PATH CLASSPATH

 

2.       上传zookeeper的安装包

3.解压安装 tar -xvf …………

4.进入zookeeper安装目录下的conf目录,有一个zoosample.cfg的文件

复制一份,并重命名为zoo.cfg文件,这个名字固定写死,因为zookeeper启动会检查这个文件,根据这个配置文件里的信息来启动服务

5.进入bin目录

执行:./zkServer.sh start 启动zookeeper

6.进入zookeeper客户端,操作zookeeper

执行:./zkCli.sh

三: zk基础概念及指令


知识点:

1.Zk有一个 根节点  /。对于zk的操作,都是基于根节点来操作的

2.每个节点都可以创建自己的子节点

3.每个节点都叫做 znode节点

4.每个znode节点都可以存储数据

5.多个znode节点共同形成一棵znode树

6.znode树会存在于zk服务端的内存中,供用户快速查询。此外,为了防止数据丢失,znode树数据也会落地到磁盘上,会存到zoo.cfg 里dataDir指定的目录下。

7.znode的路径是全局唯一的。我们可以基于此特性,做集群的naming(命名服务),确保命名的唯一性。

8.创建节点时,需要指定初始数据,否则不能创建节点。

9.Zookeeper是事务的概念,针对每个事务(写操作,比如创建节点,更新节点,删除节点),zk都会分配一个递增的Zxid(事务id)。其中:cZxid=》创建节点的事务id    mZxid=》修改的事务id  pZxid=》指定节点下最近的一次事务id。

10.zookeeper的节点类型一种4种:

①create /park01   普通持久节点

②create -e /park01 普通临时节点

③create -s /park01  顺序持久 节点

④create -e -s /park01 临时顺序节点

以上四种节点,重点记住 临时节点。因为zk主要根据临时节点的状态,去监听对应客户端的状态。因为临时节点消失,意味着创建此节点的客户端掉线。后期很多大数据框架的检测,都是基于此机制来实现的。

 

 

Zookeeper服务端指令

指令

说明

sh zkServer.sh start

启动zk服务的

sh zkServer.sh stop

停止zk服务

sh zkServer.sh restart

重启zk服务

sh zkServer.sh status

查看zk服务角色,有:
Standalone
Leader
Follower

Observer

sh zkCli.sh

进入zk客户端

 

Zookeeper客户端指令

指令

说明

示例

ls

查看

ls  /  查看根路径
ls /park01 查看park01路径

create

创建

create /park02 ""
create /park02/node01  创建park02的子节点

get

获取指定节点信息

cZxid = 0x2   #创建此节点的事务id

ctime = Wed Jan 17 10:55:25 PST 2018 #创建此节点的时间戳

mZxid = 0x2 #修改此节点的事务id

mtime = Wed Jan 17 10:55:25 PST 2018 #修改此节点的时间戳

pZxid = 0x4

cversion = 1

dataVersion = 0

aclVersion = 0

ephemeralOwner = 0x0 #如果此节点不是临时节点,则为0

dataLength = 9 #数据长度

numChildren = 1 #子节点数量

set

更新节点数据

set  /park01 hellozk

delete

删除子节点为空的节点

delete /park01

rmr

递归删除指定节点

rmr  /park02

quit

(或ctrl+c)

退出客户端

 

 

create -e 

创建临时节点,当创建此节点的客户端下线时,节点被删除。

 

create -s

创建顺序节点,每次创建节点时,会跟上一个递增的顺序号

 

create -e -s

创建临时顺序节点

 

 

 

三: zookeeperAPI操作

2016820

21:19

同步方式

一、

连接zookeeper和创建节点数据代码:

public class ZkDemo {

 

public static voidmain(String[] args) throws Exception {

final CountDownLatch cdl=new CountDownLatch(1);

//第一个参数,连接的zookeeper节点ip,

//第二个参数,会话超时时间,以毫秒为单位。比如设置1000*30 30秒。如果30秒内zookeeper没有收到客户端节点的心跳,则断开连接

//第三个参数,Watcher,观察者,zookeeper里有事件发生时,会通知到这个process方法里

//需要注意,连接是异步的,当连接成功是,会回调process方法,我们需要做相应的处理

//此外,连接一个zookeeper连接地址也可以,因为zookeep会将数据同步至其他的zookeerper节点

ZooKeeper zk=newZooKeeper("192.168.234.137:2181",30000,new Watcher(){

 

@Override

public voidprocess(WatchedEvent event) {

if(event.getState()==KeeperState.SyncConnected){

//说明连接成功了

cdl.countDown();

}

 

}

 

});

//之所以用递减锁,因为:连接是非阻塞的,到底连接成功没,不知道。所以,用递减锁,把这个连接变成了阻塞式连接,当成功连接后,才走

//await()之后的代码

cdl.await();

//创建节点

//1.path 节点路径;2.data[]节点数据;3.acl 权限策略,一般设为所用用户都可以操作这个节点,并且具有所有权限,所以选Ids.OPEN_ACL_UNSAFE

//4.createMode创建模式:

//PERSISTENT持久

//PERSISTENT_SEQUENTITAL持久顺序

//EPHEMERAL 临时

//EPHEMERAL_SEQUENTITAL临时顺序

zk.create("/node","hello1604Zookeeper".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);

 

//也可以通过StringCallBack()回调函数来拿到创建后的节点名。rc 是返回码。0代表节点创建成功。-110代表此节点已存在,节点创建失败。

//ctx 可以是任意一个对象,这个对象也可以回调函数里接收

//需要注意的是,如果是用这种方式来创建节点,是非阻塞的

zk.create("/02","helloZK".getBytes(),Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT,new StringCallback() {

 

public voidprocessResult(int rc, String path, Object ctx, String name) {

System.out.println(rc+":"+path+":"+ctx+":"+name);

}

}, 1);

 

}

 

 

 

}

更新节点数据:

@Test

public void testSet()throws Exception{

final CountDownLatchcdl=new CountDownLatch(1);

ZooKeeper zk=newZooKeeper("192.168.234.137:2181",30000,new Watcher(){

 

@Override

public voidprocess(WatchedEvent event) {

if(event.getState()==KeeperState.SyncConnected){

cdl.countDown();

}

 

}

 

});

cdl.await();

//version版本号的作用:在指定路径下,有一个dataVersion,这个是数据更改的版本号,从0开始,在此节点下

//每更改一次数据,版本号递增1

//setData(,,version)version的意思是:指定一个版本号,基于这个版本号来修改,但是需要注意:

//如果指定的版本号是3,而当前的dataVersion4,即指定的版本号不存在(已过时),则会报错

//如果指定的版本号是-1,则说明无论当前dataVersion是多少,都会进行数据的更新,最常用的就是-1

zk.setData("/node","ccc".getBytes(), -1);

}

获取节点数据

@Test

public void testGetData()throws Exception{

final CountDownLatchcdl=new CountDownLatch(1);

ZooKeeper zk=newZooKeeper("192.168.234.137:2181",3000,new Watcher(){

 

@Override

public voidprocess(WatchedEvent event) {

cdl.countDown();

}

});

cdl.await();

//watch,当指定节点发生监听的事件时,会触发Watcher里的方法,

//监听的事件有:1.节点数据发生变化2.节点创建 3.节点删除 4.节点的子节点发生变化。但是监听的事件只会触发一次回调方法。

//stat,节点环境信息,一般设置为null即可。如果想要,可以传入一个空的Stat对象来接收

byte[]data=zk.getData("/node",new Watcher(){

 

@Override

public voidprocess(WatchedEvent event) {

if(event.getType()==EventType.NodeDataChanged){

System.out.println("节点数据发生变化");

}

 

}

 

},null);

System.out.println(newString(data));

//保持线程开启

 

//getACL,得到指定路径的权限信息,权限信息被封装在返回的集合里

//此外,也可以传入一个Stat对象,用来分装节点的环境信息,比如zxid,ctime等等

Stat s1=new Stat();

List<ACL>list=zk.getACL("/02",s1);

for(ACL a:list){

System.out.println(a);

}

System.out.println(s1);

 

while(true){}

}

获取子节点

@Test

public voidtestGetChildren() throws Exception{

//连接代码省略

List<String> list=zk.getChildren("/", null);

for(Strings:list)System.out.println(s);

}

 

删除节点

@Test

public void testDelete()throws Exception{

//连接代码略

zk.delete("/node",-1);

 

}

判断节点是否存在

@Test

public void testExists()throws Exception{

//如果节点不存在,stat返回值=null

//如果节点存在,stat返回节点的元数据

Statstat=zk.exists("/node02", null);

System.out.println(stat);

 

}

 

异步方式

异步创建节点

@Test

public voidtestCreateByAsynchronous() throws Exception{

zk.create("/node","helloworld".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT,

newStringCallback() {

 

public voidprocessResult(int rc, String path, Object ctx, String name) {

System.out.println("节点创建成功"+rc+":"+path+":"+ctx+":"+name);

 

}

},null);

 

}

 

利用监听,判断节点是否被删除或创建事件

代码:

zk.exists("/park02",new Watcher(){

 

@Override

public voidprocess(WatchedEvent event) {

if(event.getType()==EventType.NodeDeleted){

System.out.println("节点被删除");

}

if(event.getType()==EventType.NodeCreated){

System.out.println("节点被创建");

}

 

}

 

});

利用监听,判断子节点状态变化事件

代码:

zk.getChildren("/park01",newWatcher(){

 

@Override

public voidprocess(WatchedEvent event) {

if(event.getType()==EventType.NodeChildrenChanged){

System.out.println("子节点发生变化");

}

 

}

 

});

 

 

 EventType 状态的类

四: zookeeper集群安装配置

 

安装步骤:

提示:要关闭虚拟机的防火墙,执行:service iptables stop

1.准备虚拟机,安装并配置jdk,1.6以上

2.上传zookeeper的安装包 3.4.7版本

3.解压安装 tar -xvf …………

4.配置zookeeper。

5.配置伪集群模式

①切换到zookeeper安装目录的conf目录,其中有一个zoo_sample.cfg的配置文件,这个一个配置模板文件,我们需要复制这个文件,并重命名为 zoo.cfg。zoo.cfg才是真正的配置文件

 

 

②配置zoo.cfg=》vim  zoo.cfg 更改如下几个参数配置:

dataDir。这个参数是存放zookeeper集群环境配置信息的。这个参数默然是配置在 /tmp/zookeeper下的。但是注意,tmp是一个临时文件夹,这个是linux自带的一个目录,是linux本身用于存放临时文件用的目录。但是这个目录极有可能被清空,所以,重要的文件一定不要存在这个目录下。

所以改成:/home/work/zkdata

注意:这个路径是自定义的,所以目录需要手动创建

 

 

 

clientport。客户端连接服务器的端口,默认是2181,一般不用修改

 在配置文件里,需要在加上如下的配置:

server.1=192.168.234.10:2888:3888   

server.2=192.168.234.11:2888:3888

server.3=192.168.234.12:2888:3888

 

①server是关键字,写死

②后面的数字是选举id,在zk集群的选举过程中会用到。

补充:此数字不固定,但是需要注意选举id不能重复,相互之间要能比较大小

然后保存退出

③192.168.234.10:2888:3888   

说明:2888原子广播端口,3888选举端口

zookeeper有几个节点,就配置几个server,

 

 

③配置文件配置好,需要在dataDir目录下创建一个文件

即在:/home/work/zkdata 目录下,创建 myid

vim  myid

给当前的节点编号。zookeeper节点在启动时,就会到这个目录下去找myid文件,得知自己的编号

 

保存退出

6.配置伪集群环境的其他节点

scp-r  目录  远程ip地址:存放的路径

scp -r/home/software/zookeeper 192.168.234.151: /home/

①更改节点的ip

②更改myid的id号

③关闭防火墙 ,执行:service iptables stop;

7.启动zookeeper

进入到zookeeper安装目录的bin目录

执行:./zkServer.sh start

 

然后可以输入jps命令,查看有哪些java进程,

执行:jps

 

 

8.执行 :./zkServer.sh  status 查看当前zookeeper节点状态

结果发现报错,原因是现在是集群,但是之后一台节点启动,不能正常工作。

 

9.其他两台节点启动zookeeper服务

 

 

报错及解决办法:

 

配置说明:

tickTime: zookeeper中使用的基本时间单位, 毫秒值.

dataDir: 数据目录. 可以是任意目录.

dataLogDir: log目录, 同样可以是任意目录. 如果没有设置该参数, 将使用和dataDir相同的设置.

clientPort: 监听client连接的端口号

initLimit: zookeeper集群中的包含多台server, 其中一台为leader, 集群中其余的server为follower. initLimit参数配置初始化连接时, follower和leader之间的最长心跳时间. 此时该参数设置为5, 说明时间限制为5倍tickTime,即5*2000=10000ms=10s.

syncLimit: 该参数配置leader和follower之间发送消息, 请求和应答的最大时间长度. 此时该参数设置为2, 说明时间限制为2倍tickTime, 即4000ms.

 

 

 

 

Zookeeper选举机制

201866

17:11

概述

 

Zookeeper的选举机制:

分两个阶段。

阶段一:数据恢复阶段。每台zk启动时,会从dataDir目录找到最大事务id (Zxid)

阶段二:选举阶段。每台zk服务都会推荐自己当Leader,并且会提交选举协议,协议的内容:

①自己拥有的最大事务id

②自己的选举id

③逻辑时钟值。作用是确保每台zk在同一轮选举中

④当前的状态:

Looking(选举)

Follower

Leader

Observer(观察者)

 

pk原则:

①先比较最大事务id,谁大谁当Leader。因为事务id越大,事务越新。

②如果最大事务id比较不出来,就比较选举id,谁大谁当Leader。

但是注意:pk最基本的原则要满足过半性

 

补充:过半性是zookeeper是一大特点。有:①过半选举 ②过半存活

所以,一般搭建zk集群,都是奇数台服务器,比如11、25等。因为可以更好的满足过半性。

 


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值