ZooKeeper论文笔记.18205343
概要
是什么:ZooKeeper是一个分布式系统的基础构件(协调内核),分布式应用(如RocketMQ)可以使用ZooKeeper来处理分布式系统协同的各个方面,比如可以使用它来实现leader选举、分布式锁等等,分布式应用可以使用它暴露的API实现各种类型的协同原语(考虑Java中的AQS)。它让分布式应用的设计者无需考虑分布式系统中各种繁杂的问题,如网络分区、节点故障等等,专注于实现应用的逻辑。
API结构:ZooKeeper提供给应用的API是类似文件系统的层级结构对象,并且这种对象是无等待的(wait-free)。
ordering:单客户端所有操作FIFO,所有客户端的所有写入操作全局线性(Linearizable)。
管道设计:ZooKeeper在对请求的处理上使用了管道设计,这使得客户端的请求可以异步化,并且天然满足单客户端操作的FIFO特性
ZAB:基于leader的原子广播协议,用于处理所有的写请求。可以将它理解为一种只针对于写请求的复制状态机(思考raft),也就是说写请求是leader处理并复制到所有follower的,而对于读请求,ZooKeeper会在节点本地处理,不管它是不是leader(但这里想要保证不back-in-time,不读到过时数据,还要有其它保证)
Watch与缓存:ZooKeeper提供了Watch机制,这使得客户端可以无需直接地管理缓存,而是会在一个内容发生改变后得到通知。这里论文中还提到了Chubby,它的设计就是让客户端直接管理缓存,在这种设计下一旦缓存发生变化,就要阻止更新,失效所有相关客户端的缓存,慢客户端或者已经失效的客户端会将更新阻塞。Chubby使用lease机制来避免永久性的阻塞,保证集群的活性。
ZooKeeper Service介绍
概览
术语:
- 客户端:使用ZooKeeper服务的用户
- 服务器:提供ZooKeeper服务的进程
- znode:ZooKeeper内存中的数据节点,以数据树(data tree)形式层次化组织。节点具有key,可以看成是数据树中的名称(思考文件名),还有一个value,客户端用它来保存用于实现协同的数据结构。比如,用ZooKeeper实现leader选举的可以在一个公知的位置存储当前leader信息。
- 会话:客户端和ZooKeeper服务器之间的通信通道,由客户端建立。具有一个超时时间,服务器在超时时间内没接到客户端的请求,会话会自动关闭,或者被客户端主动关闭。客户端可以通过会话观察反应它的一系列操作的执行结果。会话跨Zookeeper服务器持久化,因为ZooKeeper支持透明的将一个client从一个服务器移动到另一个服务器上
库:ZooKeeper客户端程序中有一个Zookeeper库在处理与ZooKeeper服务器的通信,掌管连接
两种znode:
- 常规:客户端自己负责创建并删除的znode,可以具有子节点
- ephemeral:客户端创建,可以由客户端显式删除,或当该客户端会话关闭时自动删除,不可以具有子节点
sequential标识:客户端创建节点时可以加上该选项,之后创建的节点名字会被加上一个单向递增的数字后缀。假如N是P下的一个新的子节点,ZooKeeper保证N的序列号不小于任何一个已经在P下创建过的节点的序列号
watch机制:如果客户端调用读取API时添加了一个watch标志,那么该操作正常结束,并且当返回的信息发生变化时客户端还会收到一个通知。该通知是一次性的,通知完后或者session关闭后就没了。watch通知只代表数据发生了变化,不提供任何其它保证
API
create(path, data, flags)
:创建一个路径为path
的znode,将data[]
存储进去,并且返回新znode的名字。flags
允许客户端选择znode的类型:常规、ephemeral,或者设置sequential flagdelete(path, version)
:删除路径上的znode,如果znode的version是预期的exists(path, watch)
:返回路径上的znode是否存在,可以设置watchgetData(path, watch)
:返回数据以及与znode关联的元数据(如version)。也可以设置watch,和exists
的区别是,如果znode不存在就不会设置watchsetData(path, data, version)
:写入data[]
到指定znode(只有当version是znode的当前version)getChildren(path, watch)
:获取znode的子节点名字集合sync(path)
:等待该操作开始时的全部正在进行的更新传播到当前客户端连接到的所有服务器上。path参数目前没用到
所有API具有同步和异步两个版本,ZooKeeper保证异步操作对应的callback被顺序回调
版本号用于实现条件化更新,若无需实现,传入
-1
,不会执行版本号校验
ZooKeeper保证
- Linearizable writes:所有更新ZooKeeper状态的请求都是可串行化的,并且尊重优先级
- FIFO client order:给定客户端的所有请求都保证以客户端发送的顺序执行
ZooKeeper中的Linearizability和原始的定义不太一致,官方称为A-linearizability(异步线性化)
ZooKeeper允许单客户端同时有多个未处理完成的操作(outstanding operations)发生,所以它可以选择对于这种情况不给任何保证,或给与FIFO保证,ZooKeeper选择了后者。
ZooKeeper在每一个副本本地处理读请求(无需和其它服务器通信),所以这大大加强了ZooKeeper的扩展性。