本文适用于对Zookeeper有必定了解且想要了解源码或正在了解源码的同窗,花费大约五分钟bash
前几天看了一个帖子,讲Zookeeper的顺序一致性,比划了一通数学解释,看的云山雾罩的,在此讲下本身对于顺序一致性的理解微信
Zookeeper常被用于分布式协调服务(即服务或元数据注册等场景,如Dubbo、Kafka:将生产者或元数据信息注册到Zookeeper集群上,以便分布式系统其余参与者及时看到,由于Zookeeper实现了相似Paxos的Zab协议,解决了分布式数据一致性问题)、分布式锁等用途架构
假设有一个Zookeeper集群(N>=3,N为奇数),那么只有一个Leader(经过FastLeaderElection选主策略选取),全部的写操做(客户端请求Leader或Follower的写操做)都由Leader统一处理,Follower虽然对外提供读写,但写操做会提交到Leader,由Leader和Follower共同保证同一个Follower请求的顺序性,Leader会为每一个请求生成一个zxid(高32位是epoch,用来标识leader选举周期,每次一个leader被选出来,都会有一个新的epoch,标识当前属于哪一个leader的统治时期,低32位用于递增计数)分布式
针对同一个Follower A提交的写请求request一、request2,某些Follower虽然可能不能在请求提交成功后当即看到(也就是强一致性),但通过自身与Leader之间的同步后,这些Follower在看到这两个请求时,必定是先看到request1,而后再看到request2,两个请求之间不会乱序,即顺序一致性ui
Leader在处理第4步Follower的ack回复时,采用过半数响应即成功原则,也就是这时候有的Follower是尚未处理或者处理成功这个请求的spa
pendingTxns阻塞队列及txnLog
中,而后发送ack给Leaderpublic void logRequest(TxnHeader hdr, Record txn) {
Request request = new Request(hdr.getClientId(), hdr.getCxid(), hdr.getType(), hdr, txn, hdr.getZxid());
if ((request.zxid & 0xffffffffL) != 0) {
pendingTxns.add(request);
}
syncProcessor.processRequest(request);
}
复制代码
proposal这步是会发给全部的follower的(放到LearnerHandler的请求处理队列中,一个Follower一个LearnerHandler),以后Follower的ack就不必定全返回了code
long firstElementZxid = pendingTxns.element().zxid;
if (firstElementZxid != zxid) {
LOG.error("Committing zxid 0x" + Long.toHexString(zxid)
+ " but next pending txn 0x"
+ Long.toHexString(firstElementZxid));
System.exit(12);
}
复制代码
总之:Follower经过队列和zxid等顺序标识保证请求的顺序处理,一言不合就会退出或者从新同步Leadercdn