ZooKeeper整理

ZooKeeper是一个开源的分布式应用协调工具,主要用于统一命名、状态同步服务、集群管理、分布式应用配置项的管理工作
zookeeper集群架构图
zookeeper具有:最终一致性、可靠性、实时性、等待无关、原子性、顺序性
注:
Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服 务器失效的信息。但由于网络延时等原因,Zookeeper不能保证两个客户端能同时得到刚 更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。

与同类产品Eureka的对比:
在分布式系统领域有个著名的CAP定理(C-数据一致性;A-服务可用性;P-服务对网络分区故障的容错性,这三个特性在任何分布式系统中不能同时满足,最多同时满足两个)。
Zookeeper是基于CP来设计的,即任何时刻对Zookeeper的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性,但是它不能保证每次服务请求的可用性。从实际情况来分析,在使用Zookeeper获取服务列表时,如果zookeeper正在选主,或者Zookeeper集群中半数以上机器不可用,那么将无法获得数据。所以说,Zookeeper不能保证服务可用性。
诚然,在大多数分布式环境中,尤其是涉及到数据存储的场景,数据一致性应该是首先被保证的,这也是zookeeper设计成CP的原因。但是对于服务发现场景来说,情况就不太一样了:针对同一个服务,即使注册中心的不同节点保存的服务提供者信息不尽相同,也并不会造成灾难性的后果。因为对于服务消费者来说,能消费才是最重要的——拿到可能不正确的服务实例信息后尝试消费一下,也好过因为无法获取实例信息而不去消费。(尝试一下可以快速失败,之后可以更新配置并重试)所以,对于服务发现而言,可用性比数据一致性更加重要——AP胜过CP。
Eureka时遵守的则是AP原则。Eureka Server也可以运行多个实例来构建集群,解决单点问题,但不同于ZooKeeper的选举leader的过程,Eureka Server采用的是Peer to Peer对等通信。这是一种去中心化的架构,无master/slave区分,每一个Peer都是对等的。在这种架构中,节点通过彼此互相注册来提高可用性,每个节点需要添加一个或多个有效的serviceUrl指向其他节点。每个节点都可被视为其他节点的副本。
如果某台Eureka Server宕机,Eureka Client的请求会自动切换到新的Eureka Server节点,当宕机的服务器重新恢复后,Eureka会再次将其纳入到服务器集群管理之中。当节点开始接受客户端请求时,所有的操作都会进行replicateToPeer(节点间复制)操作,将请求复制到其他Eureka Server当前所知的所有节点中。
一个新的Eureka Server节点启动后,会首先尝试从邻近节点获取所有实例注册表信息,完成初始化。Eureka Server通过getEurekaServiceUrls()方法获取所有的节点,并且会通过心跳续约的方式定期更新。默认配置下,如果Eureka Server在一定时间内没有接收到某个服务实例的心跳,Eureka Server将会注销该实例(默认为90秒,通过eureka.instance.lease-expiration-duration-in-seconds配置)。当Eureka Server节点在短时间内丢失过多的心跳时(比如发生了网络分区故障),那么这个节点就会进入自我保护模式。
ZooKeeper基于CP,不保证高可用,如果zookeeper正在选主,或者Zookeeper集群中半数以上机器不可用,那么将无法获得数据。
Eureka基于AP,能保证高可用,即使所有机器都挂了,也能拿到本地缓存的数据。作为注册中心,其实配置是不经常变动的,只有发版和机器出故障时会变。对于不经常变动的配置来说,CP是不合适的,而AP在遇到问题时可以用牺牲一致性来保证可用性,既返回旧数据,缓存数据。
所以理论上Eureka是更适合作注册中心。而现实环境中大部分项目可能会使用ZooKeeper,那是因为集群不够大,并且基本不会遇到用做注册中心的机器一半以上都挂了的情况。所以实际上也没什么大问题。

ZooKeeper组成
1.Zookeeper核心是原子广播,基于zab协议(Paxos算法)
zab协议,zookeeper数据一致性核心算法,类似于2pc
与2pc的区别:
半数ack即commit,避免阻塞情况,相当于优化了2pc,通过崩溃恢复解决了2pc的单点问题,通过队列解决了2pc的同步阻塞问题
主要实现:
1.使用一个单一的主进程来接收并处理客户端的所有事务请求
2.保证一个全局的变更序列被顺序应用
3.当主进程出现异常情况时,依旧能正常工作

2.zab协议有两种模式(消息广播模式、崩溃恢复模式)
消息广播模式:
leader将客户端的写操作转化为失误,在数据写入完成后,向所有的follower节点发送 数据广播请求,等待follower的反馈,半数反馈ok,leader节点就会向所有的follower 节点发送commit消息,即将leader的数据同步到了follower上
崩溃恢复模式:
若leader服务器发生崩溃,则zab协议要求zookeeper集群进行崩溃恢复,以及leader 服务器的选举;选举需满足以下两个条件:
1.确保已经被leader提交的proposal必须被所有的follower提交;
2.确保丢弃已经被leader提出但还没有提交的proposal

