ZooKeeper 是一种分布式,开源的协同服务。分布式应用可以基于其所提供的一些特性来实现服务同步,配置维护,服务分组及命名等。zookeeper是比较简单易用的,并且使用类文件系统树状结构组织数据结构。
服务同步一直以来都是一个应用中的难点。尤其是在多线程环境中竟态条件及死锁情景极易发生的情景下。zookeeper的设计初衷就是为了减少分布式应用在服务协同方面所需要付出的成本。
ZooKeeper 很简单。ZooKeeper 允许分布式任务进程通过共享层级的命名空间(类文件系统)来实现服务协同。命名空间内部包含数据注册存储,zookeeper术语称之为znodes,这点和文件系统中的文件和文件夹很类似,所不同的是,文件系统是为了数据存储,所以一般存储于硬盘,而zookeeper的数据存储在内存,这也就保障了zookeeper系统的高吞出,低延迟。
The ZooKeeper 是一种高性能,高可用,严格有序的系统。高性能也就意味着则 zookeeper 可以用在大型,分布式应用系统。高可用则是避免了单点故障,严格有序则是实现复杂业务服务同步的基本特性。
ZooKeeper 复制。zookeeper 的目的是任务协同,同时,zookeeper自身也作为协同服务的一员参与协同。
zookeeper服务中的每个服务节点都需要有相互认知。每个节点都在内存中维护者一份zookeeper服务的实时状态信息,并且在持久化存储中保存着事务日志信息及数据镜像。只要服务中的大多数服务节点可用,那么整个服务就可认为是可用的。
每个客户端只连接到一个服务节点。客户端和zookeeper服务节点维护者一个TCP连接,用于收发请求,获取监听事件及发送心跳。如果客户端和服务节点的连接中断,客户端会重新连接zookeeper中另外一个服务节点。
ZooKeeper 是有序的。ZooKeeper 会给每一个事务打上时间戳,用以标识顺序。
ZooKeeper 很快。尤其是在以读为主的业务系统中,当读写比例为10:1时,性能优佳。
zookeeper的命名空间类似文件系统,每个命名都是以“/”分割的路径,并且唯一。
zookeeper的节点及子节点都可以存储数据,称之为znode。zookeeper节点是设计用来存储服务协同数据,包括状态信息,服务配置,位置信息等,所以节点数据通常需要很小。
Znode 以版本信息维护数据,ACL及时间戳变更。版本会随着发生的变更而增加。
节点数据的读写是原子性的,读写操作都是针对节点的所有数据。每个节点都维护者一份ACL(访问控制列表)信息用以控制数据访问。
ZooKeeper 瞬时节点,生命周期同节点创建的会话生命周期,会话结束,则节点会被删除。
ZooKeeper watch事件,客户端在zookeeper节点上设置watch,节点变化时watch被触发,然后被删除,watch触发后,客户端会收到节点变化的信息。客户端和服务节点断开后,客户端也会收到提醒。
ZooKeeper 很快并且很简单,为了实现服务复杂业务系统的目的,zookeeper提供以下保障:
ZooKeeper 的设计目标之一便是提供简便的开发接口,因此其只是支持如下操作:
概览图:
复制型数据库是一种内存型数据库,存储着zookeeper服务完整的数据。更新会被记录日志到硬盘以便用以数据恢复。写操作在被应用到内存数据库之前会被先序列化到硬盘。
zookeeper的每一个服务节点都可以作为客户端服务节点,每个客户端连接到一个服务节点来发送请求。服务节点以本地数据副本来响应客户端请求,写请求则会通过zookeeper的一致性协议来处理。
一致性协议要求客户端的所有写请求都转发到一台服务器,我们称之为领导者服务节点,其余的服务节点称之为跟随者。跟随者接收领导者提议消息,同意或拒绝并回复。消息层协议用于领导者选举及跟随者同步。
ZooKeeper 原子广播协议。原子性也就保证了追着服务节点的本地数据副本的实时性,一致性。当zookeeper服务接收到写请求时,领导者应用写请求,然后获取将数据状态作为事务消息发送到跟随者。
ZooKeeper 在读请求为主的应用中能够获得更好的性能(因为写操作涉及到数据及服务状态的同步)。
参考资料:ZooKeeper Throughput as the Read-Write Ratio Varies
如上图所示:当跟随者宕机然后快速恢复,zookeeper在期间仍能保持较高的吞吐量。更重要的是,领导者选举协议保障了服务节点的快速恢复从而避免吞吐量急剧变化,通常领导者选举耗时不超过200ms。
详细参阅:ZooKeeper Wiki.
zookeeper保障基本的CP特性。
项目地址:https://github.com/windwant/rpc-service.git | https://github.com/windwant/rmi-service.git