栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

zookeeper教程

zookeeper教程

文章目录

⼀、Zookeeper介绍

1.什么是Zookeeper2.Zookeeper的应⽤场景 ⼆、搭建Zookeeper服务器

1.zoo.cfg 配置⽂件说明2.Zookeeper服务器的操作命令 三、Zookeeper内部的数据模型

1.zk是如何保存数据的2.zk中的znode是什么样的结构3.zk中节点znode的类型4.zk的数据持久化 四、Zookeeper客户端(zkCli)的使⽤

1.多节点类型创建2.查询节点3.删除节点4.权限设置 五、Curator客户端的使⽤

1.Curator介绍1.引⼊Curator2.创建节点3.获得节点数据4.修改节点数据5.创建节点同时创建⽗节点6.删除节点 六、zk实现分布式锁

1.zk中锁的种类:2.zk如何上读锁3.zk如何上写锁4.⽺群效应5.curator实现读写锁 七、zk的watch机制

1.Watch机制介绍2.zkCli客户端使⽤watch ⼋、Zookeeper集群实战

1.Zookeeper集群⻆⾊2.集群搭建3.连接Zookeeper集群 九、ZAB协议

1.什么是ZAB协议2.ZAB协议定义的四种节点状3.集群上线时的Leader选举过程4.崩溃恢复时的Leader选举5.主从服务器之间的数据同步6.Zookeeper中的NIO与BIO的应⽤ ⼗、CAP理论

1.CAP 定理2.CAP 权衡3.base 理论4.Zookeeper追求的⼀致性

⼀、Zookeeper介绍 1.什么是Zookeeper

ZooKeeper 是⼀种分布式协调服务,⽤于管理⼤型主机。在分布式环境中协调和管理服务是 ⼀个复杂的过程。ZooKeeper 通过其简单的架构和 API 解决了这个问题。ZooKeeper 允许开 发⼈员专注于核⼼应⽤程序逻辑,⽽不必担⼼应⽤程序的分布式特性。

2.Zookeeper的应⽤场景

分布式协调组件

在分布式系统中,需要有zookeeper作为分布式协调组件,协调分布式系统中的状态。

分布式锁 zk在实现分布式锁上,可以做到强⼀致性,关于分布式锁相关的知识,在之后的ZAB协议中介 绍

⽆状态化的实现

⼆、搭建Zookeeper服务器 1.zoo.cfg 配置⽂件说明
# zookeeper时间配置中的基本单位 (毫秒)
tickTime=2000
# 允许follower初始化连接到leader最⼤时⻓,它表示tickTime时间倍数
即:initLimit*tickTime
initLimit=10
# 允许follower与leader数据同步最⼤时⻓,它表示tickTime时间倍数
syncLimit=5
#zookeper 数据存储⽬录及⽇志保存⽬录(如果没有指明dataLogDir,则⽇志也保存在这个
⽂件中)
dataDir=/tmp/zookeeper
#对客户端提供的端⼝号
clientPort=2181
#单个客户端与zookeeper最⼤并发连接数
maxClientCnxns=60
# 保存的数据快照数量,之外的将会被清除
autopurge.snapRetainCount=3
#⾃动触发清除任务时间间隔,⼩时为单位。默认为0,表示不⾃动清除。
autopurge.purgeInterval=1 
2.Zookeeper服务器的操作命令

重命名 conf中的⽂件zoo_sample.cfg->zoo.cfg

./bin/zkServer.sh start ./conf/zoo.cf

启动zk服务器:

./bin/zkServer.sh start ./conf/zoo.cf

查看zk服务器状态:

./bin/zkServer.sh status./conf/zoo.cf

停⽌zk服务器:

./bin/zkServer.sh stop./conf/zoo.cfg

三、Zookeeper内部的数据模型 1.zk是如何保存数据的

zk中的数据是保存在节点上的,节点就是znode,多个znode之间构成⼀颗树的⽬录结构。 Zookeeper 的数据模型是什么样⼦呢?它很像数据结构当中的树,也很像⽂件系统的⽬录。

树是由节点所组成,Zookeeper 的数据存储也同样是基于节点,这种节点叫做 Znode 但是,不同于树的节点,Znode 的引⽤⽅式是路径引⽤,类似于⽂件路径:

/animal/dog
/车/宝马

这样的层级结构,让每⼀个 Znode 节点拥有唯⼀的路径,就像命名空间⼀样对不同信息作出 清晰的隔离。