3.类似于Linux文件系统的树形结构
在这里插入图片描述
树中每个节点被称为–Znode
Znode间距文件和目录两种特点。既能像文件一样维护着数据、元信息、ACL、时间戳等数 据结构,又能像目录一样作为路径标识的一部分

Znode类型分为临时节点、永久节点和顺序节点(其中顺序节点可与其他节点结合)。节点的类型在创建时即被确定,并且不能改变
1.临时节点:生命周期依赖于创建它们的会话,一旦会话结束,即会被删除,并且,临时 节点不允许拥有子节点
2.永久节点:只有在客户端执行删除操作时,它们才能被删除
3.顺序节点:顺序节点可以使持久或临时的,当一个新的Znode被创建伟一个顺序节点时, Zookeeper通过将10位序列号附加到原始名称来设置Zonde路径

4.Watches 监视器
客户端可以在节点上设置watch,即监视器。当节点状态发生改变时,将会触发watch的对应操作。当watch被触发时,Zookeeper将会向客户端发送且仅发送一条通知

5.集群中的角色

 在ZooKeeper集群当中,集群中的服务器角色有两种Leader和Learner,Learner角色又分为Observer和Follower,具体功能如下:

 Leader(领导者)为客户端提供读和写的服务,负责投票的发起和决议,更新系统状态。

 Follower(跟随者)为客户端提供读服务,如果是写服务则转发给Leader。在选举过程中参与投票。

 Observe(观察者)为客户端提供读服务器,如果是写服务则转发给Leader。不参与选举过程中的投票,也不参与“过半写成功”策略。在不影响写性能的情况下提升集群的读性能。此角色于zookeeper3.3系列新增的角色。

  client(客户端)连接zookeeper服务器的使用着,请求的发起者。独立于zookeeper服务器集群之外的角色。

  领导者(leader),负责进行投票的发起和决议,更新系统状态

  学习者(learner),包括跟随者(follower)和观察者(observer),

  客户端(client),请求发起方

Observer机制
Observer和follower在一些方面是一样的。详细点来讲,他们都向leader提交proposal。但与follower不同,observer不参与投票的过程。它简单的通过接收leader发过来的INFORM消息来learn已经commit的proposal。因为leader都会给follower和observer发送INFORM消息,所以它们都被称为learner。
因为observer不会接收proposal并参与投票,leader不会发送proposal给observer。leader发送给follower的commit消息只包含zxid,并没有proposal本身。所以,只发送commit消息给observer则不会让observer得知已提交的proposal。这就是使用INFORM消息的原因,此消息本质上是一个包含了已被commit的proposal的commit消息。
使用observer模式的一个主要的理由就是对读请求进行扩展。通过增加更多的observer,可以接收更多的请求的流量,却不会牺牲写操作的吞吐量。注意到写操作的吞吐量取决于quorum的size。如果增加更多的server进行投票,quorum会变大,这会降低写操作的吞吐量。然而增加observer并不会完全没有损耗,每一个新的observer在每提交一个事务后收到一条额外的消息,这就是前面提到的INFORM消息。这个损耗比起加入follower来投票来说损耗更少。
使用observer的另一个原因是跨数据中心部署。把participant分散到多个数据中心可能会极大拖慢系统,因为数据中心之间的网络的延迟。使用observer的话,更新操作都在一个单独的数据中心来处理,并发送到其他数据中心,让其他数据中心的client消费数据。阿里开源的跨机房同步系统Otter就使用了observer模式,可以参考。
注意observer的使用并无法完全消除数据中心之间的网络延迟,因为observer不得不把更新请求转发到另一个数据中心的leader,并处理INFORM消息,网络速度极慢的话也会有影响,它的优势是为本地读请求提供快速响应。

ZooKeeper的选举机制
在这里插入图片描述
全新启动的集群:

以一个简单的例子来说明整个选举的过程.

假设有五台服务器组成的zookeeper集群,它们的id从1-5,那半数以上就是3台,同时它们都是最新启动的,也就是没有历史数据,在存放数据量这一点上,都是一样的.假设这些服务器依序启动,来看看会发生什么。

  1. 服务器1启动,此时只有它一台服务器启动了,它发出去的报没有任何响应,所以它的选举状态一直是LOOKING状态

  2. 服务器2启动,它与最开始启动的服务器1进行通信,互相交换自己的选举结果,由于两者都没有历史数据,所以id值较大的服务器2胜出,但是由于没有达到超过半数以上的服务器都同意选举它(这个例子中的半数以上是3),所以服务器1,2还是继续保持LOOKING状态.

  3. 服务器3启动,根据前面的理论分析,服务器3成为服务器1,2,3中的老大,而与上面不同的是,此时有三台服务器选举了它,所以它成为了这次选举的leader.

  4. 服务器4启动,根据前面的分析,理论上服务器4应该是服务器1,2,3,4中最大的,但是由于前面已经有半数以上的服务器选举了服务器3,所以它只能接收当小弟的命了.

  5. 服务器5启动,同4一样,当小弟.

