几个用于协同的原语经常被跨多个应用所共享。因此,一种设计用于协同的服务就是提供一组原语,通过为每个原语创建实例来暴露调用接口,同时直接操作这些这些实例。比如,我们说分布式锁组成了一个重要的原语,并且提供了创建、获取和释放锁的调用。

    然而,这样的设计有几个重要的缺陷。第一,我们要么在使用之前就列出一个原语的详细清单,要么继续扩展API来引入新的原语。第二,这种设计不能为那些使用这个服务的应用提供足够的灵活性以实现最适合它们的原语。

    我们因此为Zookeeper选择了一条不一样的路。Zookeeper不直接提供原语。相反的,它提供一个像文件系统的API,由一个小规模的调用组成,这些调用使得应用能够实现他们自己的原语。我们通常使用recipes来表示这些原语的实现。Recipes包括Zookeeper的操作,这些操作能操控小的被称之为znode的数据节点。这些数据节点以树形的结构进行组织,像文件系统一样。Figure 2-1详细的描述了一个znode树。

    Zookeeper基础 - 图1

    图2-1. Zookeeper数据树示例

    数据的确实经常暗含了关于一个znode重要的信息。在master-worker的例子中,举个例子,缺少master节点(以下znode均译为节点)意味着当前没有master被选举出来。图2-1包含了少数几个其他的节点,它们在master-worker的配置中可能很有用。

    • \/workers节点是系统中所有可用的worker的父节点。图2-1表明有一个worker(foo.com:2181)可用。如果worker变得不可用,那么它的节点应用从\/workers中删除。
    • \/tasks节点是所有被创建和等待被worker执行的任务的父节点。master-worker应用的客户端在\/tasks下新增子节点用来代表新的任务,同时等待代表任务状态的节点。
    • \/assigin节点是所有指派关系的父节点。当一个master指派一个任务给一个worker,它会在\/assign下面新增一个子节点。