2.zk中的znode是什么样的结构

zk中的znode,包含了四个部分:

data:保存数据acl:权限,定义了什么样的⽤户能够操作这个节点,且能够进⾏怎样的操作。

c: create 创建权限,允许在该节点下创建⼦节点w:write 更新权限,允许更新该节点的数据r:read 读取权限,允许读取该节点的内容以及⼦节点的列表信息d:delete 删除权限,允许删除该节点的⼦节点a:admin 管理者权限,允许对该节点进⾏acl权限设置 stat:描述当前znode的元数据child:当前节点的⼦节点 3.zk中节点znode的类型

持久节点: 创建出的节点,在会话结束后依然存在。保存数据

持久序号节点: 创建出的节点,根据先后顺序,会在节点之后带上⼀个数值,越后执⾏数 值越⼤,适⽤于分布式锁的应⽤场景- 单调递增

临时节点:
临时节点是在会话结束后,⾃动被删除的,通过这个特性,zk可以实现服务注册与发现的 效果。那么临时节点是如何维持⼼跳呢?

临时序号节点:跟持久序号节点相同,适⽤于临时的分布式锁。 Container节点(3.5.3版本新增):

Container容器节点,当容器中没有任何⼦节点,该 容器节点会被zk定期删除(60s)。

TTL节点:可以指定节点的到期时间,到期后被zk定时删除。只能通过系统配置 zookeeper.extendedTypesEnabled=true 开启

4.zk的数据持久化

zk的数据是运⾏在内存中,zk提供了两种持久化机制:

事务⽇志 zk把执⾏的命令以⽇志形式保存在dataLogDir指定的路径中的⽂件中(如果没有指定 dataLogDir,则按dataDir指定的路径)。数据快照 zk会在⼀定的时间间隔内做⼀次内存数据的快照,把该时刻的内存数据保存在快照⽂件 中。

zk通过两种形式的持久化,在恢复时先恢复快照⽂件中的数据到内存中,再⽤⽇志⽂件中的 数据做增量恢复,这样的恢复速度更快。

四、Zookeeper客户端(zkCli)的使⽤ 1.多节点类型创建

创建持久节点创建持久序号节点创建临时节点创建临时序号节点创建容器节点 2.查询节点

普通查询查询节点相信信息

cZxid: 创建节点的事务IDmZxid:修改节点的事务IDpZxid:添加和删除⼦节点的事务IDctime:节点创建的时间mtime: 节点最近修改的时间dataVersion: 节点内数据的版本,每更新⼀次数据,版本会+1aclVersion: 此节点的权限版本ephemeralOwner: 如果当前节点是临时节点,该值是当前节点所有者的session id。如果节点不是临时节点,则该值为零。dataLength: 节点内数据的⻓度 numChildren: 该节点的⼦节点个数 3.删除节点

普通删除乐观锁删除 4.权限设置

注册当前会话的账号和密码:

addauth digest xiaowang:12345

创建节点并设置权限

create /test-node abcd auth:xiaowang:123456:cdwra

在另⼀个会话中必须先使⽤账号密码,才能拥有操作该节点的权限

五、Curator客户端的使⽤ 1.Curator介绍

Curator是Netflix公司开源的⼀套zookeeper客户端框架,Curator是对Zookeeper⽀持最好 的客户端框架。Curator封装了⼤部分Zookeeper的功能,⽐如Leader选举、分布式锁等,减 少了技术⼈员在使⽤Zookeeper时的底层细节开发⼯作。

1.引⼊Curator

引⼊依赖


 
 org.apache.curator
 curator-framework
 2.12.0
 
 
 org.apache.curator
 curator-recipes
 2.12.0
 
 
 
 org.apache.zookeeper
 zookeeper
 3.7.14
 

application.properties配置⽂件

curator.retryCount=5
curator.elapsedTimeMs=5000
curator.connectString=172.16.253.35:2181
curator.sessionTimeoutMs=60000
curator.connectionTimeoutMs=5000

注⼊配置Bean

@Data
@Component
@ConfigurationProperties(prefix = "curator")
public class WrapperZK {
 private int retryCount;
 private int elapsedTimeMs;
 private String connectString;
 private int sessionTimeoutMs;
 private int connectionTimeoutMs;
}

@Data

