zk消息处理链

http://blog.csdn.net/shaolinshu/article/details/7927345


Zookeeper介绍:
Zookeeper是paxos算法的一种实现,被广泛的用于分布式锁服务,名字服务,leader选举等。一般是一个集群系统,每一个集群节点称作quorum,quorum的类型分为Leader,Follow和Observer。他在内存中维护了一个树状的数据结构,如下所示,

每个节点上可以存储数据,由于是一个集群系统,因此需要维护数据的一致性,它通过一个类似两阶段提交协议的过程保证数据的一致性。对于读请求,直接返回本地数据,而对于写请求,则需要转发给Leader,由Leader发起Proposal,并由所有的follow投票,只有当半数以上的follow同意该写请求,才会真正的执行该请求。这个方式也保证了只要集群中有一半以上的server活着,该集群就可以对外提供服务。
Zookeeper通过QuorumPeerMain启动类启动,根据配置启动单机版或者集群版得zk。启动集群版zk读取配置文件,设置相应参数后启动QuorumPeer线程,该线程首先load数据到内存,然后启动leaderelection算法选取leader确定身份(Follow,Leader,Observer),确定好身份后,调用各自的lead,followLeader,ObserverLeader方法。Zookeeper在确定自己身份后,会启动相应的ZookeeperServer,在ZookeeperServer中建立相应的消息处理链,以后所有的请求Request,都会经过这个消息处理链,以保证整个Zookeeper的一致性。
ZookeeperServer的作用
ZookeeperServer的继承关系和处理链的关系如下图所示:

1.1 ZookeeperServer
是总的基类,该类包含了ZKDataBase,Session,zxid,submitRequest等重要方法。
Session类相关的方法有createSessionTracker,createSession,reopenSession,closeSession,killSession,expire等
getZxid,getNextZxid记录了相关的事物Id
submitRequest将Request交给第一个消息处理链。
setUpRequestProcessor则建立相应的处理链,以流水线的形式处理所有消息。
1.2 QuorumZookeeperServer
继承自ZooKeeperServer,只是增添了一个成员QuorumPeer,代表一个类型(如Leader,Follow和Observer),该方法完成本地ZKDatabase的数据load,leader选举,然后根据身份启动相应的线程。(Leader线程lead方法,Follow线程的followLeader方法)
1.3 LearnerZookeeperServer
继承自QuorumZookeeperServer,但是其createSessionTracker方法创建的SessionTracker是LearnerSeesionTracker,只是维护一个SessionSet,然后向Leader发送ping消息时,带上自己的所有Session,Session的超时计算在Leader端完成。
1.4 FollowZookeeperServer
继承自LeanerZookeeperServer,FollowZookeeperServer创建如上图所示的消息处理链,并增加logRequest和commit方法。
logRequest方法将收到的来自Leader的Proposal消息发往SyncRequestProcessor记录日志下一个AckRequestProcessor发送ack给Leader
commit方法收到来自Leader的Leader.COMMIT后,将相应消息送到CommitProcessor去commit
1.5 ObServerZooKeeperServer继承自LeanerZookeeperServer,FollowZookeeperServer创建如上图所示的消息处理链。(TODO)没看全。
1.6 LeaderZookeeperServer继承自QuorumZookeeperServer,创建如上图所示的消息处理链,创建Leader方的SessionTracker。
消息处理链
follow和leader的消息都是通过在QuorumPacket中的txnHeader和txn来进行的。
2.1 消息处理链的作用:
2.1.1 PreRequestProcessor
只在Leader放存在,消费submittedRequests队列(pRequest),该队列来自客户端直接发到leader的消息(写和读都有),和learner转发而来的消息(只有写)。该处理链对消息反序列化后,对消息作参数和ACL方面的检查,然后将填充消息的TxnHeader和Txn,发往消息处理链的下一层。对于多机版是ProposalRequestProposal进行Proposal。
2.1.2 ProposalRequestProposal
只在Leader方存在。处理PreRequestProcessor转发来的请求,对于其中的写消息(TxnHeader!=null)调用leader.propose(request)向所有follow发送Leader.PROPOSAL消息,并且发往SyncRequestProcessor记录日志,具体看下面消息循环的说明部分。然后所有消息转交给下一个消息处理器处理,一般为CommitRequestProcessor。
2.1.3 CommitRequestProcessor
在Leader和Leaner方均存在。该处理器中有两个队列,queuedRequests队列和committedRequests队列。其中queuedRequests来自客户端发来的消息,committedRequest队列包含所有Leader发送的commit消息。该线程收到一个commit消息(即commitRequest队列被增加一个消息),对比queuedRequests中的消息,如果sessionid和cxid都相同,说明是客户端发来的消息,直接将queuedRequest队列中的该消息加入toProcess队列(这个消息的request的cnxn不是null,含有客户端信息,用于finalRequestProcessor发送response。);如果不同,则是别的集群收到的消息,将收到的commit消息放到toProcess队列。toProcess队列中的消息会传递到下一个消息处理器。
2.1.4 Leader.toBeAppliedRequestProcessor
只在Leader方存在。将所有消息转发到下一个消息处理器FinalRequestProcessor,如果toBeApplied队列里有该消息,从此队列中删除该消息。toBeApplied队列在startForwarding方法中使用,用来让follow同步leader所有的已通过投票的Proposal。(没全搞懂这个toBeApplied)
2.1.5 FinalRequestProcessor
在Leader和Learner方都存在,用来处理请求。该处理器是消息处理链的最后一个。调用ProcessTxn真正处理到DataTree的操作,写到本地内存中的树。然后真正拥有客户端连接的那个机器发送response给客户端。在CommitRequest的queueRequest队列就是干这个作用的。
2.1.6 SyncRequestProcessor
Leader放和Learner方都存在。用来将操作记录到snapshot和transaction log里。每条写操作都会记录到transaction log中,日志采用满1000条批量flush到日志文件,满一定条数单独线程生成snapshot文件。该处理器一般接SendAckRequestProcessor,记录完日志后,投出自己的一票。
2.1.7 SendAckRequestProcessor
只在Learner方存在。用来发送Leader.ACK消息,投出自己的一票。
2.1.8 AckRequestProcessor
只在Leader方存在,Leader直接调用leader.processACK处理ack消息,当做是自己也投出了一票。
2.1.9 FollowRequestProcessor
转发写请求给leader.getFollow.request(request)
3.消息处理
3.1 Follow
3.1.1 Follow的消息处理:
QuorumPeer类启动经过选举确定为Follow身份后,follow调用followLeader方法,该方法主要进行下面三方面操作
1. 连到Leader(connectToLeader);
2. 同步数据。leader具有最新的数据。(SyncWithLeader)。同步完成后,会启动FollowZookeeperServer线程(SyncWithLeader中),进而启动处理链上的各个线程。
Follow的处理链为:
FollowerRequestProcessor--->CommitRequestProcessor--->FinalRequestProcessor
SyncRequetProcessor--->SendAckRequestProcessor
3. 消息循环。对Lead的消息作出响应。(processPacket)
Leader对Follow发送如下几种消息:
1)Leader.PROPOSAL消息:
该消息是Leader发来的提议,需要Follow进行投票。Follow收到Leader的Proposal消息,会将其发送到SyncRequestProcessor进行处理。也就是记录完日志后,发送Leader.ACK消息给Leader,相当于自己投出一票。
2)Leader.COMMIT消息:
该消息表示Leader方对此消息已经投票通过。Follow收到该消息,将消息加入到CommitRequestProcessor的committedRequests队列,最终提交到FinalRequestProcessor改变本地DataTree。
3)Leader.UPTODATE消息:
Leader发送完对Follow的同步指令后发送该消息,表示follow已经可以开始接受客户端请求,同步已经完成。
4)Leader.REVALIDATE消息:
和Leader同步Session信息。关闭已经不能用的Session。
5)Leader.SYNC消息:
同步
3.1.2 Follow端得消息走向:
1.Follow对自己收到来自客户端的写请求,转为Leader.REQUEST消息转发给Leader。
2.收到Leader.PROPOSAL消息,记录日志,发送ACK消息,投出自己一票。
3.收到Leader.Commit消息后,更新CommitRequestProcessor的committedRequests队列,将已经通过的请求发往Final做真正的提交。
4.Final通过ProcessTxn改变zk的内存数据库。
3.2 Leader
3.2.1 Leader的消息处理:
QuromPeer类启动经过选举确定为Leader身份后,leader条用lead方法,该方法进行下面3步操作。
1.宣布自己是leader,启动CnxAcceptor线程,接受来自follow的连接,对于接受的连接启动leanerHandler线程。
2.等到半数以上的follow响应自己为leader。
3.循环发送ping消息。
对于和每一个连接上的follow的交互逻辑交由leanerHandler线程处理。该线程主要做下面三件事
1.像leader报告自己是follow还是oberver
2.确定自己的同步类型(diff,trunc还是snap)
3.进入leader对follow的消息循环。
Follow对Leader发送如下几种消息:
1)Leader.ACK:
该消息是follow发来的对Proposal的投票,leader调用processAck处理投票,当发现超过半数同意后(self.getQuorumVerifier().containsQuorum(p.ackSet)),发送COMMIT消息给所有follow,发送INFORM消息给observer
2) Leader.PING:
心跳消息,
3) Leader.REVALIDATE:
维护Session,延长Session过期时间
4) Leader.REQUEST:
follow转发的来自客户端的写请求,发往submittedRequests队列,该队列由Leader的PreRequestProcessor消费
3.2.2 Leader端得消息走向:
1.PreRequestProcessor检查参数情况和ACL情况,然后向所有follow提交Proposal消息
2.收到多数对某个proposal的ack消息,把消息发送到commitProcess的已commit队列,发送commit消息给所有follow,发送inform消息给所有的observer
3.commit过的消息经toBeappliedRequestProcessor到FinalRequestProcessor最终执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值