一、zookeeper详解概念与原理(总结的干货)

ZK总结:
zookeeper(以下就用ZK代替)是一个分布式协调系统,主要有两大功能,文件系统和通知系统。

1、zk(分布式高性协调系统):
功能:
配置服务
集群管理
名字服务
分布式同步
发布订阅(注册中心)
数据库动态切换
分布式日志收集
分布式锁
队列管理
组服务等

2、zk结构和Linux有点类似
树状结构

3、zk的角色
leader
follower
observer(比如:操作zk的java代码)

4、zk的主要特点:
1.最终一致性
2.可靠性
3.实时性
4.等待无关性
5.原子性
6.顺序性

一、概念:

1.zk结构:常规ZNode和临时ZNode

2.zk服务器端和zk客户端
zk客户端请求zk server集群的时候,zk server可以透明的移动(zk server 通过zk leader可以把资源共享)
zk客户端请求zk server的时候会生成一个session,session是可以设置超时间(t),每t/3ms 就会向服务器
发送一个心跳来维持长连接,如果2t/3ms 没有接收到zk server的心跳回复,就会切换到另一个zk server3.ZK Watcher
Zk支持Watch操作,zk Client可以在zk server上的ZNode节点上设置Watcher,
如果ZNode有变化就会通知Zk client端,但是Watcher 是一次性的,如果需要必须重新设置Watcher。

二、ZK的特性

1.读写模式
1.1.读:zk client端读取数据的时候,可以从任意一个ZK server中读取
1.2.写:zk client端操作写数据的时候,一般请求会作用在follower上,然后再到leader上,然后leader通过
(原子广播协议)将写数据的请求广播给所有的Follower,Leader只要收到一半以上的Follower写数据成功的(ACK)响应后,
就将持久化数据。并且把操作成功结果响应给zk client2.WAL(Write-Ahead-Log:在操作数据之前写日志)和Snapshot
2.1.WAL:对于zk 的每个操作都会先WAL,然后再对数据做操作。
2.2.Snapshot:每隔一段时间zk会对内存中的目录树形ZNode进行Snapshot,
写入磁盘。(这与HDFS中的FSImage的功能类似)。目的:确保数据完整备份和持久化,让zk的启动恢复速度加快。

3.FIFO:所有的zk client操作zk server都遵循FIFO顺序,因为通讯协议是基于TCP的,
tcp传输包是FIFO的顺序,zk server也是按照FIFO顺序执行的。

4.Linearizability:zk都是FIFO的,更新的操作都是串行的。

三、ZK client API接口

    create(path, data, flags): 创建一个ZNode path是其路径,data是要存储在该ZNode上的数据,
    flags常用的有: PERSISTEN, PERSISTENT_SEQUENTAIL, EPHEMERAL, EPHEMERAL_SEQUENTAIL

    delete(path, version): 删除一个ZNode,可以通过version删除指定的版本, 如果version是-1的话,

    exists(path, watch): 判断指定ZNode是否存在,并设置是否Watch这个ZNode。这里如果要设置Watcher的话,
    以下几个带watch参数的API也都类似


    setData(path, watch): 更新指定ZNode的数据,并设置是否Watch这个ZNode


    sync(path): 把所有在sync之前的更新操作都进行同步,达到每个请求都在半数以上的ZooKeeper Server上生效。
    path参数目前没有用


    getAcl(path): 获取指定ZNode的Acl信息

