ZooKeeper的基本概念
- Architecture(架构)
- Hierarchical namespace(层次命名空间)
- Session(会话)
- Watches(监视)
1、架构
客户端:用于访问服务器获取服务,每个客户端定期向服务器发送消息以使服务器知道客户端是活跃的。当客户端连接时,服务器发送确认码。如果连接的服务器没有响应,客户端会自动将消息重定向到另一个服务器。
服务器:集群中的一个节点,为客户端提供服务。
服务器组:Ensemble,标识Zookeeper的一个服务器组织,最小服务器数量为3台。
首领:Leader,就像总统是通过选举的办法产生一样,Leader服务器节点控制其他节点或者是分配任务。一般读任务都不归他管,写操作会由它决策。负责响应所有对ZooKeeper状态变更的请求。
下属:Follower,就像领导的下属一样,从服务器的职责就是遵守Leader的指令。除了响应本服务器上的读请求外,follower还要处理leader的提议,并在leader提交该提议时在本地也进行提交。
观察者:Observer,如果ZooKeeper集群的读取负载很高,可以设置一些observer服务器,以提高读取的吞吐量。与Follower类似,但是不会持久化,不参与选举,不响应提议,也不计入服务器成员数中。
2、层次命名空间
右图是ZooKeeper的分层名字空间的示意图
|
下面详细说明一下节点的含义。以下部分内容出自:
node既可以有其他子znode,又可以存放数据(严格说是必须存放数据,真没有的话得给个“”),znode被用来存储Byte级或KB级的数据,如状态信息、配置信息、位置信息等,因此znode可存放数据量的最大值默认被设为1MB,请注意,该值不仅计算数据的Byte数,所有子节点的名字也要折算成Byte数计入,因此znode的子节点数也不是无限的。改大这个参数可以存储更多数据或包含更多子znode,但我非常不建议这样做,因为这与ZooKeeper的设计目的相悖,只有数据足够小,才能保证ZooKeeper的高读取性能。如果要存储大量数据,有的是其他解决方案。
除了数据外,znode还管理了其他一些元数据, 存储在 stat对象( 一个stat仅提供一个znode的元数据。它由版本号,操作控制列表(ACL),时间戳和数据长度组成。 ) 中:
- 版本号:znode的数据每次更新时,该版本号递增。当客户端请求该znode时,数据和版本号会一起发回。另外,当znode重建时版本号会被重置,但很多时候这是巨坑的来源,比如:客户端执行了’set /test “testdata” 1’,即指定版本1写/test节点,之后该znode被删除重建,数据默认置为“”,版本号还是1,此时客户端请求时虽然该版本号仍然存在,但已经是错误的数据了。
- ACL:即Access Control List,ACL基本上是访问znode的认证机制。它管理所有znode读取和写入操作。用来限定哪些账号可以操作该znode。ZooKeeper内置了4种ACL模式,第1种是any,即不鉴权;第2种是super,即不受任何ACL约束的管理员模式;第3种是digest,使用用户名和密码进行认证;第4种是SASL,通常使用Kerberos协议来认证,但Kerberos也是个大坑,并且对性能也有一定影响。
- 时间戳:其实就是zxid,存储该znode创建或修改时的时间戳,用于缓存验证或协调更新等。Zxid 是唯一的,并且为每个事务保留时间,以便你可以轻松地确定从一个请求到另一个请求所经过的时间。
- 数据长度:存储在znode中的数据总量是数据长度。你最多可以存储1MB的数据。
Znode的类型
Znode被分为持久(persistent)节点,顺序(sequential)节点和临时(ephemeral)节点。
- 持久节点 默认情况下,除非另有说明,否则所有znode都是持久的。持久节点只能用delete来删除。
- 临时节点 - 客户端活跃时,临时节点就是有效的。当客户端与ZooKeeper集合断开连接时,临时节点会自动删除,常用来检测会话的有效性。因此,只有临时节点不允许有子节点。如果临时节点被删除,则下一个合适的节点将填充其位置。临时节点在leader选举中起着重要作用。
- 顺序节点 - 顺序节点可以是持久的或临时的。当一个新的znode被创建为一个顺序节点时,ZooKeeper通过将10位的序列号附加到原始名称来设置znode的路径。例如,如果将具有路径 /myapp 的znode创建为顺序节点,则ZooKeeper会将路径更改为 /myapp0000000001 ,并将下一个序列号设置为0000000002。如果两个顺序节点是同时创建的,那么ZooKeeper不会对每个znode使用相同的数字。顺序节点在锁定和同步中起重要作用。
3、Sessions(会话)
会话对于ZooKeeper的操作非常重要。会话中的请求按FIFO顺序执行。一旦客户端连接到服务器,将建立会话并向客户端分配会话ID 。
客户端以特定的时间间隔发送心跳以保持会话有效。如果ZooKeeper集合在超过服务器开启时指定的期间(会话超时)都没有从客户端接收到心跳,则它会判定客户端死机。
会话超时通常以毫秒为单位。当会话由于任何原因结束时,在该会话期间创建的临时节点也会被删除。
会话的状态:
- connecting:一旦客户端开始创建Zookeeper对象,那么客户端状态就会变成CONNECTING状态
- connected:连接成功后,客户端状态变为CONNECTED
- reconnecting :由于断网或其他原因,客户端与服务端之间会出现断开情况,Zookeeper客户端会自动进行重连服务
- reconnected:直到重新连上服务端后,状态又变为CONNECTED
- close:会话超时、权限检查或是客户端主动退出程序等情况,客户端的状态就会直接变更为CLOSE状态。
以下内容参考文章:
Session是Zookeeper中的会话实体,代表了一个客户端会话,其包含了如下四个属性
1. sessionID。会话ID,唯一标识一个会话,每次客户端创建新的会话时,Zookeeper都会为其分配一个全局唯一的sessionID。
2. TimeOut。会话超时时间,客户端在构造Zookeeper实例时,会配置sessionTimeout参数用于指定会话的超时时间,Zookeeper客户端向服务端发送这个超时时间后,服务端会根据自己的超时时间限制最终确定会话的超时时间。
3. TickTime。下次会话超时时间点,为了便于Zookeeper对会话实行"分桶策略"管理,同时为了高效低耗地实现会话的超时检查与清理,Zookeeper会为每个会话标记一个下次会话超时时间点,其值大致等于当前时间加上TimeOut。
4. isClosing。标记一个会话是否已经被关闭,当服务端检测到会话已经超时失效时,会将该会话的isClosing标记为"已关闭",这样就能确保不再处理来自该会话的心情求了。
会话管理机制是通过分桶策略来进行的的,以便对会话进行不同区块的管理和统一的处理。将会话分配到不同的桶依据是会话的超时时间。服务器循环向客户端发送ping以更新超时时间。
4、Watches(监视)
监视是一种简单的机制,使客户端收到关于ZooKeeper集合中的更改的通知。客户端可以在读取特定znode时设置Watches。Watches会向注册的客户端发送任何znode(客户端注册表)更改的通知。
Znode更改是与znode相关的数据的修改或znode的子项中的更改。只触发一次watches。如果客户端想要再次通知,则必须通过另一个读取操作来完成。当连接会话过期时,客户端将与服务器断开连接,相关的watches也将被删除。
以下的三个变革可以触发watch:
- znode数据的改变,如使用setData操作在znode域中写入新数据。
- znode子节点的改变,如使用delete操作删除znode的子节点。
- znode的创建或删除。
关于watches和通知,Zookeeper确保维护一下几点:
- Zookeeper保证所有的watch都是按先进先出(FIFO)排序,通知也是按顺序发送。
- 同一个znode的第二次修改发生之前watch的通知就一定发送给客户端。
- watch事件的顺序依赖于Zookeeper服务所能检测到的数据更新的顺序。