Zookeeper
一、Zookeeper 简介
1.发展史
1.传统单机
当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。
此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。
适用于小型网站,小型管理系统,将所有功能都部署到一个功能里,简单易用。
缺点:
- 性能扩展比较难
- 协同开发问题
- 不利于升级维护
2.垂直应用架构
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。
此时,用于加速前端页面开发的Web框架(MVC)是关键。
通过切分业务来实现各个模块独立部署,降低了维护和部署的难度,团队各司其职更易管理,性能扩展也更方便,更有针对性。
缺点: 公用模块无法重复利用,开发性的浪费
3.RPC
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键
4.SOA
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)[ Service Oriented Architecture]是关键。
由于业务的进展,最终到达了我们的微服务。
当然,这只是发展史,我们并不是要学习整个微服务架构,而是学习一个分布式协调技术-ZooKeeper。
2.Zookeeper 是什么
ZooKeeper很有意思,顾名思意:动物园管理员
注:图片的大数据相关技术有兴趣可自行了解,对本章影响不大,故不做解释。
它是拿来管大象(Hadoop)、蜜蜂(Hive)、小猪(Pig)的管理员, Apache Hbase和Apache Solr以及阿里的Dubbo等项目中都采用到了Zookeeper。
一句话:ZooKeeper是一个分布式协调技术、高性能的,开源的分布式系统的协调(Coordination)服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用程序一致性和分布式协调技术服务的软件。
zookeeper是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper就将负责通知已经在Zookeeper上注册的那些观察者做出相应的反应,从而实现集群中类似Master/Slave管理模式。
就像是老师,学生有什么事,就找老师。
打个比方
一个班级有50个学生,每个学生就是一个服务,服务之间要相互调用,比如张三要和李四调换座位,这就是一个服务调用另一个服务,但是张三需要和老师申请是否可以调换座位,他们换座位是不是要找老师,服务注册和治理及调度协调通知机制。一句话,老师就是zookeeper。
我们在打个比方
比如一个公司,有人想访问这个公司的研发部,那他就需要先去前台,前台联系研发部,研发部选择是否接见这个人。
前提就是,研发部等各个部门都需要注册进前台,前台负责协调管理他们。就类似与spring cloud 的ureka;
那zookeeper是什么我知道了,那他有没有一条类似于公式的使用方式呢?
zookeeper=类似unix文件系统+通知机制+Znode节点
作用:服务注册+分布式系统之间的一致性通知协调服务
有公式看不懂?没事,我们就是混个眼熟。
统一命名服务(Name Service如Dubbo服务注册中心)
Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,是阿里巴巴SOA服务化治理方案的核心框架,每天为2,000+个服务提供3,000,000,000+次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。
在Dubbo实现中:
服务提供者在启动的时候,向ZK上的指定节点/dubbo/${serviceName}/providers目录下写入自己的URL地址,
这个操作就完成了服务的发布。
节点角色说明:
Provider: 暴露服务的服务提供方。
Consumer: 调用远程服务的服务消费方。
Registry: 服务注册与发现的注册中心。
Monitor: 统计服务的调用次调和调用时间的监控中心。
Container: 服务运行容器。
调用关系说明:
0 服务容器负责启动,加载,运行服务提供者。
1 服务提供者在启动时,向注册中心注册自己提供的服务。
2 服务消费者在启动时,向注册中心订阅自己所需的服务。
3 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
配置管理(Configuration Management 如淘宝开源配置管理框架Diamond)
在大型的分布式系统中,为了服务海量的请求,同一个应用常常需要多个实例。如果存在配置更新的需求,常常需要逐台更新,给运维增加了很大的负担同时带来一定的风险(配置会存在不一致的窗口期,或者个别节点忘记更新)。
zookeeper可以用来做集中的配置管理,存储在zookeeper集群中的配置,如果发生变更会主动推送到连接配置中心的应用节点,实现一处更新处处更新的效果。
现在把这些配置全部放到zookeeper上去,保存在 Zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中就好。
小总结:
Zookeeper一个最常用的使用场景就是用于担任服务生产者和服务消费者的注册中心,服务生产者将自己提供的服务注册到Zookeeper中心,服务的消费者在进行服务调用的时候先到Zookeeper中查找服务,获取到服务生产者的详细信息之后,再去调用服务生产者的内容与数据,简单示例图如下:
3. Zookeeper去哪下
-
官网首页:https://zookeeper.apache.org/
-
下载地址: http://zookeeper.apache.org/releases.html#download
-
本次使用版本:zk3.4.9
二、Zookeeper安装
注:没有linux基础请自学。
1.准备
- 本次安装平台采用 CentOS7
- JAVA8
- 官网下载安装包,本次版本Zookeeper-3.4.9.tar.gz
- 拷贝进入到/opt目录下并解压
- 拷贝解压后的zookeeper-3.4.9到/myzookeeper/下
准备完成如下图所示
2. 配置文件
进入到 conf 文件夹中,可以发现zoo_sample.cfg,一看就知道是配置文件,为了防止污染源文件,我们将zoo_sample.cfg拷贝到当前目录重命名为zoo.cfg。如图所示
那tomcat默认端口是8080,mysql默认端口是3306,redis默认端口是6379,那么zookeeper呢?先混个眼熟下面解答。
我们打开配置文件,在vi里依然先set nu 显示行号如下图所示
首先看到4个参数。
1.tickTime - 通信心跳数
Zookeeper服务器心跳时间,单位毫秒
Zookeeper使用的基本时间, 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳,时间单位为毫秒。
它用于心跳机制,并且设置最小的超时时间为两倍心跳时间.(session的最小超时时间是2*tickTime。),也即最小超时时间为两个心跳时间
2.initLimit
看不懂没事,后面说
多少个心跳时间内,允许其他server连接并初始化数据,如果ZooKeeper管理的数据较大,则应相应增大这个值
这个配置项是用来配置Zookeeper接收Follower客户端(这里所说的客户端不是用户链接Zookeeper服务器的客户端,而是Zookeeper服务器集群中连接到leader的Follower服务器,Follower在启动过程中,会从Leader同步所有最新数据,然后确定自己能够对外服务的起始状态。Leader允许Follower在 initLimit 时间内完成这个工作)初始化连接是最长能忍受多少个心跳的时间间隔数。
当已经超过10个心跳的时间(也就是tickTime)长度后Zookeeper服务器还没有收到客户端返回的信息,那么表明这个客户端连接失败。总的时间长度就是10*2000=20秒
3.syncLimit
看不懂没事,后面说
集群中Leader与Follower之间同步通信时限
集群中Leader与Follower之间的最大响应时间单位,多少个tickTime内允许follower同步,如果follower落后太多,则会被丢弃。
在运行过程中,Leader负责与ZK集群中所有机器进行通信,例如通过一些心跳检测机制,来检测机器的存活状态,
假如响应超过syncLimit * tickTime(假设syncLimit=5 ,请求和应答时间长度,最长不能超过多少个tickTime的时间长度,总的时间长度就是5*2000=10秒。),Leader认为Follwer死掉,从服务器列表中删除Follwer。
在运行过程中,Leader负责与ZK集群中所有机器进行通信,例如通过一些心跳检测机制,来检测机器的存活状态。
如果L发出心跳包在syncLimit之后,还没有从F那收到响应,那么就认为这个F已经不在线了。
4.dataDir
数据文件目录+数据持久化路径
保存内存数据库快照信息的位置,如果没有其他说明,更新的事务日志也保存到数据库。
比如,某个客户端需要注册到zookeeper中,那么就将这个客户端存到zookeeper中。
默认文件夹为,/tmp/zookeeper/
5.clientPort
客户端连接端口
监听客户端连接的端口。
默认为2181
配置文件读完了,我们启动zookeeper吧。
3. 启动Zookeeper
必须安装java
先查看后台是否启动了Zookeeper进程,然后到bin目录中。
我们可以发现,zookeeper没有启动(这不废话吗),bin目录中有.sh结尾的可执行文件,有.cmd结尾的可执行文件,.sh是linux用的,.cmd是windows用的。
我们将zookeeper启动
在启动客户端
看到welcome to zookeeper就代表客户端启动成功了。
在命令行输入quit退出
启动之后,我们看看是否启动成功,are you ok?
我们看到它回应im ok就代表启动成功了。
三、Zookeeper 使用
1.基本命令与操作
我们回顾下前面说的一条公式
zookeeper=类似unix文件系统+通知机制+Znode节点
unix文件系统,体现在哪里呢
我们知道unix文件系统采用的时树状结构,树状结构都有一个特点,那就是 / (根),在根上有枝(文件夹),那zookeeper类似unix文件系统是否也有这样的特性呢?
我们首先使用客户端连接上服务器
进入到客户端第一件事当然是打help了
我们发现了很多命令,其中有一些我们熟悉的,比如ls,create等。
我们知道,mysql中可以show databases 查看数据库,并且mysql中预装了一些数据库,那么zookeeper呢?
ls命令在linux中是查看的意思,那么在zookeeper中呢?
从上图可以看到,ls / ,这个命令故名思意,就是查询根有什么,发现有zookeeper,那么zookeeper下还有没有东西呢,我们在ls /zookeeper/,我们发现zookeeper下真的还有东西,是quota, 那quota呢?ls /zookeeper/quota/,发现[]空。根据树形结构,如图所示
嗯…
我们发现默认的确有节点,就像mysql默认装了数据库一样,那mysql可以新建数据库,那么zookeeper可不可以新建节点呢?
我们在help提示的语句看到了 create [-s] [-e] path data acl。
大学学习网络安全的时候了解了 ACL 是访问控制列表,在这个创建语句中应该可以缺省,我们也知道 [] 里的内容是可以缺省的,那么简化下就是,create path data。
create是创建
path在前面我们查询了,是一个节点,那节点里有什么内容呢?data
data就是节点中存储的内容,所以实际上这就是一个K-V键值对。
如图所示
果然,处理zookeeper以外,我们又创建了个mynode节点,那么树状图也要更新了。
聪明的小伙伴们是不是又想怎么get节点的data了呢?是不是又想怎么set节点的data了呢。
我们首先查看下节点内的数据长什么样吧!如图
get /zookeeper 这条数据是一个空行,我们可以理解为,zookeeper = null,
get /mynode 这条数据是lovecsdn,我们可以理解为,mynode = lovecsdn
那么除了存储的数据还有一大堆东西是什么呢,不要急,我们后面再说。
能get就可以set,如图所示
果然不出所料,我们发现zookeeper存储的是键值对,redis存储的也是键值对,那么redis是数据库,那么zookeeper是否可以当作数据使用呢?思考下,后面解释。
总结一下
zookeeper所使用的数据模型风格很像文件系统的目录树结构, 有名称,有树节点,有Key(键)/Value(值)对的关系,可以看做一个树形结构的数据库,分布在不同的机器上做名称管理。
前面说过了,ZooKeeper数据模型的结构与Unix文件系统很类似,整体上可以看作是一棵树,每个节点称做一个ZNode,很显然zookeeper集群自身维护了一套数据结构。这个存储结构是一个树形结构,其上的每一个节点,我们称之为"znode",每一个znode默认能够存储1MB的数据,每个ZNode都可以通过其路径唯一标识。
回顾上面的问题,可以不可做数据库呢?
答案是不可以,因为每个节点只能存储最多1MB的数据。。
2.Znode节点深入
Znode维护了一个stat结构,这个stat包含数据变化的版本号、访问控制列表变化、还有时间戳。版本号和时间戳一起,可让Zookeeper验证缓存和协调更新。每次znode的数据发生了变化,版本号就增加。
例如,无论何时客户端检索数据,它也一起检索数据的版本号。并且当客户端执行更新或删除时,客户端必须提供他正在改变的znode的版本号。如果它提供的版本号和真实的数据版本号不一致,更新将会失败。
这个stat结构就是我们get /mynode 得到的lovecsdn下面的一堆数据。
针对于这么多数据,官网的解释是这样的,如下图
有点不太易懂?别急
- czxid
引起这个znode创建的zxid,创建节点的事务的zxid (ZooKeeper Transaction ld)
每次修改ZooKeeper状态都会收到一个zxid形式的时间戳,也就是ZooKeeper事务ID。
事务ID是ZooKeeper中所有修改总的次序。每个修改都有唯一的zxid,如果zxid1小于zxid2,那么zxid1在zxid2之前发生。 - ctime
znode被创建的毫秒数(从1970年开始) - mzxid
znode最后更新的zxid - mtime
znode最后修改的毫秒数(从1970年开始) - pZxid
znode最后更新的子节点zxid - cversion
znode子节点变化号,znode子节点修改次数 - dataversion
数据变化号 - aclVersion
znode访问控制列表的变化号 - ephemeralOwner
如果是临时节点,这个是znode拥有者的session id。如果不是临时节点则是0。 - dataLength
znode的数据长度 - numChildren
znode子节点数量
这么多?没事,这些东西只需要了解,看懂就行
整理一下
zookeeper内部维护了一套类似UNIX的树形数据结构:由znode构成的集合,znode的集合又是一个树形结构,每一个znode又有很多属性进行描述。 Znode = path + data + Stat
我们继续深入Znode节点
znode是由客户端创建的,它和创建它的客户端的内在联系,决定了它的存在性
Znode节点也有分类,大致分两类,持久化节点、临时节点;细致分4类,普通永久持久化节点、持久化顺序编号节点、临时目录节点、临时顺序编号目录节点。
PERSISTENT-持久化目录节点
0-
PERSISTENT_ SEQUENTIAL-持久化顺序编号目录节点
3-
EPHEMERAL-临时目录节点
0-
EPHEMERAL _SEQUENTIAL-临时顺序编号目录节点
1.PERSISTENT-持久化节点
创建这个节点的客户端在与zookeeper服务的连接断开后,这个节点也不会被删除(除非您使用API强制删除)。
客户端与zookeeper断开连接后,该节点依旧存在
2.PERSISTENT_SEQUENTIAL-持久化顺序编号节点
当客户端请求创建这个节点A后,zookeeper会根据parent-znode的zxid状态,为这个A节点编写一个全目录唯一的编号(这个编号只会一直增长)。当客户端与zookeeper服务的连接断开后,这个节点也不会被删除。
客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节 点名称进行顺序编号
3.EPHEMERAL-临时目录节点
创建这个节点的客户端在与zookeeper服务的连接断开后,这个节点(还有涉及到的子节点)就会被删除。图见 4.
客户端与zookeeper断开连接后,该节点被删除
4.EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点
当客户端请求创建这个节点A后,zookeeper会根据parent-znode的zxid状态,为这个A节点编写一个全目录唯一的编号(这个编号只会一直增长)。当创建这个节点的客户端与zookeeper服务的连接断开后,这个节点被删除。
断开客户端在重新连接
我们发现刚才创建的node2临时节点和node3临时顺序编号节点都已经不存在了。
客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节 点名称进行顺序编号
另外,无论是EPHEMERAL还是EPHEMERAL_SEQUENTIAL节点类型,在zookeeper的client异常终止后,节点也会被删除
Zookeeper表现为一个分层的文件系统目录树结构
不同于文件系统之处在于:zk节点可以有自己的数据,而unix文件系统中的目录节点只有子节点
一个节点对应一个应用/服务,节点存储的数据就是应用需要的配置信息。
3.常用命令
1.zkCli的常用命令
2.zkCli的四字命令
zookeeper支持某些特定的四字命令,他们大多是用来查询ZK服务的当前状态及相关信息的,
通过telnet或nc向zookeeper提交相应命令,如:echo ruok | nc 127.0.0.1 2181
运行公式:echo 四字命令 | nc 主机IP zookeeper端口
除以上总结还有官网提供的
四、Zookeeper实现分布式锁
1.需求
比如有一个很大的公司,这个公司公司每天的订单量很大,所以通过分布式的方式将应用运行在多个服务器上,这些服务器可能在杭州,可能在武汉,可能在黑龙江,那么当用户下单的时候,这么多的服务器都要产生订单编号难免会冲突,因此需要锁,然后系统会生成一个全局唯一的订单编号。
2.思想
我们在JUC那章学的8锁不知道还有印象没有,8锁锁的是this/Class。是线程操作资源类。是在一个JVM中进行操作。
这回可厉害了,由于多个服务器每个服务器都有一个JVM,因此这回锁的是JVM。
曾经是多个线程操作一个JVM,这回是多个线程操作多个JVM。
那我们知道分布式锁了解了分布式锁了,可是怎么通过zookeeper实现分布式锁呢?
思想:
我们知道zookeeper有持久节点和临时节点,其中临时节点是不允许重复的,并且当客户端断开连接的时候,临时节点就会自动删除。那我们能不能利用这个特性呢?
当有一个人下单的时候,一个服务器想请求申请订单号,我们设想服务器在申请订单号之前应该先抢占锁,抢占的方式就是设定一个标记节点,当抢占成功时,将标记节点挂在zookeeper上。
此时其他服务器在想抢占锁就会报节点以重复异常,因此抢占锁失败。所以需要等待,监听节点情况。如果节点被删除,应该马上去抢占锁。
这个服务器申请完订单编号后,断开连接,标记节点就会自动消失,此时,其他服务器可以抢锁。
了解个大概了,我们实现一下吧,我们手写一把锁,ZkLock。
本人使用的工具是IDEA
启动zk服务器并保证防火墙关闭,client (win10) 可以连通server (Linux上面的zk服务器)。
3.实现
1.新建maven项目,在pom文件中导入zookeeper需要的驱动类。
<dependencies>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.9</version>
</dependency>
</dependencies>
2.建立规范接口-ZkLock
是个锁就应该有加锁和解锁。
public interface Zklock {
public void lock();
public void unlock();
}
3.按照模板设计模式,建立抽象类 - ZkAbstractTemplateLock
public abstract class ZkAbstractTemplateLock implements Zklock {
//服务器地址
public static final String ZKSERVER = "10.10.10.120:2181";
//超时时间
public static final int TIME_OUT= 45 * 1000;
//zk客户端
ZkClient zkClient = new ZkClient(ZKSERVER,TIME_OUT);
//临时节点路径
protected String path = "/myzklock";
//线程等待会用到
CountDownLatch countDownLatch = null;
@Override
public void lock() {
//如果锁没有被抢占,就立即抢占
if(tryZklock()) {
System.out.println("线程"+Thread.currentThread().getName()+"抢占锁成功");
}
else //如果锁已经被占用
{
//等待释放锁
waitZklock();
//等待完成,重新尝试抢占锁
lock();
}
}
//模板设计模式,固定化的流程升级到父类定死规范,但是,具体落地实现方法下放给子类各自实现。
public abstract void waitZklock();
public abstract boolean tryZklock();
@Override
public void unlock() {
if(zkClient != null) {
zkClient.close();
System.out.println("线程"+Thread.currentThread().getName()+"释放锁成功\n");
}
}
}
4.继承抽象类,实现抽象方法 - ZkDistributeLock
public class ZkDistributeLock extends ZkAbstractTemplateLock {
@Override
public boolean tryZklock() {
try {
//创建节点path
zkClient.createEphemeral(path);
return true;
}catch (Exception e) {
//节点已存在或其他错误
return false;
}
}
@Override
public void waitZklock() {
//监听器,监听节点path状态
IZkDataListener listener = new IZkDataListener() {
//监听节点,如果节点被删除
@Override
public void handleDataDeleted(String arg0) throws Exception {
//如果countDownLatch!=null意味着有节点正在等待
if(countDownLatch != null) {
//将数字-1,就会解除wait
countDownLatch.countDown();
}
}
//节点改变监听,在这里没用
@Override
public void handleDataChange(String arg0, Object arg1) throws Exception {}
};
//节点监听,path为监听的节点,listener为监听接口,上面已经实现
zkClient.subscribeDataChanges(path, listener);
//必须等待path也即临时节点被删除后才能继续向下运行
//怎么让程序被卡在这里? ? ?
//如果节点已经存在,那么就要等待
if(zkClient.exists(path)) {
//countDownLatch初始为一
countDownLatch = new CountDownLatch(1);
try {
//等待中。。。。。。当节点删除后,会触发监听器,将countDownLatch改回
countDownLatch.await();
} catch (Exception e) {
e.printStackTrace();
}
}
//关闭监听
zkClient.unsubscribeDataChanges(path, listener);
}
}
5.生成订单号工具类 - OrderNumGenerateUtil
private static int number = 0;
public String getorderNumber(){
return " " +(++number);
}
6.订单业务类,主类,OrderService
public class OrderService {
//订单工具类,用来生成订单号
OrderNumGenerateUtil orderNumGenerateUtil = new OrderNumGenerateUtil();
//自己写的锁
Zklock lock = new ZkDistributeLock();
//申请订单
public void getOrderNum() {
lock.lock();
try {
System.out.println("订单编号为:"+orderNumGenerateUtil.getorderNumber());
}finally {
lock.unlock();
}
}
public static void main(String[] args) {
OrderService orderService = new OrderService();
//模拟40个服务器产生的对象申请订单号
for(int i = 0; i<40; i++) {
new Thread(()->{
new OrderService().getOrderNum();
},String.valueOf(i)).start();
}
}
}
到这里,使用zookeeper分布式锁也就结束了。很简单吧。
五、Zookeeper集群
1.简介说明
别把分布式和集群弄混了,分布式是将多个功能运行在多个服务器上,对外展示为一个应用。
集群是为了一个功能而用多台服务器提升效率。
说说Zookeeper集群。
下图有三个服务器,大家都学过redis,原理和redis差不多,自行一看就懂。
集群信息包括,服务器编号,服务器地址,LF通信端口,选举端口
由于上图是真正的集群,本人没有那么多的真实服务器,故只能用一个服务器模拟多个服务器,ip地址一样,只能在端口上做文章。
那么配置项的书写也有公式,这个配置项的书写格式比较特殊,规则如下:server.N=YYY:A:B ;
- N表示服务器编号,
- YYY表示服务器的IP地址,
- A为LF通信端口,表示该服务器与集群中的leader交换的信息的端口。
- B为选举端口,表示选举新leader时服务器间相互通信的端口(当leader挂掉时,其余服务器会相互通信,选择出新的leader)
一般来说,集群中每个服务器的A端口都是一样,每个服务器的B端口也是一样。
下面是一个集群的例子:
server.0=233.34.9.144:2008:6008
server.1=233.34.9.145:2008:6008
server.2=233.34.9.146:2008:6008
server.3=233.34.9.147:2008:6008
但是当所采用的为伪集群时,IP地址都一样,只能是A端口和B端口不一样。
下面是一个伪集群的例子:
server.0=127.0.0.1:2008:6008
server.1=127.0.0.1:2007:6007
server.2=127.0.0.1:2006:6006
server.3=127.0.0.1:2005:6005
在节点一章提到节点的结构时,有两点没有解释
- initLimit是Zookeeper用它来限定集群中的Zookeeper服务器连接到Leader的时限说明。
- syncLimit 限制了follower服务器与leader服务器之间请求和应答之间的时限
架构。
2.配置步骤
1.zookeeper-3.4.9.tar.gz解压后拷贝到/myzookeeper目录下并重新名为zk01,再复制zk01形成zk02、zk03, 共计3份
2.进入zk01/02/03分别新建文件夹,mydata、mylog
3.分别进入zk01-zk03各自的conf文件夹,新建zoo.cfg
4.编辑zoo.cfg
- 设置自己的数据和log路径
dataDir= /myzookeeper/zk01/mydata
dataLogDir=/myzookeeper/zk01/mylog - 修改各自的clientPort
- 在最后面添加server的列表
5.在各自mydata下面创建myid的文件,在里面写入server的数字
6.分别启动三个服务器
- zkCli连接server,带参数指定-server
2191/2192/2193任意用客户端链接一台,会发现只需要有一个改变了,整个集群的内容自动一致性同步。
文章的最后,我们再看一下那条公式
zookeeper=类似unix文件系统+通知机制+Znode节点
文件系统,如 /zookeeper
通知机制,在实现分布式锁的时候,等待与通知
Znode节点,粗略分2类,细致分3类