ZooKeeper主要服务于分布式系统,可以用ZooKeeper来做:统一配置管理、统一命名服务、分布式锁、集群管理。ZooKeeper使得开发人员可以实现通用的协作任务,包括选举主节点,管理组内成员关系,管理元数据等.
一.简介与基础
对分布式系统的定义为:分布式系统是同时跨越多个物理主机,独立运行的多个软件组件所组成的系统.分布式系统中的进程通信有两种选择:直接通过网络进行信息交换,或读写某些共享存储.(zookeeper选择后者)
1.1主从应用

图中所展示的就是主从的架构模式,一般在这种架构中1,主节点进程负责跟踪从节点状态和任务的有效性,并分配任务到从节点.
要实现主从模式的系统必须解决三个问题:
1.主节点崩溃:如果主节点发送错误并失效,系统将无法分配新的任务或重新分配已失败的任务.
2.从节点崩溃:如果从节点崩溃,已分配的任务将无法完成.
3.通信故障:如果主节点和从节点之间无法进行信息交换,从节点将无法得知新任务分配给它.
1.主节点失效时,需要有一个备份主节点.主节点崩溃时,备份主节点接管主要主节点的角色.新的主节点需要能够恢复到旧的主要主节点崩溃时的状态.对于主节点状态的可恢复性,不能从已经崩溃的主节点来获取信息,而需要从其他地方获取,也就是通过Zookeeper.
假如主节点有效,备份主节点却认为主节点已经崩溃(主节点负载很高,导致消息任意延迟),备份主节点将会接管成为主节点的角色,执行所有必须的程序,如果一些从节点无法与主要主节点通信,这些从节点可能会停止与主要主节点的通信,这种现象称之为脑裂(split-brain).要避免脑裂的产生
2.客户端向主节点提交任务,之后主节点将任务派发到有效的从节点中。从节点接收到派发的任务,执⾏完这些任务后会向主节点报告执⾏状态。主节点下⼀步会将执⾏结果通知给客户端。如果这个节点崩溃,那么这些任务就需要重新分配.首要需求是让主节点具有检测从节点的崩溃的能力.
3.如果⼀个任务允许多次执⾏,我们在进⾏任务再分配时可以不⽤验证第⼀个从节点是否完成了该任务。如果⼀个任务不允许,那么我们的应⽤需要适应多个从节点执⾏相同任务的可能性。
根据上面的描述,可以得到主从架构有以下需求:1.主节点选举2.崩溃检测3.组成员关系管理4.元数据管理
zookeeper的主从:https://www.cnblogs.com/shan1393/p/9479110.html