@Configuration
public class CuratorConfig {
 @Autowired
 WrapperZK wrapperZk;
 @Bean(initMethod = "start")
 public Curatorframework curatorframework() {
 return CuratorframeworkFactory.newClient(
 wrapperZk.getConnectString(),
 wrapperZk.getSessionTimeoutMs(),
 wrapperZk.getConnectionTimeoutMs(),
 new RetryNTimes(wrapperZk.getRetryCount(),
wrapperZk.getElapsedTimeMs()));
 }
}
2.创建节点
 @Autowired
 Curatorframework curatorframework; 
 @Test
 void createNode() throws Exception {
 //添加持久节点
 String path = curatorframework.create().forPath("/curator-node");
 //添加临时序号节点
 String path1 =
curatorframework.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).for
Path("/curator-node", "some-data".getBytes());
 System.out.println(String.format("curator create node :%s 
successfully.",path));
 System.in.read();
 }
3.获得节点数据
@Test
 public void testGetData() throws Exception {
 byte[] bytes = curatorframework.getData().forPath("/curator-node");
 System.out.println(new String(bytes));
 }
4.修改节点数据
@Test
 public void testSetData() throws Exception {
 curatorframework.setData().forPath("/curatornode","changed!".getBytes());
 byte[] bytes = curatorframework.getData().forPath("/curator-node");
 System.out.println(new String(bytes));
 }
5.创建节点同时创建⽗节点
@Test
 public void testCreateWithParent() throws Exception {
 String pathWithParent="/node-parent/sub-node-1";
 String path =
curatorframework.create().creatingParentsIfNeeded().forPath(pathWithPare
nt);
 System.out.println(String.format("curator create node :%s 
successfully.",path));
 }
6.删除节点
@Test
 public void testCreateWithParent() throws Exception {
 String pathWithParent="/node-parent/sub-node-1";
 String path =
curatorframework.create().creatingParentsIfNeeded().forPath(pathWithPare
nt);
 System.out.println(String.format("curator create node :%s 
successfully.",path));
 }
六、zk实现分布式锁 1.zk中锁的种类:

读锁:⼤家都可以读,要想上读锁的前提:之前的锁没有写锁写锁:只有得到写锁的才能写。要想上写锁的前提是,之前没有任何锁。 2.zk如何上读锁

创建⼀个临时序号节点,节点的数据是read,表示是读锁获取当前zk中序号⽐⾃⼰⼩的所有节点判断最⼩节点是否是读锁:

如果不是读锁的话,则上锁失败,为最⼩节点设置监听。阻塞等待,zk的watch机制 会当最⼩节点发⽣变化时通知当前节点,于是再执⾏第⼆步的流程如果是读锁的话,则上锁成功
3.zk如何上写锁

创建⼀个临时序号节点,节点的数据是write,表示是 写锁 获取zk中所有的⼦节点判断⾃⼰是否是最⼩的节点:

如果是,则上写锁成功如果不是,说明前⾯还有锁,则上锁失败,监听最⼩的节点,如果最⼩节点有变化, 则回到第⼆步。
4.⽺群效应

如果⽤上述的上锁⽅式,只要有节点发⽣变化,就会触发其他节点的监听事件,这样的话对 zk的压⼒⾮常⼤,——⽺群效应。可以调整成链式监听。解决这个问题。

5.curator实现读写锁

1)获取读锁

@Test
 void testGetReadLock() throws Exception {
 // 读写锁
 InterProcessReadWriteLock interProcessReadWriteLock=new
InterProcessReadWriteLock(client, "/lock1");
 // 获取读锁对象
 InterProcessLock
interProcessLock=interProcessReadWriteLock.readLock();
 System.out.println("等待获取读锁对象!");
 // 获取锁
 interProcessLock.acquire();
 for (int i = 1; i <= 100; i++) {
 Thread.sleep(3000);
 System.out.println(i);
 }
 // 释放锁
 interProcessLock.release();
 System.out.println("等待释放锁!");
 }

2)获取写锁

@Test
 void testGetWriteLock() throws Exception {
 // 读写锁
 InterProcessReadWriteLock interProcessReadWriteLock=new
InterProcessReadWriteLock(client, "/lock1");
 // 获取写锁对象
 InterProcessLock
interProcessLock=interProcessReadWriteLock.writeLock();
 System.out.println("等待获取写锁对象!");
 // 获取锁
 interProcessLock.acquire();
 for (int i = 1; i <= 100; i++) {
 Thread.sleep(3000);
 System.out.println(i);
 }
 // 释放锁
 interProcessLock.release();
 System.out.println("等待释放锁!");
 }
七、zk的watch机制 1.Watch机制介绍

我们可以把 Watch 理解成是注册在特定 Znode 上的触发器。当这个 Znode 发⽣改变,也就 是调⽤了 create , delete , setData ⽅法的时候,将会触发 Znode 上注册的对应事件, 请求 Watch 的客户端会接收到异步通知。

具体交互过程如下:

客户端调⽤ getData ⽅法, watch 参数是 true 。服务端接到请求,返回节点数据,并 且在对应的哈希表⾥插⼊被 Watch 的 Znode 路径,以及 Watcher 列表。当被 Watch 的 Znode 已删除,服务端会查找哈希表,找到该 Znode 对应的所有 Watcher,异步通知客户端,并且删除哈希表中对应的 Key-Value。

客户端使⽤了NIO通信模式监听服务端的调⽤。

2.zkCli客户端使⽤watch

create /test xxx
get -w /test ⼀次性监听节点
ls -w /test 监听⽬录,创建和删除⼦节点会收到通知。⼦节点中新增节点不会收到通知
ls -R -w /test 对于⼦节点中⼦节点的变化,但内容的变化不会收到通知

3.curator客户端使⽤watch

@Test
 public void addNodeListener() throws Exception {
 
 NodeCache nodeCache = new NodeCache(curatorframework, "/curatornode");
 nodeCache.getListenable().addListener(new NodeCacheListener() {
 @Override
 public void nodeChanged() throws Exception {
 log.info("{} path nodeChanged: ","/curator-node");
 printNodeData();
 }
 });
 nodeCache.start();
 System.in.read(); 
 }
 public void printNodeData() throws Exception {
 byte[] bytes = curatorframework.getData().forPath("/curator-node");
 log.info("data: {}",new String(bytes));
 }
⼋、Zookeeper集群实战 1.Zookeeper集群⻆⾊

zookeeper集群中的节点有三种⻆⾊

Leader:处理集群的所有事务请求,集群中只有⼀个Leader。Follower:只能处理读请求,参与Leader选举Observer:只能处理读请求,提升集群读的性能,但不能参与Leader选举。 2.集群搭建

搭建4个节点,其中⼀个节点为
1)创建4个节点的myid,并设值
在/usr/local/zookeeper中创建以下四个⽂件

/usr/local/zookeeper/zkdata/zk1# echo 1 > myid
/usr/local/zookeeper/zkdata/zk2# echo 2 > myid
/usr/local/zookeeper/zkdata/zk3# echo 3 > myid
/usr/local/zookeeper/zkdata/zk4# echo 4 > myid

2)编写4个zoo.cfg

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# 修改对应的zk1 zk2 zk3 zk4
dataDir=/usr/local/zookeeper/zkdata/zk1
# 修改对应的端⼝ 2181 2182 2183 2184
clientPort=2181
# 2001为集群通信端⼝,3001为集群选举端⼝,observer表示不参与集群选举
server.1=172.16.253.54:2001:3001
server.2=172.16.253.54:2002:3002
server.3=172.16.253.54:2003:3003
server.4=172.16.253.54:2004:3004:observer

3)启动4台Zookeeper

