首先说一下什么是zookeeper
(1)zookeeper是一个用于降低分布式系统开发过程中节点间协调问题开发难度的工具!
(2)zookeeper提供的功能有:
提供数据注册功能;
提供数据查询功能;
提供数据监听功能
zookeeper怎么用?
安装:
机器:奇数台(1,3,5,7,…….):一个leader,众多follower
为什么要奇数台?
zookeeper这个分布式系统没有固定的主节点(leader),它的主节点是通过集群各节点动态选举出来的。
选举的规则:谁得多数票,谁就当选为leader
v 初次启动的投票过程(假设集群为3台,每台节点都在配置文中配了自己的id):
集群中n1启动,它会在网络中寻找leader,没有leader,则开始向网络中广播投票(第一次投自己)
集群中n2启动,它会在网络中寻找leader,没有leader,但是收到了n1的票,n2也投票(由于n2的id>n1的id,n2就投自己); n1会收到n2的票后,得知n2的存在以及n2的id,则n1重新投票(投n2);
此时,n2得2票,过半数,则当选为leader,n2将自己的工作状态切换为Leader;n1则将自己的状态从投票状态切换为follower;
启动中n3启动,它会在网络中寻找leader,发现n2是leader,自己主动进入follower状态;
v 运行过程中leader宕机,其他机器发现leader不在,进入投票选举状态;
投票规则:投数据版本最新的节点为leader;如果大家的数据版本一样,则投id大的为leader;
安装步骤
1.先解压到指定目录
tar -zxvf zookeper……. -C /usr/local
2.添加一个zoo.cfg配置文件,复制根目录下的zoo_sample.cfg文件
# $ZOOKEEPER是安装zookeeper的根目录
cd $ZOOKEEPER/conf
mv zoo_sample.cfg zoo.cfg
3.修改配置文件
里面有一个dataDir
并且在后面添加一些内容:
#在其根目录下创建一个data目录,dataDir的路径就是data的路径
dataDir=/usr/local/zookeeper-3.4.6/data
#配置形式 server.*=ip01:2888:3888 第一个*为数字,可以自己起,但不要重复,ip01是节点ip,后面是两个端口,不要改变
server.1=hadoop01:2888:3888
server.2=hadoop02:2888:3888
server.3=hadoop03:2888:3888
4.在(dataDir=/bigdata/zookeeper-3.4.5/data)创建一个myid文件,里面内容是server.N中的N(server.2里面内容为2)*
echo "2" > myid //可以使用下面命令往里面写
5.将配置好的zk拷贝到其他集群上
注意改成自己的路径 例如可以是 scp -r /usr/local/zookeeper hadoop01:/usr/local/
6.注意:在其他节点上一定要修改myid的内容*
7.启动集群(一定要启动百分之五十以上,要不然起不来)
/bin/Server.sh start
8.查看启动状态,出现leader就对了
/bin/zkServer.sh status
链接:https://pan.baidu.com/s/1UI6Zd0ftpB0n_MbM4c_eJA 密码:fyom
常用操作-------------Shell端的操作
启动zookeeper集群后 输入help
1、使用 ls 命令来查看当前 ZooKeeper 中所包含的内容:
[zk: 202.115.36.251:2181(CONNECTED) 1] ls /
2、创建一个新的 znode ,使用 create /zk myData 。这个命令创建了一个新的 znode 节点“ zk ”以及与它关联的字符串:
[zk: 202.115.36.251:2181(CONNECTED) 2] create /zk "myData“
3、我们运行 get 命令来确认 znode 是否包含我们所创建的字符串:
[zk: 202.115.36.251:2181(CONNECTED) 3] get /zk
监听这个节点的变化,当另外一个客户端改变/zk时,它会打出下面的
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/zk
[zk: localhost:2181(CONNECTED) 4] get /zk watch
4、下面我们通过 set 命令来对 zk 所关联的字符串进行设置:
[zk: 202.115.36.251:2181(CONNECTED) 4] set /zk "zsl“
5、下面我们将刚才创建的 znode 删除:
[zk: 202.115.36.251:2181(CONNECTED) 5] delete /zk
6、删除节点:rmr
[zk: 202.115.36.251:2181(CONNECTED) 5] rmr /zk
常用操作--------------java客户端api的使用
public class ZKCURD {
//zookeeper地址
private static final String connectString = "hadoop01:2181,hadoop02:2181,hadoop03:2181";
private int sessionTimeout = 2000;
ZooKeeper zkClient = null;
/**
* 初始化资源
* @throws Exception
*/
@Before
public void init() throws Exception{
zkClient= new ZooKeeper(connectString, sessionTimeout, new Watcher() {
public void process(WatchedEvent event) {
System.out.println(event.getType() +" "+ event.getPath());
try {
zkClient.getChildren("/", true);//递归实现监听
} catch (KeeperException | InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
/**
* 数据的增加
* @throws Exception
*/
@Test
public void testCreate() throws Exception{
// 1:路径 2:数据 3:权限 4:节点的类型 临时的和持久的 (EPHEMERAL PERSISTENT PERSISTENT_SEQUENTIAL EPHEMERAL_SEQUENTIAL)
zkClient.create("/eclipse/e", "eclipse".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
//Thread.sleep(15000);
}
/**
* 获取子节点
* @throws Exception
*/
@Test
public void getChildren() throws Exception{
List<String> children = zkClient.getChildren("/", false);
for (String string : children) {
System.out.println(string);
}
}
/**
* 判断节点是否存在
* @throws Exception
*/
@Test
public void testExist() throws Exception{
Stat exists = zkClient.exists("/eclipse", false);
System.out.println(exists);
}
/**
* 获取节点数据
* @throws KeeperException
* @throws InterruptedException
*/
@Test
public void testGetData() throws KeeperException, InterruptedException{
byte[] data = zkClient.getData("/eclipse", false, null);
System.out.println(new String(data));
}
/**
* 删除节点
* @throws InterruptedException
* @throws KeeperException
*/
@Test
public void deleteData() throws InterruptedException, KeeperException{
zkClient.delete("/w", -1);
}
/**
* 修改数据
* @throws KeeperException
* @throws InterruptedException
*/
@Test
public void setData() throws KeeperException, InterruptedException{
zkClient.setData("/w", "hello".getBytes(), -1);
}
/**
* 监听
* @throws Exception
*/
@Test
public void watch() throws Exception{
List<String> children = zkClient.getChildren("/", true);
for (String string : children) {
System.out.println(string);
}
Thread.sleep(2*60*1000);
}
/**
* 释放资源
* @throws Exception
*/
@After
public void close() throws Exception{
zkClient.close();
}
}