zookeeper
1. zookeeper是什么?
zookeeper是一个用于开发分布式系统时,进行分布式协调问题处理的基础中间件;
它所提供的功能主要有3个:
1)可以为客户端提供注册信息的功能
2)可以为客户端提供查询信息的功能
3)可以为客户端提供数据监听并通知的功能
2. zookeeper是如何工作的?
2.1 数据存储形式
zookeeper通过key-value形式(存在内存中,也会持久化到磁盘)为客户端记录信息;
key是类似路径的形式:
/servers
/servers/server01
/servers/server02
用了路径的形式后,key之间就有了父子关系!
value 可以是任何数据(byte[])
完整的数据形式:
/servers “abc”.getBytes()
/servers/server01 “ccc”.getBytes()
2.1 安全可用性
zookeeper不是一个单机系统,而是一个分布式系统;
它会用多台(5)机器,帮客户端存储数据的多个副本;
一旦一份数据被存储到多台机器,就涉及到一个数据一致性问题!!!zookeeper是通过一个分布式数据一致性算法paxos来实现的。
集群中必须有半数以上节点存活,才能提供正常对外服务!
数据同步机制:
集群中会有一个节点状态为leader
其他节点为follower;
客户端交过来的数据,首先由leader更新自身,然后再同步给其他follower
zookeeper集群中的leader不是配置文件配死的,而是在运行过程中,集群各个节点共同选举出来的;
选举机制:(两种情况)
每个节点的机器上都存有一个id(由用户配置的)
node1 myid=>1
node2 myid=>2
node3 myid=>3
启动时:(假设集群有3个节点)
1.启动node1
node1一启动,就会在局域网中寻找leader,找到不到,则进入选举模式,开始投票(1)
投来投去,它都只收到自己投给自己的票(1),仅得1票,不能当选(多数票才能当选)
2.启动node2
node2一启动,也会寻找leader,找不到,打开一个端口开始投票,立马收到一票(1),一比对自己的myid(2),发现1<2,它决定投(2)
此时,node1会收到node2的投票(2),node1发现2比自己大,转而投(2)
此时,node2得2票,已过半数,成功当选leader,打开leader端口
此时,node1发现已经有leader了,自动切换为follower状态;
3.启动node3
node3一启动,寻找leader,发现有响应,则自动切换为follower状态
运行过程中,如果leader宕机,选择过程:
大家投票,投票优先考虑:各节点上存储的数据版本号;再考虑myid的大小
3. 安装zookeeper
集群节点数最好为奇数
本案例使用3台节点
步骤:上传安装包;解压;改配置
修改配置:
mv zoo_sample.cfg zoo.cfg
[root@cts01conf]# vi zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/root/zkdata/
clientPort=2181
server.1=cts01:2888:3888
server.2=cts02:2888:3888
server.3=cts03:2888:3888
接下来,到每台节点的zk数据目录中生成一个myid文件,存储的内容就是这个节点的id值
cts01:
mkdir /root/zkdata
echo 1 > /root/zkdata/myid
cts02:
mkdir /root/zkdata
echo 2 > /root/zkdata/myid
cts03:
mkdir /root/zkdata
echo 3 > /root/zkdata/myid
接下来,就可以启动zookeeper服务了:
在每一台节点上,输入命令:
bin/zkServer.shstart
查看zk进程服务状态:
bin/zkServer.shstatus
4. zookeeper的使用
4.1 命令客户端
启动: bin/zkCli.sh
提交一个key-value让zookeeper保存:
create /key1 hello
若想创建深一层的节点必须先创建一个节点再次创建才可以
查看zookeeper中有哪些key:
ls /
获取一个key的value内容:
get /key1
修改一个key的value内容:
set /key1 byebye
删除一个key
rmr /key1
监听:
get /a watch 监听/a节点的数据变化事件
ls / watch 监听/a节点的子节点变化事件
而且,客户端注册一次监听,zk服务只会向这个客户端通知一次!!!
4.1 JAVA-API客户端
// 1.地址 2.会话超时时间 3.收到事件通知后要做的事(方法)
ZooKeeper zk = new ZooKeeper("tyler01:2181,tyler02:2181,tyler03:2181",2000,null);
zk.create("/aa", "zhangmeng".getBytes(),Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);//持久的带序号的
zk.close();
//1 删除的文件 2参数要删除的版本(-1 所有版本)
zk.delete("/aa0000000002",-1);
zk.close();
List<String>children = zk.getChildren("/servers", true);//这是获取所有的节点
zk.getData("/servers/" + s, true, null);//这是得到节点的value值