zookeeper概述:为其他分布式应用程序提供协调的服务。
zookeeper架构:
架构分析:
①一个zk集群中由一组Server节点构成 (ps:数目一般选择奇数 3,5,7...)
②一组Server节点中存在一个角色Leader的节点,剩下的其他节点都是Follower
③当客户端Client连接到zk集群时,并执行读写请求,这些请求会被发送到Leader节点上
④然后,Leader节点上的数据变更会同步到集群的其他的Follower节点
⑤Leader节点接受到数据变更请求之后,首先会将变更写入到磁盘(ps:为以后的容错、恢复等所有)
当所有的写请求持久化到磁盘之后,才会将变更应用到内存中(即:通知所有机子进行写)
⑥如果当前的Leader发生故障无法提供服务之后,就会从Follower中选择一个节点作为新的Leader,而新的Leader将 继续为其他分布式应用程序提供协调的服务。
Leader选举算法:
采用Paxos协议,即:当多数server写成功,则任务数据写成功
其中多数server是指:只有集群中有过半的集群是正常工作的,则整个集群对外可用。
死亡容忍度:
2n个和2n-1个节点的死亡容忍度是一样的,即:n-1
zk死亡容忍度:就是指不能死掉一半
server个数为偶数:除以2减1就是zk的死亡容忍度
server个数为奇数:除以2取商,就是zk的死亡容忍度
zookeeper的两种类型:
①短暂的(ephemeral)
客户端会话结束,那么zk就会将该类型的node删除。(ps:此类型的node不可以有子节点)
②持久的(persistent)
只有当客户端明确使用命令或API的方式删除节点时,此节点才会被删除,否则,即使客户端断开,节点依然存在
zookeeper监控机制:
"/path" | "/path/child" | |||||
exists | getData | getChildren | exists | getData | getChildren | |
create("/path") | √ | √ | ||||
delete("/path") | √ | √ | √ | |||
setData("/path") | √ | √ | ||||
create("/path/child") | √ | √ | √ | |||
delete("/path/child") | √ | √ | √ | √ | ||
setData("/path/child") | √ | √ |
Java API 操作zk:
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
/**
* Created by Selen on 2017/7/25.
* 使用Java API 操作ZK
*/
public class TestZKApp {
private static final int SESSION_OUT=30000;
private ZooKeeper zooKeeper;
private Watcher watcher=new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("process:"+event.getType());;
}
};
@Before
public void setUp() throws IOException {
zooKeeper=new ZooKeeper("hadoop-node3:2181",SESSION_OUT,watcher);
}
//创建节点
@Test
public void createNode() throws KeeperException, InterruptedException {
zooKeeper.create("/node4","test4".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
//获得节点数据
@Test
public void getNodeData() throws KeeperException, InterruptedException {
byte[]data=zooKeeper.getData("/node3",null,null);
System.out.println(new String(data));
}
//设置或修改数据
@Test
public void setNodeData() throws KeeperException, InterruptedException {
zooKeeper.setData("/node2","test2".getBytes(),-1);
}
//判断节点是否存在
@Test
public void exists() throws KeeperException, InterruptedException {
Stat stat=zooKeeper.exists("/node2",null);
System.out.println(stat.getCzxid());
}
//删除节点
@Test
public void delete() throws KeeperException, InterruptedException {
zooKeeper.delete("/node2",-1);
}
@After
public void down() throws InterruptedException {
zooKeeper.close();
}
}