非全新集群的选举机制(数据恢复)

当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的Server都恢复到一个正确的状态。Zk的选举算法有两种:一种是基于basic paxos实现的,另外一种是基于fast paxos算法实现的。系统默认的选举算法为fast paxos。先介绍basic paxos流程:

1 .选举线程由当前Server发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的Server;

2 .选举线程首先向所有Server发起一次询问(包括自己);

3 .选举线程收到回复后,验证是否是自己发起的询问(验证zxid是否一致),然后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(id,zxid),并将这些信息存储到当次选举的投票记录表中;

  1. 收到所有Server回复以后,就计算出zxid最大的那个Server,并将这个Server相关信息设置成下一次要投票的Server;

  2. 线程将当前zxid最大的Server设置为当前Server要推荐的Leader,如果此时获胜的Server获得n/2 + 1的Server票数, 设置当前推荐的leader为获胜的Server,将根据获胜的Server相关信息设置自己的状态,否则,继续这个过程,直到leader被选举出来。

通过流程分析我们可以得出:要使Leader获得多数Server的支持,则Server总数必须是奇数2n+1,且存活的Server的数目不得少于n+1.

每个Server启动后都会重复以上流程。在恢复模式下,如果是刚从崩溃状态恢复的或者刚启动的server还会从磁盘快照中恢复数据和会话信息,zk会记录事务日志并定期进行快照,方便在恢复时进行状态恢复。选主的具体流程图如下所示:

在这里插入图片描述
fast paxos流程是在选举过程中,某Server首先向所有Server提议自己要成为leader,当其它Server收到提议以后,解决epoch和zxid的冲突,并接受对方的提议,然后向对方发送接受提议完成的消息,重复这个流程,最后一定能选举出Leader。其流程图如下所示:
在这里插入图片描述

消息同步
在这里插入图片描述
在zookeeper集群中新的leader选举成功后,leader会将自身提交的最大proposal的事 务ZXID发送给其他follower节点。Follower及诶单会根据leader的消息进行回退或数据 同步操作,最终保证集群中所有节点的数据副本保持一致。

每选举出一个新的leader,新的leader就从本地事物日志中取出ZXID,然后解析出高 32位的epoch编号,进行加1,再将低32位的全部设置为0;以此来保证了ZXID的唯 一性且是保证递增的

同步策略:

SNAP :如果Follower数据太老,Leader将发送快照SNAP指令给Follower同步数据;

DIFF :Leader发送从Follolwer.lastZXID到Leader.lastZXID议案的DIFF指令给Follower 同步数据;

TRUNC :当Follower.lastZXID比Leader.lastZXID大时,Leader发送从Leader.lastZXID到 Follower.lastZXID的TRUNC指令让Follower丢弃该段数据;

应用
命名服务:

在zookeeper的文件系统里创建一个目录,即有唯一的path。在我们使用tborg无法确定上游程序的部署机器时即可与下游程序约定好path,通过path即能互相探索发现。

集群管理和master选举:

   1、所有机器约定在父目录下创建临时目录节点,然后监听父目录节点的子节点变化消息,一旦子节点变化,通知客户端

   2、创建临时节点,一旦客户端和服务器的会话结束或过期,该节点就会消失

数据发布和订阅:

   发布者将数据发布到zk节点上,供订阅者获取数据,实现配置信息的集中式管理和动态更新。

   基于watches监控节点及子节点的数量改变实现

分布式锁:

   基于zookeeper为我们保证了数据的强一致性。锁服务可以分为两类,一种是保持独占,另一种是控制时序。

   保持独占基于临时节点实现;

   控制时序基于临时顺序节点实现。

ZooKeeper的其他问题
选举过程速度很慢

这是一个很难从理论分析上看到的弱点,网络实际上常常是会出现隔离等不完整状态的,而zookeeper对那种情况非常敏感。一旦出现网络隔离,zookeeper就要发起选举流程。zookeeper的选举流程通常耗时30到120秒,期间zookeeper由于没有master,都是不可用的。对于网络里面偶尔出现的,比如半秒一秒的网络隔离,zookeeper会由于选举过程,而把不可用时间放大几十倍。

zookeeper的性能是有限的

典型的zookeeper的tps大概是一万多,无法覆盖系统内部每天动辄几十亿次的调用。因此每次请求都去zookeeper获取业务系统master信息是不可能的。因此zookeeper的client必须自己缓存业务系统的master地址。因此zookeeper提供的‘强一致性’实际上是不可用的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值