Zookeeper简单介绍
Zookeeper是为了解决大型分布式系统的一系列问题而开发的一套协调服务,它将复杂且容易出错的分布一致性服务封装起来,构成了一个高效可靠的原语集,并以简单易用的接口提供给用户使用。它提供了发布/订阅、分布式协调/通知、配置管理、集群管理、主从协调、分布式锁等功能。
要明白Zookeeper的功能,先了解下分布式系统和这样的系统遇到的问题
分布式系统
硬件/软件组件分布在不同的计算机上,彼此之间通过消息进行协调和通信的系统即称为分布式系统
分布式系统的特点
分布性 分布式系统的布置在不同的服务器、不同的机架甚至不同的机房、不同的城市,它的物理位置很分散,而且可能由于环境因素随时发生变化
对等性 分布式系统无主从之分,每台服务器都是相对公平的提供服务,这样方便实现数据及服务的高可用
并发性 分布式系统可能出现同时对同一份数据进行操作的情况
缺乏全局时钟 各个服务之间的时间先后顺序很难定义
故障随时发生 由于系统服务器众多,故障也就随时有可能发生
分布式系统的问题
通信异常 由于分布式系统分布式的特点,网络不可避免的会出现问题
网络分区 俗称脑裂,由于分布式系统部分服务器的延迟,集群中只有部分节点能处理请求,而这样就有可能造成断网的节点也在处理请求,而断网的节点间可能构成了新的分布式系统对外提供服务,这样就导致了数据不一致
三态 单机系统对一个请求的处理有成功、失败两种很明确的状态,但分布式系统还可以有超时状态
节点故障
分布式系统-CAP定理
CAP即Consistency(一致性)、Availability(可用性)、Partition tolerance(分区容错性),CAP定理指出:任何系统 不可能同时满足上述三个特性,最多只能满足其中两项
而分区容错性对于分布式系统来说是必须解决的问题,因而对于系统的优化主要集中在一致性和可用性两个方面
Zookeeper使用了最终一致性来使一致性和可用性达到了平衡,它在在解决分区容错性和可用性的同时,保证数据达到最终一致性
Zookeeper特性
最终一致性 系统数据经过一定时间后,最终能达到一致
顺序性 从同一个客户端发起的事务请求,最终会严格地按照其发送顺序被应用到Zookeeper中
可靠性 一旦服务器成功应用一个事务并完成了客户端的响应,那么该事务所引起的服务端状态变更会一直被保留下去
实时性 不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,需要在读数据前调用sync()接口
原子性 一次数据更新要么成功,要么失败,没有中间状态
单一视图 无论客户端连接到哪台服务器,看到的数据模型都是一致的
Zookeeper的架构
zookeeper总体架构Zookeeper角色简介
Leader : 从所有的follower中选举出来,为客户端提供读写服务及发起投票和决议,处理事务请求,更新系统状态
Follower: Leaner角色的一种,负责客户端的读请求服务,如果收到写请求,则转发给Leader,同时负责选举
Observer:Leaner角色的一种,负责客户端的读请求服务,将客户端的写请求转发给Leader,但不负责选举,Observer存在的目的是为了扩展系统,提高读写速度。
Client: 请求发起方
Zookeeper写入
数据写入的核心算法:ZAB算法
Zookeeper写入图示1. 客户端向Follower发送写请求
2. Follower收到客户端的写请求后,将写请求发送给Leader
3.Leader接收到以后开始发起投票并通知Follwer进行投票
4.Follwer把投票结果发送给Leader
5.Leader将结果汇总后如果需要写入,则开始写入同时把写入操作通知给Leader,然后commit;
6.Follwer把请求结果返回给Client
Zookeeper选举简介
服务器四种状态
LOOKING :寻找leader状态,处于该状态需要进入选举流程
LEADING: 领导者状态,Leader已经选举出来,表明当前服务角色为Leader
FOLLOWING: 跟随者状态,Leader已经选举出来,表明当前服务角色为Follower
OBSERVER: 观察者状态,表明当前服务角色Observer
事务ID:用ZXID表示,为一个64位数字,由Leader统一分配,全局唯一,不断递增
选举(全新启动)
每个Server发出一个投票,内容为(myid,ZXID)(两台机器启动)
接收每个Server的投票
处理投票(与自己的广播消息进行对比,事务ID、myid等)
统计投票
改变服务器状态
选举(运行期间,Leader挂)
与全新启动状态类似
数据模型Znode
Zookeeper特有的数据节点,视图结构类似于Linux文件系统,没有目录和文件的概念
Znode是Zookeeper中数据的最小单元
Znode上可以保存数据通过挂载子节点构成一个树状的层次化命名空间
Znode树的根由“/”开始
Znode树结构Znode的生命周期取决于其节点类型
节点类型
持久节点
临时节点
顺序节点
组合节点
持久节点
持久顺序节点
临时节点(不允许在临时节点中创建子节点,临时节点的生命周期和客户端会话绑定,如果客户端与会话失效,节点会被Zookeeper自动删除,会话由客户端与zookeeper通过心跳保持周期性联系)
临时顺序节点
Znode版本
版本类型
dataVersion:当前数据节点的版本号
cVersion:当前数据节点子节点的版本号
aVersion:当前数据节点ACL权限变更版本号
如何保证分布式数据原子性操作
悲观锁 事务执行的整个过程中对数据进行加锁
乐观锁 事务进行更新/提交之前对数据进行检查,如果数据有其他数据进行修改,则回滚,如果没有,则提交(适合数据并发量不大的情况)
zookeeper中使用version实现乐观锁的写入校验:
// 获取当前请求的Version
version = setDataRequest.getVersion();
// 获取当前服务器上该数据的最新Versionint
currentVersion = nodeRecord.stat.getVersion();
if(version != -1 && version != currentVersion) {
throw new KeeperException.BadVersionException(path);
}
version = currentVersion + 1;
Znode状态
Znode状态Znode监听机制
Znode监听客户端在集群中注册监听事件,集群中的WatchManager存储此监听,如果监听事件发生,则执行相应的回调函数
Zookeeper的应用场景
统一命名服务
对应用/服务进行统一命名,便于识别不同服务
按照层次结构组织服务/应用名称 可将服务名称及地址信息写到Zookeeper上,客户端通过Zookeeper获取可用服务列表
全局唯一ID 依靠Zookeeper的顺序节点可以轻松生成全局唯一ID
配置管理
配置信息写入Zookeeper的一个Znode上;
各节点监听Znode
Znode数据变化,通知各节点更新
集群管理
实时掌握每个节点的状态 将节点信息写入到一个Znode上,监听这个Znode可获取它的实时状态变化
分布式锁
Zookeeper强一致 多个客户端在Zookeeper上创建相同的Znode,只有一个创建成功
锁的独占性 多个客户端同时在Zookeeper上创建相同的Znode,创建成功的那个客户端得到锁,其他客户端等待
锁的时序 各个客户端在某个Znode下创建临时znode(类型为CreateMode.EPHEMERAL_SEQUENTIAL),这样该Znode可掌握全局访问时序
分布式队列
先入先出队列
同步队列 当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达,比如一个聚合计算开始之前需要并行计算的很多子任务全部完成才能进行,可以为这个聚合计算创建一个Znode,同时监听这个Znode,其他并行子任务在这个Znode下创建临时节点,每次Znode都会发出通知,接收到通知统计子节点个数,直到达到所有的子任务数
Zookeeper的介绍就先这些,如有疏漏,敬请指正