参考文档
http://www.crazyant.net/2120.html
zookeeper中的相关概念
zookeeper中有如下角色:
- 领导者(leader),负责进行投票的发起和决议,更新系统状态。只有一个。由系统启动时依照Paxos算法选举产生。
- 学习者(learner),包括跟随者(follower)和观察者(observer)
- follower用于接受客户端请求并想客户端返回结果,在选主过程中参与投票
- Observer可以接受客户端连接,将写请求转发给leader,但observer不参加投票过程,只同步leader的状态,observer的目的是为了扩展系统,提高读取速度(3.3.0后版本提供)
在zookeeper集群中,follower+leader应该为奇数。这是因为,如果5个server,最多允许2个server刮掉,6个server也最多允许两个2server刮掉。没必要多增加一个。
Paxos
Paxos 一致性协议可以说是一致性协议研究的起点,也以难以理解闻名。笔者就不尝试解释这个算法,只是说明这个算法的目的。
一个分布式系统如何就某个值(决议)达成一致。
问题的故事如下:
希腊岛屿Paxon 上的执法者(legislators,后面称为牧师priest)在议会大厅(chamber)中表决通过法律,并通过服务员传递纸条的方式交流信息,每个执法者会将通过的法律记录在自己的账目(ledger)上。问题在于执法者和服务员都不可靠,他们随时会因为各种事情离开议会大厅,并随时可能有新的执法者进入议会大厅进行法律表决,使用何种方式能够使得这个表决过程正常进行,且通过的法律不发生矛盾。
Paxos核心思想:当多数Server写成功,则任务数据写成功
zab协议是paxos协议的一种改进。
client写请求执行过程
- 1.在Client向Follwer发出一个写的请求
- 2.Follwer把请求发送给Leader
- 3.Leader接收到以后开始发起投票并通知Follwer进行投票
- 4.Follwer把自己投票结果发送给Leader
- 5.Leader将结果汇总后如果需要写入,则开始写入同时把写入操作通知给所有Follwer,然后commit;
- 6.Follwer把请求结果返回给Client
读
如果是对zk进行读取操作,读取到的数据可能是过期的旧数据,不是最新的数据。
如果一个zk集群有10000台节点,当进行写入的时候,如果已经有6K个节点写入成功,zk就认为本次写请求成功。但是这时候如果一个客户端读取的刚好是另外4K个节点的数据,那么读取到的就是旧的过期数据。
CAP原理
对于zookeeper来说,它实现了A可用性、P分区容错性、C中的写入强一致性,丧失的是C中的读取一致性。这也是为什么由观点认为Eureka比ZooKeeper更适合做服务注册中心。因为,Eureka是基于AP原则构建的,而ZooKeeper是基于CP原则构建的
分布式事务
2pc,3pc和paxos,和zookeeper的zab,都是分布式事务的一种努力。
脑裂
指一个【分布式集群】分裂成两个独立集群对外分别提供的服务的情况。比如说缓存集群也会有脑裂问题。
如一个ZK集群部署于两个机房
如果机房网络断开,就会出现
为了防止这个事情出现,必须要求过半节点投票才能选出来新的Leader。
节点
zookeeper中有四种节点:
- 持久节点(PERSISTENT) 该数据节点被创建后,就会一直存在于zookeeper服务器上,直到有删除操作来主动删除这个节点。
- 持久顺序节点(PERSISTENT_SEQUENTIAL)
- 临时节点(EPHEMERAL) 经常用于服务注册系统。临时节点的生命周期和客户端会话绑定在一起,客户端会话失效,则这个节点就会被自动清除。
- 临时顺序节点(EPHEMERAL_SEQUENTIAL) 可以用来实现分布式锁
可以通过get指定查看节点状态的ephemeralOwner值。如果这个节点是临时节点,这个值应该指向所有者。如果这个节点是持久节点,那么这个值应该是0。
分布式锁的实现
- 客户端连接ZK,在/lock下创建临时且有序的子节点。
- 客户端获取/lock目录下所有节点的列表,检查自己是否是不是当前序号最小的。是则获取锁。否则设置监听器监听该目录。直到自己是当前序号最小的,获取锁。
羊群效应:
假如当前有1000个节点在等待锁,如果获得锁的客户端释放锁时,这1000个客户端都会被唤醒,这种情况称为“羊群效应”;
为了避免上述的羊群效应,我们需要作出一个优化,就是监听器不检查目录,而是用来监听自己的前置节点。
监听器的原理如下