./bin/zkServer.sh status ./conf/zoo1.cfg
./bin/zkServer.sh status ./conf/zoo2.cfg
./bin/zkServer.sh status ./conf/zoo3.cfg
./bin/zkServer.sh status ./conf/zoo4.cfg

3.连接Zookeeper集群

./bin/zkCli.sh -server
172.16.253.54:2181,172.16.253.54:2182,172.16.253.54:2183

九、ZAB协议 1.什么是ZAB协议

zookeeper作为⾮常重要的分布式协调组件,需要进⾏集群部署,集群中会以⼀主多从的形式 进⾏部署。zookeeper为了保证数据的⼀致性,使⽤了ZAB(Zookeeper Atomic Broadcast)协议,这个协议解决了Zookeeper的崩溃恢复和主从数据同步的问题。

2.ZAB协议定义的四种节点状

Looking :选举状态。Following :Follower 节点(从节点)所处的状态。 Leading :Leader 节点(主节点)所处状态。Observing:观察者节点所处的状态 3.集群上线时的Leader选举过程

Zookeeper集群中的节点在上线时,将会进⼊到Looking状态,也就是选举Leader的状态,这 个状态具体会发⽣什么?

4.崩溃恢复时的Leader选举

Leader建⽴完后,Leader周期性地不断向Follower发送⼼跳(ping命令,没有内容的 socket)。当Leader崩溃后,Follower发现socket通道已关闭,于是Follower开始进⼊到 Looking状态,重新回到上⼀节中的Leader选举过程,此时集群不能对外提供服务。

