ZooKeeper是个集群,内部有多个server,每个server都可以连接多个client,每个client都可以修改server中的数据

ZooKeeper可以保证每个server内的数据完全一致,是如何实现的呢?

数据一致性是靠Paxos算法保证的,Paxos可以说是分布式一致性算法的鼻祖,是ZooKeeper的基础

Paxos的基本思路


假设有一个社团,其中有团员、议员(决议小组成员)两个角色


团员可以向议员申请提案来修改社团制度


议员坐在一起,拿出自己收到的提案,对每个提案进行投票表决,超过半数通过即可生效

为了秩序,规定每个提案都有编号ID,按顺序自增


每个议员都有一个社团制度笔记本,上面记着所有社团制度,和最近处理的提案编号,初始为0

投票通过的规则:


新提案ID 是否大于 议员本中的ID,是 议员举手赞同


如果举手人数大于议员人数的半数,即让新提案生效

例如

刚开始,每个议员本子上的ID都为0,现在有一个议员拿出一个提案:团费降为100元,这个提案的ID自增为1


每个议员都和自己ID对比,一看 1>0,举手赞同,同时修改自己本中的ID为1


发出提案的议员一看超过半数同意,就宣布:1号提案生效


然后所有议员都修改自己笔记本中的团费为100元

以后任何一个团员咨询任何一个议员:"团费是多少?",议员可以直接打开笔记本查看,并回答:团费为100元

可能会有极端的情况,就是多个议员一起发出了提案,就是并发的情况

例如

刚开始,每个议员本子上的编号都为0,现在有两个议员(A和B)同时发出了提案,那么根据自增规则,这两个提案的编号都为1,但只会有一个被先处理


假设A的提案在B的上面,议员们先处理A提案并通过了,这时,议员们的本子上的ID已经变为了1,接下来处理B的提案,由于它的ID是1,不大于议员本子上的ID,B提案就被拒绝了,B议员需要重新发起提案


上面就是Paxos的基本思路,对照ZooKeeper,对应关系就是:

团员 - client

议员 - server

议员的笔记本 - server中的数据

提案 - 变更数据的请求

提案编号 - zxid(ZooKeeper Transaction Id)

提案生效 - 执行变更数据的操作

ZooKeeper中还有一个leader的概念,就是把发起提案的权利收紧了,以前是每个议员都可以发起提案,现在有了leader,大家就不要七嘴八舌了,先把提案都交给leader,由leader一个个发起提案

Paxos算法就是通过投票、全局编号机制,使同一时刻只有一个写操作被批准,同时并发的写操作要去争取选票,只有获得过半数选票的写操作才会被批准,所以永远只会有一个写操作得到批准,其他的写操作竞争失败只好再发起一轮投票