四、常用的zk使用场景
1.名字服务:在分布式系统中,一般需要一套命令机制,既要能产生唯一标识,又能便于记忆和识别。因为每个ZNode都可以标识路径的唯一性,路径本身比较简单直观,ZNode可以存储少量数据(一般默认1M)
1.1.通过简单的名字来访问指定的HDFS集群
1.2.定义命名规则:这里要做到简洁易记忆。下面是一种可选的方案: [serviceScheme://][zkCluster]-[clusterName],比如hdfs://lgprc-example/表示基于lgprc ZooKeeper集群的用来做example的HDFS集群
1.3.配置DNS映射: 将zkCluster的标识lgprc通过DNS解析到对应的ZooKeeper集群的地址
1.4.创建ZNode:在对应的ZooKeeper上创建/NameService/hdfs/lgprc-example结点,将HDFS的配置文件存储于该结点下
1.5.用户程序要访问hdfs://lgprc-example/的HDFS集群,首先通过DNS找到lgprc的ZooKeeper机群的地址,然后在ZooKeeper的/NameService/hdfs/lgprc-example结点中读取到HDFS的配置,进而根据得到的配置,得到HDFS的实际访问入口

2.配置管理:在分布式系统中,有很多实例中的大多数配置项是相同的,需要改变配置项,如果有zk的话,不需要在每个实例去修改。
2.1.将公共的配置内容放在zk中的某个ZNode上,如:/xpservice/common-conf
2.2.所有的实例在启动时会把zk的集群的入口地址,运行中Watch 到/xpservice/common-conf这个ZNode
2.3.zk集群修改了/xpservice/common-conf,所有的实例都会被通知到,跟新自己的配置,并且重新设置Watch /xpservice/common-conf节点

3.组员管理:在Master-Slave结构的分布式系统中,Master管理所有的Slave,当有Slave加入,或者有Slave宕机,master都需要知道,然后做出调整,以便不影响整个集群对外提供服务。如:HBase。HMaster管理了所有的RegionServer,当有新的RegionServer加入的时候,HMaster需要分配一些Region到该RegionServer上其提供服务;当有RegionServer宕机时,HMaster需要将该RegionServer之前服务的Region都重新分配到当前正在提供服务的其它RegionServer上,以便不影响客户端的正常访问。
3.1.Master在ZooKeeper上创建/service/slaves结点,并设置对该结点的Watcher
3.2.每个Slave在启动成功后,创建唯一标识自己的临时性(Ephemeral)结点/service/slaves/${slave_id},并将自己地址(ip/port)等相关信息写入该结点
3.3.Master收到有新子结点加入的通知后,做相应的处理
3.4.如果有Slave宕机,由于它所对应的结点是临时性结点,在它的Session超时后,ZooKeeper会自动删除该结点
3.5.Master收到有子结点消失的通知,做相应的处理

4.简单的分布式锁(简单互斥锁):传统线程、进程的同步,操作系统一般可以提供相应的机制完成。在分布式系统,多个进程之间的同步,操作系统层就不能为力。在这个时候就需要zk这样的分布式协调(Coordination)服务来协助完成同步。
4.1.多个进程去在指定的目录下创建一个临时节点(临时ZNode),如:/lock/my_lock
4.2.zk是可以保证一个进程只会一个进程创建了该节点,创建成功进程相当于抢到锁
4.3.其他进程对/lock/my_lock进行watch
4.4.当获取锁的进程不需要锁的时候,显示的删除/lock/my_lock节点(ZNode),然后Watcher就能监测到变更,然后通知让其他进程去创建/lock/my_lock临时节点(ZNode)抢锁过程。依次循环。

5.分布式锁(互斥锁):上面简单分布式锁,每次都会有大量进程竞争,会造成羊群效应(Herd Effect),为了解决这个问题。
5.1.每个进程ZK上创建临时的顺序节点(Ephemeral Sequential)/lock/lock_ s e q 5.2. {req}最小的为当前的锁持有者(${req}是ZK生成的Sequential number)
5.3.其他进程只对比自己小的进程节点Watch,如:进程2 Watch 进程1,进程3 Watch 进程2,以此类推
5.4.当前持锁释放锁后,比当前进程大的进程就会收到ZK的通知,它就成为持锁者,如此循环。
补充:分布式系统中,zk来做leader Election(选主)就是通过上面的机制来实现的,这里的持锁者就是当前的“主”

6.读写锁:读写锁和互斥锁不同的地方是,读写锁分成读和写两种模式,多个读是可以并发执行,但写和读、都是互斥的。不能同事执行。利用zk,在上面的基础上,稍作修改也可以实现传统的读写锁的语义。
6.1.每个进程都在zk上创建一个临时的顺序点(Ephemeral Sequential)/lock/lock_ s e q 6.2. {req}最小的一个或多个节点为当前的持锁者,多个是因为多个读可以并发
6.3.需要写锁的进程,watch比它次小的进程对应的节点
6.4.需要读锁的进程,watch比它小的最后一个写进程对应的节点
6.5.当前节点释放锁后,所有的watch该节点的进程都会被通知到,他们成为新的持锁者,如此循环反复。

7. 屏障(Barrier)
在分布式系统中,屏障是这样一种语义: 客户端需要等待多个进程完成各自的任务,然后才能继续往前进行下一步。下用是用ZooKeeper来实现屏障的基本步骤:

7.1.Client在ZooKeeper上创建屏障结点/barrier/my_barrier,并启动执行各个任务的进程
7.2.Client通过exist()来Watch /barrier/my_barrier结点 7.3.每个任务进程在完成任务后,去检查是否达到指定的条件,如果没达到就啥也不做,如果达到了就把/barrier/my_barrier结点删除
7.4.Client收到/barrier/my_barrier被删除的通知,屏障消失,继续下一步任务

8. 双屏障(Double Barrier)
双屏障是这样一种语义: 它可以用来同步一个任务的开始和结束,当有足够多的进程进入屏障后,才开始执行任务;当所有的进程都执行完各自的任务后,屏障才撤销。下面是用ZooKeeper来实现双屏障的基本步骤:

进入屏障: 

Client Watch /barrier/ready结点, 通过判断该结点是否存在来决定是否启动任务每个任务进程进入屏障时创建一个临时结点/barrier/process/${process_id},然后检查进入屏障的结点数是否达到指定的值,如果达到了指定的值,就创建一个/barrier/ready结点,否则继续等待Client收到/barrier/ready创建的通知,就启动任务执行过程

离开屏障: 

Client Watch /barrier/process,如果其没有子结点,就可以认为任务执行结束,可以离开屏障

每个任务进程执行任务结束后,都需要删除自己对应的结点/barrier/process/${process_id}

猜你喜欢

转载自blog.csdn.net/xp_zyl/article/details/79928974
今日推荐