ZooKeeper内部原理

  • 查看日志命令

java -cp zookeeper-3.4.8.jar:lib/log4j-1.2.16.jar:lib/slf4j-log4j12-1.6.1.jar:lib/slf4j-api-1.6.1.jar org.apache.zookeeper.server.LogFormatter tmp/zookeeper/version-2/log.1

请求、事务和标识符

  • 请求:zk服务器会在本地处理只读请求,对于增删改请求会转发给leader处理
  • 事务:leader执行相应的请求,并形成状态的更新。一个事务为一个单位,所有的变更处理需要以原子方式执行。
  • 标识符:leader产生一个事务,并给该事务分配一个标识符,称为zk服务会话id(Zxid),通过zxid对事务进行标识,就可以按照leader所指定的顺序在各个服务中按序执行。
  • zxid为一个long型(64位)整数:分为两部分:时间戳(epoch)部分和计数器(counter)部分.
  • 时间戳的概念代表了管理权随时间的变化情况,时间戳的值在每次新leader选举发生的时候便会增加。

leader选举

当一个服务器进入Looking状态,就会向集群中每个服务器发送一个通知消息,该消息中包括服务器的投票(vote)消息,该信息主要由标识符(sid)和最近执行的事务zxid信息组成。 当一个服务器收到一个投票信息,该服务器将会根据以下规则修改自己的投票信息:

  • 1.将接收的voteId和voteZxid作为一个标识符,并获取接收方当前的投票中的zxid,用myZxid和mySid表示接收方服务器自己的值。
  • 2.如果(voteZxid > myZxid)或者(voteZxid = myZxid且voteId>mySid),保留当前的投票信息。
  • 3.否则,修改自己的投票信息,将voteZxid赋值给myZxid,将voteId赋值给mysid。

选举过程中出现脑裂问题,最简单有效的方式,是通过延时,即让old leader在选举过程中,多停顿一会儿。这样新的leader,再被选举出来后,会通知所有从机然后更新zxid,这样就就可以解决脑裂问题了。

Zab:状态更新的广播协议

Zab:zookeeper原子广播协议。假设我们有一个活动的leader服务器,并拥有仲裁数量的追随者支持该leader的管理权,通过该协议提交一个事务非常简单,类似于一个两阶段提交:

  • 1.leader向所有追随者发送一个personal消息p;
  • 2.当一个追随者接受消息p后,会响应leader一个ACK消息,通知leader其已经接受该personal;
  • 3.当收到仲裁数量的服务器发送的确认消息后,leader就会发送消息通知追随者进行提交(commit)操作。

Zab保障了以下几个重要属性:

  • 如果leader按顺序广播了事务T和事务T',那么每个服务器在提交T'事务前保证事务T已经提交完成。
  • 如果某个服务器按照事务T、事务T'的顺序提交事务,所有其他服务器也必然会在提交事务T'前提交事务T。

Zab协议需要提供的保障:

  • 一个被选举的leader确保在提交完所有之前的时间戳内需要提交的事务,之后才开始广播新的事务。为保证这个需求,leader在被选举出来后,并不会直接处于活动状态,直到确保仲裁数量的服务器认可这个leader新的时间戳值。

  • 在任何时间点,都不会出现两个被被选举的leader。 在leader选举中,我们选择zxid最大的服务器作为leader

观察者

  • 引入观察者的一个主要原因是提高读请求的可扩展性
  • 采用观察者的另外一个原因是进行垮多个数据中心的部署

快照

快照是zk数据树的拷贝副本,每一个服务器会经常以序列化整个数据树的方式来提取快照,并将这个提取的快照保存到文件中。

参考文献

results matching ""

    No results matching ""