5.主从服务器之间的数据同步

6.Zookeeper中的NIO与BIO的应⽤

NIO

⽤于被客户端连接的2181端⼝,使⽤的是NIO模式与客户端建⽴连接客户端开启Watch时,也使⽤NIO,等待Zookeeper服务器的回调 BIO 集群在选举时,多个节点之间的投票通信端⼝,使⽤BIO进⾏通信。 ⼗、CAP理论 1.CAP 定理

2000 年 7 ⽉,加州⼤学伯克利分校的 Eric Brewer 教授在 ACM PODC 会议上提出 CAP 猜 想。2年后,麻省理⼯学院的 Seth Gilbert 和 Nancy Lynch 从理论上证明了 CAP。之后, CAP 理论正式成为分布式计算领域的公认定理。

CAP 理论为:⼀个分布式系统最多只能同时满⾜⼀致性(Consistency)、可⽤性 (Availability)和分区容错性(Partition tolerance)这三项中的两项。

⼀致性(Consistency) ⼀致性指 “all nodes see the same data at the same time”,即更新操作成功并返回客户端 完成后,所有节点在同⼀时间的数据完全⼀致。可⽤性(Availability) 可⽤性指“Reads and writes always succeed”,即服务⼀直可⽤,⽽且是正常响应时间。分区容错性(Partition tolerance)

分区容错性指“the system continues to operate despite arbitrary message loss or failure of part of the system”,即分布式系统在遇到某节点或⽹络
分区故障的时候,仍然能够对外 提供满⾜⼀致性或可⽤性的服务。——避免单点故障,就要进⾏冗余部署,冗余部署相当于 是服务的分区,这样的分区就具备了容错性。

2.CAP 权衡

通过 CAP 理论,我们知道⽆法同时满⾜⼀致性、可⽤性和分区容错性这三个特性,那要舍弃 哪个呢?

对于多数⼤型互联⽹应⽤的场景,主机众多、部署分散,⽽且现在的集群规模越来越⼤,所 以节点故障、⽹络故障是常态,⽽且要保证服务可⽤性达到 N 个 9,即保证 P 和 A,舍弃 C(退⽽求其次保证最终⼀致性)。虽然某些地⽅会影响客户体验,但没达到造成⽤户流程的 严重程度。

对于涉及到钱财这样不能有⼀丝让步的场景,C 必须保证。⽹络发⽣故障宁可停⽌服务,这是 保证 CA,舍弃 P。貌似这⼏年国内银⾏业发⽣了不下 10 起事故,但影响⾯不⼤,报到也不 多,⼴⼤群众知道的少。还有⼀种是保证 CP,舍弃 A。例如⽹络故障是只读不写。

孰优孰略,没有定论,只能根据场景定夺,适合的才是最好的。

3.base 理论

eBay 的架构师 Dan Pritchett 源于对⼤规模分布式系统的实践总结,在 ACM 上发表⽂章提出 base 理论,base 理论是对 CAP 理论的延伸,核⼼思想是即使⽆法做到强⼀致性(Strong Consistency,CAP 的⼀致性就是强⼀致性),但应⽤可以采⽤适合的⽅式达到最终⼀致性 (Eventual Consitency)。

基本可⽤(Basically Available)

可⽤是指分布式系统在出现故障的时候,允许损失部分可⽤性,即保证核⼼可⽤。 电商⼤促时,为了应对访问量激增,部分⽤户可能会被引导到降级⻚⾯,服务层也可能只提 供降级服务。这就是损失部分可⽤性的体现。

软状态(Soft State)

软状态是指允许系统存在中间状态,⽽该中间状态不会影响系统整体可⽤性。分布式存储中 ⼀般⼀份数据⾄少会有三个副本,允许不同节点间副本同步的延时就是软状态的体现。mysql replication 的异步复制也是⼀种体现。

最终⼀致性(Eventual Consistency)

最终⼀致性是指系统中的所有数据副本经过⼀定时间后,最终能够达到⼀致的状态。弱⼀致 性和强⼀致性相反,最终⼀致性是弱⼀致性的⼀种特殊情况。

4.Zookeeper追求的⼀致性

Zookeeper在数据同步时,追求的并不是强⼀致性,⽽是顺序⼀致性(事务id的单调递增)。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/700272.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号