Zookeeper文档摘要

分布式共识一直以来是被广泛讨论的话题,每一个分布式系统都会涉及到“共识问题”——对某一个值或者状态达成共识。有些中间件(例如redis)自己写了分布式共识的实现方式,有些(例如kafka)则直接利用zookeeper或者etcd解决共识问题。在java的生态环境中,zookeeper是分布式共识的实际标准,这边博文就来了解下zookeeper相关的知识。

zookeeper的自我定位:协调分布式应用的组件。他把分布式应用必做一个动物园,而自己则是动物园的keeper。zookeeper提供了一套简单的指令,分布式系统可以基于此实现更高等级的功能,例如:同步,分布式配置,分组,命名服务。分布式共识比较难实现,而zookeeper的目的就是让大家不需要自己造分布式共识的轮子。

设计目标

  • simple 类似文件系统的层级关系。基于内存——高吞吐、低延迟
  • replicated 数据有多副本——高可用。node保存状态、transaction log、快照
  • orderd 用ID标记每一次变更(transaction),这种顺序可以用来实现更高的抽象,例如同步原语。
  • fast 适合读多写少的应用,例如读写比10:1,读写比越高性能越好。10:1以下不建议使用

数据模型和层级的命名空间

zookeeper的命名空间很像文件系统,一个znode的路径是以“/”分割的name组成的。与文件系统不同的是,一个znode既是“文件”又是“文件夹”,既可以包含数据,又可以有子节点。因为zookeeper是涉及来保存协作信息的,所以节点下的信息通常比较小,例如状态、配置、location这些,大约都在nb-nkb范围内。

znode的数据结构包含版本号(标识数据变更、ACL变更、时间戳),以此实现缓存验证和协作更新(达成共识)。每次数据变更,这个版本号会增加。获取数据时,会同时获取版本号。

读写单个znode的数据是原子的,要么读写所有数据,要么全部失败。每个znode都有一个ACL(Access Controll list)控制哪些客户端能做什么。

zookeeper也有临时节点,临时节点的生命周期在与客户端session断开的时候结束,并被删除

watch机制

支持watch机制,当数据变更时,zookeeper可以向client发送变更通知,然后删除这个watch。如果client和zookeeper断开,client会收到一个通知。

3.6版本后:

  • watch可以是永久的:发送变更,并且不删除这个watch
  • watch可以是递归的:监听该znode及其任何子节点的变化

承诺

  • 顺序一致性:client发来的变更会顺序地生效
  • 原子的: updates要么全部成功,要么全部失败
  • 单一系统镜像: 一个client如果连接断开,连上新的zookeeper,看到的东西也是一样的
  • 可靠的: 一旦update被采纳,不会丢失直到有新的update
  • 及时性:update被采纳的延时不会很长,保证client能及时地看到最新的数据

简单的api

  • create : creates a node at a location in the tree
  • delete : deletes a node
  • exists : tests if a node exists at a location
  • get data : reads the data from a node
  • set data : writes data to a node
  • get children : retrieves a list of children of a node
  • sync : waits for data to be propagated

开发者指南

zookeeperProgrammers.html

PAXOS两阶段提交

# 正常流程
prepare(N)  # N>任何n
promise(N,n,v)

propose(N,?) # 如果上面的v!=null,取上面的v;如果v==null,可以自定义
accept(N,?)

basic-paxos