server中的数据结构是znode形式的,全局数据统一的话那每个server底下的znode都一致?(用znode实现主从,创建一个master节点,然后其他server再创建时就会报错,剩下就是task节点分配任务和assign记录)
1.在Client向Follwer发出一个写的请求
2.Follwer把请求发送给Leader
3.Leader接收到以后开始发起投票并通知Follwer进行投票
4.Follwer把投票结果发送给Leader
5.Leader将结果汇总后如果需要写入,则开始写入同时把写入操作通知给Leader,然后commit;
6.Follwer把请求结果返回给Client
Zookeeper读写机制:Zookeeper是一个由多个server组成的集群 , 一个leader,多个follower, 每个server保存一份数据副本,全局数据一致,分布式读写,更新请求转发,由leader实施。
Zookeeper的保证:更新请求顺序进行,来自同一个client的更新请求按其发送顺序依次执行,数据更新原子性,一次数据更新要么成功,要么失败,全局唯一数据视图,client无论连接到哪个server,数据视图都是一致的,实时性,在一定事件范围内,client能读到最新数据。
1.1.1选举
A提案说,我要选自己,B你同意吗?C你同意吗?B说,我同意选A;C说,我同意选A。(注意,这里超过半数了,其实在现实世界选举已经成功了。但是计算机世界是很严格,另外要理解算法,要继续模拟下去。)
接着B提案说,我要选自己,A你同意吗;A说,我已经超半数同意当选,你的提案无效;C说,A已经超半数同意当选,B提案无效。
接着C提案说,我要选自己,A你同意吗;A说,我已经超半数同意当选,你的提案无效;B说,A已经超半数同意当选,C的提案无效。
• 选举已经产生了Leader,后面的都是follower,只能服从Leader的命令。
其实谁先启动谁当头。
1.2 ZooKeeper基础
ZooKeeper中并不直接暴露原语,它暴露了一小部分调用方法组成的类似文件系统的API,以便允许应用实现自己的原语。recipes(菜谱)包括ZooKeeper操作和维护一个小型的数据节点,这些节点被称为znode,采用类似于文件系统的层级树状结构进行管理。
如上图,根节点包含了四个子节点,下面三个子节点拥有下一级节点,叶子节点存储了数据信息。
1.2.1 Znode
znode节点可能包含有数据,也可能没有。如果一个znode节点包含任何数据,那么数据存储为字节数组。字节数组的具体格式特定于每个应用的实现,并不直接提供解析的支持。
ZooKeeper的API暴露了以下方法:
create/path data:创建一个名为/path的znode节点,并包含数据data
delete/path :删除名为/path的znode
exists/path :检查是否存在名为/path的节点。
setData/path data :设置名为/path的znode的数据为data。
getData/path : 返回名为/path节点的数据信息。
getChildren/path : 返回所有/path节点的所有⼦节点列表。
注:zookeeper并不允许局部写入或读取znode节点的数据。当设置一个znode节点的数据或读取时,znode节点的内容会被整个替换或全部读取进来。
znode的不同类型
在新建znode时,还需要指定该节点的类型,不同的类型决定了znode节点的行为方式。
持久节点(persistent):持久的znode,如/path,只能通过调用delete来进行删除。即使znode的创建者不再属于应用系统时,数据也可以保存下来而不丢失。
临时节点(ephemeral):创建该节点的客户端崩溃或关闭了与zookeeper的连接时,这个节点就会被删除。如果一个从节点失效,那么会话将会过期,之后znode/workers也将自动消失。有两种情况会被删除:1.当创建该znode的客户端的会话因超时或主动关闭而中止时。2.当某个客户端主动删除该节点时。临时节点不允许有子节点
有序节点(sequential):一个有序znode节点被分配唯一的单调递增的整数。当创建有序节点时,一个序号会被追加到路径之后。例如创建/tasks/task-,分配序号之后最后该节点为/tasks/task-1
总结,znode总共有四种类型: znode⼀共有4种类型:持久的(persistent)、临时的 (ephemeral)、持久有序的(persistent_sequential)和临时有序的 (ephemeral_sequential)。
监视与通知
zookeeper通常以远程服务的方式被访问,如果每次访问znode时,客户端都需要获得节点中的内容,这样的代价就⾮常⼤。因为这样会导致更 ⾼的延迟,⽽且ZooKeeper需要做更多的操作。所以采用监视的手段,有变更再告诉你
客户端向zookeeper注册需要接受通知的znode,通过对znode设置监视点来接受通知。监视点是一个单次触发的操作,意思就是监视点会触发⼀个通知。为了接收多个通知,客户端必 须在每次通知后设置⼀个新的监视点 。
注:如果你首先设置了一个监视点,然后你发送了一个任务,你接受到了通知,在继续设置监视点之前有其他客户端发了一个新的任务,那么你就会错过这次任务,所以在设置新的监视点之前,要先去读取一下zookeeper里面的状态
ZooKeeper可以定义不同类型的通知,这依赖于设置监视点对应的通知 类型。客户端可以设置多种监视点,如监控znode的数据变化、监控znode ⼦节点的变化、监控znode的创建或删除。
版本
每一个znode都有一个版本号,随着每次数据变化而自增,setData和delete可以有条件的执行。可以以版本号作为转入参数,只有版本号与服务器一致才会成功。下图就是使用版本来阻止并行操作的不一致性
1.2.2 Zookeeper架构
ZooKeeper服务器端运⾏于两种模式下:独⽴模式(standalone)和仲裁模式(quorum)。独⽴模式⼏乎与其术语所描述的⼀样:有⼀个单独的服务器,ZooKeeper状态⽆法复制。在仲裁模式下,具有⼀组ZooKeeper服务器,我们称为ZooKeeper集合(ZooKeeper ensemble),它们之间可以进⾏状态的复制,并同时为服务于客户端的请求。
在仲裁模式下,ZooKeeper复制集群中的所有服务器的数据树 。在公共管理领域,法定⼈数是指进⾏⼀项投票所需的⽴法者的最⼩数量。⽽在ZooKeeper中,则是指为了使ZooKeeper⼯作必须有效运⾏的服务器的最⼩数量。 比如有五个zookeeper服务器,法定人数为3,只要任何三个保存,客户端就可以继续,其他两个服务器最终也将捕获到数据。
所以zookeeper的服务器数量最好为单数,因为要大于一半的服务器能工作
客户端提交给zookeeper的所有操作均关联在一个会话上。当一个会话因某种原因而中止时,临时节点会消失。 会话⽆法与当前连接的服务器继续通信时,会话就可能转移到另⼀个服务器上。ZooKeeper客户端库透明地转移⼀个会话到不同的服务器。
会话提供了顺序保障,这就意味着同⼀个会话中的请求会以FIFO(先 进先出)顺序执⾏ 。
《Zookeeper 分布式过程协同技术详解》
