开源的分布式的协调服务,是Google的Chubby一个开源的实现,它是一个为分布式应用提供一致性服务的软件
简单
丰富
高可靠
松耦合交互
资源库
leader(领导者)
learner (学习者)
包括跟随者(follower)和观察者(observer),follower用于接
受客户端请求并向客户端返回结果,在选举过程中参与投票。Observer可以接受客户端连接,
将写请求转发给leader,但observer不参与投票过程,只同步leader的状态,observe r的
目的是为了扩展系统,提高读取速度
客户端(client)
zookeeper中的节点包含下面两个类型的节点
znode的类型在创建时确定并且之后不能再修改
znode默认不指定类型是持久节点
ephemeral类型的节点
persistent节点不依赖与客户端会话,只有当客户端明确要删除该persistent节点时才会被删除
ZooKeeper的客户端和服务器通信采用长连接方式 ,每个客户端和服务器通过心跳来保持连接,这个连接状态称之为session ,如果znode是临时节点,这个seesion失效,znode也就删除了
服务器的ID
数据的ID
编辑时钟
选举状态
选举信息的内容
在投票完成后,需要将投票信息发送给集群中的所有服务器,它包含如下内容。
选举机制的结果
安装zookeeper集群要求大于1的奇数台机器
zookeeper-3.4.6.tar.gz
tar -zxvf zookeeper-3.4.6.tar.gz -C /opt/
mv zookeeper-3.4.6/ zookeeper
vim /etc/profile
export ZOOKEEPER_HOME=/opt/zookeeper
export PATH=$PATH:$ZOOKEEPER_HOME/bin
scp /etc/profile mini02:/etc/
scp /etc/profile mini03:/etc/
scp /etc/profile mini04:/etc/
scp /etc/profile mini05:/etc/
source /etc/profile
cp zoo_sample.cfg zoo.cfg
mkdir data
vim conf/zoo.cfg
dataDir=/opt/zookeeper/data
scp -r /opt/zookeeper/ mini03:/opt/
在zookeeper的各个机器中分别创建myid文件(/opt/zookeeper/data ),内容分别为1 2 3
vim myid
或者
echo 1 > myid
server.1=mini03:2888:3888
server.2=mini04:2888:3888
server.3=mini05:2888:3888
scp zoo.cfg mini04:/opt/zookeeper/conf/
scp zoo.cfg mini05:/opt/zookeeper/conf/
保证zookeeper 集群中的时间不能有超过20秒的误差
ntpdate -u ntp.api.bz 根据时间同步服务器同步时间,-u是绕过防火请
zkServer.sh start
zkCli.sh -server mini05:2181 :进入
create znodename data :创建znode
get znodename :查看znode
set znodename data : 修改znode的数据
rmr znodename : 删除znode节点
quit :退出会话
delete : 删除节点
setquota -b 长度配额 :设置节点长度配额
setquota -n 数量配额 :设置节点数量配额
listquoat path : 列出配额
delquota path :删除配额
create -e znode :创建临时节点
package com.mini.bigdata.zookeeper;
import org.apache.zookeeper.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class ZookeeperTest {
private ZooKeeper zooKeeper;
@Before
public void init() throws Exception {
String connStr = "mini03:2181,mini04:2181,mini05:2181";
zooKeeper = new ZooKeeper(connStr, 3000, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println("watch..." + watchedEvent.getType());
}
});
}
/**
* 创建节点
*/
@Test
public void testCreateZNode() throws Exception {
String path = "/test01";
zooKeeper.exists(path, true);
String ret = zooKeeper.create(path, "HELLO2".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println(ret);
}
@Test
public void testSetZnode() throws KeeperException, InterruptedException {
zooKeeper.setData("/test02", "mini02".getBytes(), 1);
}
@Test
public void testGetZnode() throws KeeperException, InterruptedException {
byte[] data = zooKeeper.getData("/test02", true, null);
System.out.println(new String(data, 0, data.length));
}
@Test
public void testDeleteZnode() throws KeeperException, InterruptedException {
zooKeeper.delete("/test02", -1);
}
@After
public void destory() throws Exception {
zooKeeper.close();
}
}
实现注册监听的方法
事件的类型
名称 | 描述 |
---|---|
Recipes | Zookeeper典型应用场景的实现,这些实现是基于Curator Framework。 |
Framework | Zookeeper API的高层封装,大大简化Zookeeper客户端编程,添加了例如Zookeeper连接管理、重试机制等。 |
Utilities | 为Zookeeper提供的各种实用程序。 |
Client | Zookeeper client的封装,用于取代原生的Zookeeper客户端(ZooKeeper类),提供一些非常有用的客户端特性。 |
Errors | Curator如何处理错误,连接问题,可恢复的例外等。 |
<dependency>
<groupId>org.apache.curatorgroupId>
<artifactId>curator-recipesartifactId>
<version>2.12.0version>
dependency>
package com.mini.bigdata.zookeeper;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.RetryForever;
import org.junit.Before;
import org.junit.Test;
public class CuratorTest {
public String connStr = "mini03:2181,mini04:2181,mini05:2181";
private CuratorFramework zkClient;
@Before
public void init() {
zkClient = CuratorFrameworkFactory.newClient(connStr, new RetryForever(6000));
zkClient.start();
}
/**
* 创建空节点(其实不是空节点,是给节点默认设置了ip地址)
*
* @throws Exception
*/
@Test
public void createZnode() throws Exception {
zkClient.create().forPath("/test03");
}
@Test
public void createZnode1() throws Exception {
zkClient.create().forPath("/test02", "h".getBytes());
}
@Test
public void deleteZnode() throws Exception {
zkClient.delete().deletingChildrenIfNeeded().forPath("/test02");
}
@Test
public void setZnode() throws Exception {
zkClient.setData().forPath("/test03");
}
@Test
public void getZnode() throws Exception {
byte[] bytes = zkClient.getData().forPath("/test03");
System.out.println(new String(bytes, 0, bytes.length));
}
}
String conn = "mini03:2181,mini05:2181,mini04:2181";
RetryNTimes retryNTimes = new RetryNTimes(3,3000);
//建立链接
CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient(conn, retryNTimes);
curatorFramework.start();
//创建监听器
NodeCache nodeCache = new NodeCache(curatorFramework, "/tes01");
//启动监听器
nodeCache.start();
nodeCache.getListenable().addListener(new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
if (nodeCache.getCurrentData() == null) {
System.out.println("删除了节点...."+path);
} else {
System.out.println("节点改变.." + "路径为:" + nodeCache.getCurrentData().getPath() + "数据为:" + new String(nodeCache.getCurrentData().getData()));
}
}
});
Thread.sleep(Integer.MAX_VALUE);
curatorFramework.close();
String connStr = "mini03:2181,mini04:2181,mini05:2181";
RetryPolicy retryPolicy = new RetryNTimes(3, 3000);
CuratorFramework zkClient = CuratorFrameworkFactory.newClient(connStr, retryPolicy);
zkClient.start();
String path = "/test01";
//创建监听监听器
PathChildrenCache pathChildrenCache = new PathChildrenCache(zkClient, path, true);
pathChildrenCache.start();
pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
System.out.println("一级子节点改变.."+event.getData()+ event.getType());
}
});
Thread.sleep(Integer.MAX_VALUE);
zkClient.close();