写在前面:学习任何一个框架首先就是要知道这个框架是拿来干什么用的,第二就是要了解这个框架的核心工作机制是什么,第三个要知道其内部的组成,角色。
1.zookeeper
Zookeeper是一个分布式协调服务;就是为用户的分布式应用程序提供协调服务
- zookeeper是为别的分布式程序服务的
- Zookeeper本身就是一个分布式程序,作为第三方他必须保证自己就是高可用的(只要有半数以上节点存活,zk就能正常服务,zookeeper适合装在奇数台机器上!!!)
- Zookeeper所提供的服务涵盖:主从协调、服务器节点动态上下线、统一配置管理、分布式共享锁、统一名称服务……
- 虽然说可以提供各种服务,但是zookeeper在底层其实只提供了两个功能:
zookeeper作为第三方最重要的两个功能:1.管理(存储,读取)用户程序提交的数据,比如说集群的公共配置文件;2.并为用户程序提供数据节点监听服务,比如说集群的哪个节点挂掉了,就采用选举机制让其他的节点顶上去。
2.zookeeper的选举机制
采用paxos算法的简化版zab协议来投票,
首先三台zookeeper都有配置文件,和id,当第一台起来的时候,他会投票,投给自己,但是他不会是leader,因为配置文件中配了三台机器,第一台机器没有获得半数以上的票,所以他是follower,
接着第二台zookeeper其起来了,此时第一台机器会投给自己,第二台机器也会投给自己,所以第一台和第二台机器都会收到两票,一票投给1,一票投给2,这样投给1和2的票数是一样的,所以还是无法选出leader,所以他们会继续投票,此时就会有一个规则,投给id大的机器,所以1会投给2,2也会投给2,所以现在2收到两票给2,1也收到两票给2,所以2是leader.
3启动以后发现已经有leader了,就自觉成为follower.
3.zookeeper集群搭建安装zookeeper
如果我们启动一台机器,整个集群是不会工作的,因为没有半数以上的机器存活
4.命令行客户端的使用
那么如果要拿到zookeeper里面的数据,就要了解zookeeper的数据的组织结构
zookeeper数据结构:
1、层次化的目录结构,命名符合常规文件系统规范(见下图)
2、每个节点在zookeeper中叫做znode,并且其有一个唯一的路径标识
3、节点Znode可以包含数据和子节点(但是EPHEMERAL类型的节点不能有子节点,下一页详细讲解)
4、客户端应用可以在节点上设置监视器(后续详细讲解)
查看有哪些命令:
可以直接通过命令来创建zookeeper节点,这个节点不仅仅是个文件路径,还可以存放信息
节点类型:
1、Znode有两种类型:
短暂(ephemeral)(断开连接自己删除)
持久(persistent)(断开连接不删除)
2、Znode有四种形式的目录节点(默认是persistent )
PERSISTENT
PERSISTENT_SEQUENTIAL(持久带序列/test0000000019 )
EPHEMERAL
EPHEMERAL_SEQUENTIAL(短暂带序列/test0000000019)
3、创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护
4、在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序
创建短暂的节点:
然后退出客户端,在连接上,短暂的节点没了:
在第一台机器上建好的节点,在第二台机器上也可以看到,而且在第一台机器上修改了数据,会很快地同步到其他的机器上,但是有几十台机器的时候就有明显的延时了:
第二个功能监听:
在机器一上监听这个节点
机器二上修改这个节点的值
机器一会监听到变化:
5.zookeeper的java客户端api:
public class SimpleDemo {
// 会话超时时间,设置为与系统默认时间一致
private static final int SESSION_TIMEOUT = 30000;
// 创建 ZooKeeper 实例
ZooKeeper zk;
// 创建 Watcher 实例
Watcher wh = new Watcher() {
public void process(org.apache.zookeeper.WatchedEvent event)
{
System.out.println(event.toString());
}
};
// 初始化 ZooKeeper 实例
private void createZKInstance() throws IOException
{
zk = new ZooKeeper("weekend01:2181", SimpleDemo.SESSION_TIMEOUT, this.wh);
}
private void ZKOperations() throws IOException, InterruptedException, KeeperException
{
System.out.println("/n1. 创建 ZooKeeper 节点 (znode : zoo2, 数据: myData2 ,权限: OPEN_ACL_UNSAFE ,节点类型: Persistent");
zk.create("/zoo2", "myData2".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("/n2. 查看是否创建成功: ");
System.out.println(new String(zk.getData("/zoo2", false, null)));
System.out.println("/n3. 修改节点数据 ");
zk.setData("/zoo2", "shenlan211314".getBytes(), -1);
System.out.println("/n4. 查看是否修改成功: ");
System.out.println(new String(zk.getData("/zoo2", false, null)));
System.out.println("/n5. 删除节点 ");
zk.delete("/zoo2", -1);
System.out.println("/n6. 查看节点是否被删除: ");
System.out.println(" 节点状态: [" + zk.exists("/zoo2", false) + "]");
}
private void ZKClose() throws InterruptedException
{
zk.close();
}
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
SimpleDemo dm = new SimpleDemo();
dm.createZKInstance();
dm.ZKOperations();
dm.ZKClose();
}
}
那么他有哪些应用的案例呢?分布式应用系统服务器上下线动态感知,逻辑图如下:
第二个应用,分布式共享锁的实现逻辑: