CAP
一致性(Consistency):同一个数据在集群中的所有节点,任意同一时刻是否具有同样的值。
可用性(Availability):集群中部分节点故障后,集群整体是否还能处理客户端请求。
分区容忍性(Partition tolerance):是否允许数据的分区,意思是指是否允许集群中的节点之间无法通信。
CAP定理指出,一个系统不可能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition-Tolerance。
如果在分布式系统里,P就有可能发生,也即P是我们要容忍的,CA才是我们要去权衡的。当然在没有发生P的情况下,是能够实现完美的C和A的。
Zookeeper提供的一致性是弱一致性。主要用来做分布式协调,是个AP系统。
首先数据的复制有如下规则:zookeeper确保对znode树的每一个修改都会被复制到集合体中超过半数的机器上。那么就有可能有节点的数据不是最新的而被客户端访问到。并且会有一个时间点,在集群中是不一致的。但是实时的一致性可以由客户端通过调用调用sync()方法来自己保证。
角色
Zookeeper集群是由一组Server节点组成,Server节点中存在一个角色为Leader的节点,其他节点都为Follower。客户端可以和集群中的任一Server建立连接,当读请求时,所有Server都可以直接返回结果;当请求为数据变更请求时,Follower会将请求转发给Leader节点,Leader节点接收到数据变更请求后,首先会将变更写入本地磁盘,以作恢复,当持久化完毕后才会将变更写入内存,并将变更后的数据同步到各个Follower(leader会广播事务,只要有超过半数节点写入成功,该写请求就会被提交。
文件系统
ZooKeeper提供的命名空间类似于标准文件系统,名称是以斜杠(/)分隔的路径元素序列。
命名空间中的每个节点都有唯一的路径标识。
每个节点(znode)都可以持有数据与子节点(目录),存储的数据,都以原子方式进行读取与写入。
ZAB协议(Zookeeper Atomic Broadcast)
对paxos的改进
恢复模式:
当Zookeeper集群启动或Leader崩溃时,就进入到该模式。该模式需要选举出新的Leader,选举算法基于paxos或fastpaxos
广播模式:
Leader选举完毕后,Leader需要与Follower进行数据同步。
Leader服务器负责将一个客户端事务请求转换成一个事务Proposal(提议),并将该Proposal分发给集群中所有的Follower服务器。之后Leader服务器需要等待所有的Follower服务器的反馈,一旦超过半数的Follower服务器进行了争取的反馈后,那么Leader就会再次向所有的Follower服务器分发Commit消息,要求他们将前一个Proposal进行提交。
Leader服务器会为每个事务请求生成对应的Proposal来进行广播,并且在广播事务Proposal之前,Leader服务器会首先为这个事务分配一个全局单调递增的唯一ID,称之为事务ID(即ZXID)。每个事务必须按照先后顺序进行排序与处理。(ZXID是一个64为的数字,其中低32位是一个简单的单调递增的计数器,针对客户端每一个事务请求,计数器加1;而高32位则代表Leader周期epoch的编号,每个当选产生一个新的Leader服务器,就会从这个Leader服务器上取出其本地日志中最大事务的ZXID,并从中读取epoch值,然后加1,以此作为新的epoch,并将低32位从0开始计数。当一个包含了上一个Leader周期中尚未提交过的事务的服务器启动时,肯定无法成为Leader,因为在当前集群中肯定包含一个更高的epoch的事务)
Leader服务器会为每一个Follower服务器都各自分配一个单独的队列,然后将需要广播的事务依次放进队列中,并且按照FIFO的策略进行消息发送。每个Follower服务器在接受到这个事务之后,都会首先将其以事务日志的形式写入本地磁盘当中,然后返回一个ACK给Leader服务器。当Leader服务器接收到超过半数Follower的ACK响应后,就会广播一个Commit消息给所有的Follower通知它们进行事务提交,同时Leader自身也会完成对事务的提交。
特性
- 顺序一致性,客户端的更新将按照他们发送的顺序执行;
- 原子性,更新成功或失败,没有中间状态;
- 单一系统映像,无论客户端连接的是哪一台服务器,它们看到的服务视图都是相同的;
- 可靠性,一旦更新成功,它将一直持续到被下一个客户端更新覆盖;
- 及时性,客户端看到的系统视图,在一定时间范围内保证是最新的。
缺点
节点内容长度有限,只能存储一些比较小的统计信息。节点内容长度过长是,会被截断。
数据持久化对磁盘要求较高,要保证服务,通常数据操作日志目录和snapshot目录需要单独放在一个磁盘中,以免影响数据备份、持久化速度。
API
- 创建(creat),在目录树中某个位置创建一个节点;
- 删除(delete),删除一个节点;
- 存在性检查(exists),测试节点是否存在于某个位置;
- 获取数据(get data),从节点中读取数据;
- 设置数据(set data),向节点中写入数据;
- 获取子节点(get children),检索节点的子节点列表;
- 同步(syc),等待数据传播。
常见实际应用
- 服务发现
- 配置管理
- 分布式锁
- 分布式队列
- 集群管理(Master选举