本文是大数据学习总结系列第二篇之ZooKeeper,上一篇是hadoop
本文是根据《从Paxos到Zookeeper 分布式一致性原理与实践》的知识点进行整理总结。
一、 从集中式到分布式
1. 集中式
2. 分布式
3. ACID
4. CAP
5. BASE
二、 一致性
1. 2PC
2. 3PC
3. paxos
三、 zookeeper
1. 什么是zookeeper
2. zookeeper设计目标
3. zookeeper的几个角色
4. watcher监听机制
5. zookeeper的权限
四、 zab协议
1. zab 的三种状态
2. zab宏观上的三个阶段
3. zab的微观的四个阶段
4. zab的节点状态讲解
5. 详解zab四个阶段
6. zab和paxos区别
五、 ZooKeeper在大数据中的应用场景
1. 发布订阅
2. ZooKeeper HA应用(主备切换)
3. master选举
4. zookeeper在hbase中应用
5. ZooKeeper在kafka中应用
六、ZooKeeper技术内幕
1. ZooKeeper架构
2. 数据模型
3. ZooKeeper客户端
4. watcher
5. 通信协议
6. 选举Leader
7. 会话
8. 数据初始化
9. 数据同步
一、 从集中式到分布式
1. 集中式
2. 分布式
3. ACID
4. CAP
5. BASE
1. 集中式
集中式特点:不用考虑网络分区,宕机问题,协作问题。但是昂贵。
2. 分布式
分布式:由多台机器通过网络通信组成,到了的节点机器,分布式,故障发生频率大。
故障原因:网络问题,多台机器网络通信容易超时,中间有可能断掉造成分区。
网络分区:俗称脑裂。
网络的三态问题:要么连接成功,要么失败,要么超时。
所以分布式主要是网络方面和机器方面的问题,最大问题是网络问题。
3. ACID
例如数据库的事务
原子性:要么成功,要么失败;
一致性:如果出现异常数据,还是原来的那份
隔离性:各个会话之间是相互独立的
持久性:就是提交后的数据永久保存在磁盘上,不丢失。
4. CAP
一致性:多台机器拥有相同副本
可用性:在适合的时间响应客户端
分区容错性:不能出现网络分区
5. BASE
分布式主要的是网络,所以我们优先处理分布式的网络分为,然后在一致性和可用性之间权衡。这时提出了BASE就是对CAP的一致性和可用性的权衡结果。
BASE 基本可用,最终一致性
最终一致性:就是你提交一台机器,其他机器最终会把你提交的那台机器给同步到自己上。
二、 一致性
1. 2PC
2. 3PC
3. paxos
主的控制机器就叫协调者,副本机器叫参与者
1. 2PC
两个阶段,提交事务和执行事务。
提交事务
1). 询问
2).执行初始化(执行提交)
执行事务
2PC的故障情况
单台机器
1. 协调者故障,那么有个备用协调者接管,并且查询参与者当前执行到什么地步,然后接着执行下去。
2. 参与者故障,那么协调者会等待它重启,然后再执行下去。
这两种情况,都只会阻塞,并不会不一致性。
同时故障:
协调者和参与者同时故障
例如:有机器1,2,3,4。其中4是协调者,1,2,3是参与者
4给1,2发完提交事务后故障了,正好3这个时候也故障了,注意这是3是没有提交事务数据的。现在备用协调者启动了,去询问参与者,用于3死掉了,一直不知道它处于什么状态(接受了提交事务,还是反馈了能执行还是不能执行3个状态)。
面对这种情况,让1,2回归停止事务,3恢复以后,不管是什么状态,直接停止事务,回滚,这样子就保证了一致性。
这是2PC的漏洞,当同时故障了,就全部回滚,效率低下,代价大
2. 3PC
2PC 当时只考虑如果单机故障的情况,并没有考虑协调者和参与者同时故障的情况。3PC就是对2PC漏洞的补充协议。它把2PC中的提交事务请求一分为二,添加了一个状态(准备阶段)。做到就算两个同时故障也不阻塞,并且保证一致性。
事务询问阶段(can阶段)
事务准备阶段 (pre)(包括执行提交)
执行事务阶段 (do commit)(将状态更改)
下面例子分析:
1. 4是协调者 ,1,2,3 是 参与者,当新闻的节点,协调者4和参与者3同时挂掉了。这时候备用的协调者启动了,询问了1和2的状态,都在can阶段,回滚代价下,直接回滚。当3重新启动了发现自己是can阶段,回滚代价下,执行回滚,停止事务。这样子就摆在了3个节点数据一致性。3PC对应2PC就是减少回滚代价。
-
当3个参与者都进入到per准备阶段,说明它们都接受到提交询问,并且都表决过(意思是都领到了数据),这时协调者4和参与者3突然死掉了。备用协调起来后,询问其他参与者状态,一看都到pre阶段了,说明都领到了数据包括死掉的3,因为他表决过才进入到准备阶段,所以他让大家都提交了。当3重启后,看了日志,发现自己已经到准备阶段时死掉了,可以执行提交,这样保证了数据一致性。
3. paxos
有个叫paxos小岛,他们每项 决定都得通过提议然后半数才能生效,每个决定的提议都有一个唯一的全局编号,这个编号只能自增长,不能后退。
何为通过:就是提议的id好要大于议员手记录的最大的id
第一阶段:提议者发起提议给每个议员,然后等议员反馈同意或不同意。
第二阶段:如果半数以上同意了,则执行事务,否则不执行。
如果半数以上同意了,这个议题就通过,然后提议者就命令剩下的议员同步自己的数据,并修改手上的最大id好。
问题:在分布式中并发是常见的,例如现在有提议者p1,p2
提议者同时提出一个提议,这个时候他们手上的id就有可能是一样,p1的id是3,p2的id也是3。当p1提议给议员(假设议员手上的id是2),现在议员先同意了p1,p2来访问这个议员,议员告诉他已经同意了议题id是3,p2的id是3不同意。然后p2回去加大自己的id重新请求,议员这时同意了他。p1收到半数同意准备去通知他们来更新id同步数据,可是发现议员们的id比自己的大了,然后p1有加大id。这种极端情况,导致死锁了。
这种解决办法就是提议者只有一个,也就是paxos里面说的总统。
三、 zookeeper
1. 什么是zookeeper
2. zookeeper设计目标
3. zookeeper的几个角色
4. watcher监听机制
5. zookeeper的权限
1. 什么是zookeeper
zookeeper是为了解决分布式一致性问题的工程应用。
zookeeper并没有直接用paxos协议,而是在paxos协议的基础上,提出了符合自己符合实际应用场景的高可用的一致性协议ZAB原子广播协议。
zookeeper分布式一致性的特点:
-
顺序一致性:客户端访问zookeeper的一个节点,发起事务,是排着队到leader那让他发起提议,一个一个来;
-
单一视图:任何节点上的数据都是一样的,所以客户端访问任意节点都看到是相同的数据。
-
可靠性:给了一个客户端反馈,同意他的请求,那么就是真的同意了。
-
实时性:zookeeper保证在一定时间内,比如5秒之后你可以访问到最新数据。这是最终一致性导致的。
2. zookeeper设计目标
-
简单的数据模型:就是文件夹的树形结构
-
可以构建集群:
-
顺序访问:客户端提出了一个事务请求,会获得一个唯一的id编号,用于操作的先后顺序;
-
高性能:这里指的是读取数据
3. zookeeper的几个角色
zookeeper有几个角色:leader、follower、observer;其中observer一般不配置,它也不参与投票,observer可以在不影响写性能的情况下提升集群的读性能;
zookeeper中节点有实体机器节点,还有znode数据节点。znode数据节点指的是目录文件夹。数据节点有永久数据节点和临时节点。
4. watcher监听机制
zookeeper有watcher监听机制,例如一个临时数据节点,如果客户session中断了,临时节点就删除了,这时watcher就监听到了。这点就是hadoop的HA实现机制,zkfc实现了zookeeper的watcher机制来自动切换。
5. zookeeper的权限
zookeeper的数据节点就是一个文件夹目录,它有自己的权限机制ACL。
实际zookeeper删除、设置。创建目录,这些就是执行权限。
四、 zab协议
1. zab 的三种状态
2. zab宏观上的三个阶段
3. zab的微观的四个阶段
4. zab的节点状态讲解
5. 详解zab四个阶段
6. zab和paxos区别
1. zab 的三种状态:
-
Looking/election:系统刚启动时或者Leader崩溃后正处于选举状态;
-
Following:Follwoer节点所处的状态,Follower与Leader处于数据同步阶段;
-
Leading:Leader所处状态,当前集群中有一个Leader为主进程。
2. zab宏观上的三个阶段:
-
崩溃恢复
-
快速选举
-
原子广播
3. zab的微观的四个阶段:
-
选举
-
发现
-
同步
-
广播
客户端提交一个请求到leader然后leader发起提议floower来投票,这个过程都是原子广播
4. zab的节点状态讲解
-
ZooKeeper启动时所有节点初始状态为Looking,这时集群会初始选举出一个Leader节点,选举出的Leader节点切换为Leading状态;
-
当节点发现集群中已经选举出Leader则该节点会切换到Following 状态,然后和Leader节点保持同步;
-
当Following节点与Leader失去联系时Follower节点则会切换到Looking状态,开始新一轮选举;
-
在ZooKeeper的整个生命周期中每个节点都会在Looking、Following、Leading状态间不断转换。
当启动后leader崩溃选举
选举出Leader节点后zab进入原子广播阶段,这是Leader为和自己同步的每个节点Follower只能和一个Leader保持同步Leader节点与Follow节点使用心跳检测来感知对方的存在;
当Leader节点在超时时间内收到来自Follower的心跳检测,那Follower节点会一直与该节点保持连接;若超时时间内Leader没有接收到来自过半Follower节点的心跳检测或TCP连接断开,那Leader会结束当前的领导,切换到Looking状态,所有Follower节点也会放弃该Leader节点切换到Looking状态,所有Follower节点也会放弃该Leader节点切换到Looking状态,然后开始新一轮选举;
5. 详解zab四个阶段:
-
第一阶段:准备leader选举
成为leader的条件:
选epoch最大的;
epoch相等,选zxid最大的
epoch的zxid都相等,选择server id最大的(就是配置zoo.cfg中的myid)。
节点在选举开始读默认投票给自己,当接收其他节点的选票是,会根据上面的条件更改自己的选票并重新发送选票给其他节点,但一个节点的得到票超过半数,该节点会设置自己的状态leading,其他节点会设置自己的状态为following。
什么是epoch,什么是zxid?
首先ZooKeeper一个事务包含两部分,一个数数据,一个是id;id是全局唯一的id,数据就是具体操作数据,并且是lastid加1;
ZooKeeper每个请求都是顺序执行的,强顺序性的;
epoch是leader标识,zxid是事务标识。
epoch是指:年代,一个领导挂了,另一个领导上任,现在就是新领导的时代了,当产生新领导,事务编号就从0开始。
zxid是总称:前32位是leader编号(epoch),后32位是这个leader下事务编号。
-
第二阶段:发现阶段
发现阶段主要是发现最大的epoch和最大的事务编号;
之前说了快速产生准备leader,然后其他节点就是fllower,然后发现阶段就是fllower向leader报告,自己的epoch和事务编号,然后leader排序,选择最大的epoch和最大的事务编号。然后通知fllower去更改它的epoch。 -
第三阶段:同步阶段
leader利用上一个阶段知道最大事务编号,然后通知其他fllower去leader这同步数据。事务编号有可能不一样,所以要同步。保持数据最终一致性。 -
第四阶段:原子广播阶段
这时候leader真正对外提供服务,接受客户端的请求,生成一个数据,半数以上同意,然后就提交事务。剩下的其他节点直接去leader那同步数据。
原来挂掉的leader的事务?
它启动起来,发现他的时代已经过时了,就删除了事务,发现有心的leader,自己就变成fllower,然后就去同步数据。
在选举上,会选举拥有最新提议历史(lastZxid最大)的节点作为leader,这样子就省去了发现最新提议的步骤。这是局域拥有最新提议的节点也有最新提交记录的前提。
6. zab和paxos区别
paxos没有给出leader选举协议,只给出一致性协议。
五、 ZooKeeper在大数据中的应用场景
1. 发布订阅
2. ZooKeeper HA应用(主备切换)
3. master选举
4. zookeeper在hbase中应用
5. ZooKeeper在kafka中应用
ZooKeeper 目录有几个特点,有临时目录,永久目录,顺序目录,强一致性(顺序访问)和watcher机制。
利用这些特点,我们可以实现:
-
发布订阅,例如一些配置信息;
-
负载均衡,例如kafka生产,消费均衡;
-
master选举,例如hbase利用它hmaster选举;
-
主备切换,例如hdfs的HA利用它进行切换。
1. 发布订阅
例如:我们的数据库配置信息文件就可以放到ZooKeeper上。
利用ZooKeeper的watcher机制实现配置变更,程序在运行中就可以获取到最新的配置信息,不需要起停。
2. ZooKeeper HA应用(主备切换)
hdfs的HA,它的主备切换用的是ZooKeeper来做Active standby之间切换的。
大致步骤:
1). 多个nodemanager同时向ZooKeeper注册一个数据节点lock。因为ZooKeeper是强一致性的,所以只能有一个注册成功,注册成功的那个就是active
2). 没有注册成功的否成了standby,然后在lock目录上注册监听事件watcher。
注意:注册的lock节点目录是临时节点,如果active挂了,这个目录也就没了,并且这个lock目录是有权限控制的ACL,防止active假死后重新连接出现脑裂。
3). 主备切换:当active挂掉以后,会话结束,临时目录自动删除。其他standby监听到临时目录删除了,各个standby重新同时进行创建带权限的临时目录。成功的改为active,没有成功的还是standby。
4). 如果挂掉的active启动后,发现没有权限范围lock临时目录,自动更改成standby状态。
这是ZooKeeper主备切换应用,利用临时目录,ACL,watcher机制实现。
3. master选举
利用ZooKeeper master选举其实很简单,和主备切换一样。
利用强一致性同时创建同一个目录,最后只能一个成功。
成功那个节点会返回成功状态,其他节点返回异常,成功的那个就成为master,其他节点就改成slave。
4. zookeeper在hbase中应用
hmaster监控regionserver是否挂掉。
首先,rs(regionserver简称)在ZooKeeper注册一个临时目录rs/[hostname]目录,然后hmaster注册watcher监控rs目录下面变化就可以发现rs服务器是否挂掉。
元数据存储(订阅发布):每个region存储信息位置和状态,都放在ZooKeeper上存储,以便大家都能订阅目前region所处的状态,比如region是在合并还是在切割,有多少个region分别在哪个regionserver上。所以客户端访问先访问ZooKeeper得到位置信息去读取数据,不经过hmaster。
5. ZooKeeper在kafka中应用
kafka在ZooKeeper注册的信息
首先,kafka会把broker创建到ZooKeeper临时目录上。
/broker/ids/[1-n]表示broker还活着。然后topic信息创建到ZooKeeper临时目录。/brokers/topics/[topicname]/paritiong信息。如果有消费者,消费者也会在ZooKeeper创建自己消费信息的offset信息。等临时目录。
kafka注册broker和topic信息使为了生产消费时负载均衡,这就利用到ZooKeeper负载均衡。消费生产者监控到broker和topic,topic和partition之间的数量,进行重新排序。
六、ZooKeeper技术内幕
1. ZooKeeper架构
2. 数据模型
3. ZooKeeper客户端
4. watcher
5. 通信协议
6. 选举Leader
7. 会话
8. 数据初始化
9. 数据同步
1. ZooKeeper架构
ZooKeeper是主从架构,分为leader,follower,observer。
-
leader:处理事务请求,保证事务一致性;
-
follower:处理非事务请求,并转发客户端事务请求到leader,并参与选举投票;
-
observer:处理客户的非事务请求,不参与选举投票,只是为了分担数据做动态扩展,可有可无。
注意:非事务就是不改变集群状态,比如读取数据,读取目录。读取就是非事务请求。事务请求就是要改变集群转台,比如创建目录,改变了集群原本状态。
2. 数据模型
ZooKeeper的数据模型是树形结构,类似于操作系统的文件目录结构,但有点不同。
ZooKeeper的文件夹目录是可以存数据,并且他没有文件概念,比如txt等没有这个概念,所以它的目录直接叫做数据节点znode。一个“/”就代表一个znode数据节点。所以跟目录也是一个znode并且可以存数据。
znode分为永久数据节点、临时数据节点、组合数据节点;组合数据节点又分为永久顺序节点、临时顺序节点。
重点了解:永久和临时区别,顺序是什么。
-
永久和临时是和会话有关系的,永久是会话结束后依然存在的,临时是和会话的生命周期绑定在一起。
-
顺序就是每个父znode下面的子znode都是有一个唯一的编号顺序的。注意是父目录下的子目录:你可以在这父目录下车间顺序节点保证唯一。创建节点过程中,ZK会自动为给定节点名加上一个数字后缀,作为新的节点名,这个数子字后缀的范围是整型的最大值。
ZooKeeper的znode也是有自己的元数据信息,并且他可以保存数据,znode元数据也就是状态信息:
数据版本
首先说说悲观锁和乐观锁:
-
悲观锁:就是独占,我锁定资源只有当我释放资源了别人才可用(包括了不让别人读取);
-
乐观锁:就是大家可以用资源,当你写入更新的时候去判断之前数据状态是否已经被更改,如果更改就是有操作过了,那么就回滚。
ZooKeeper的数据节点采用了悲观锁的思想,用一个版本号做检验状态,每次要写入数据、更改数据都带上版本号做验证,如果是-1就是用最新版本号,不做验证。
ZooKeeper的znode权限
ZooKeeper没有利用平时我们所接触的权限控制模型,它利用了更先进的ACL权限控制列表。ACL包含权限模式、控制对象、控制权限三部分。
ZooKeeper模式就是我们经常用的就是digest。username:password。
ZooKeeper数据节点还有一个特性就是watcher——事件监听。
3. ZooKeeper客户端
ZooKeeper客户端包含了我们的编程,还有用zkCli.sh启动进行命令操作,连上那台机器follower那台就是客户端。
客户端命令
具体客户端操作:
创建znode、ls列出目录、get获取数据、set更新数据、delete删除znode(删除的时候只能一个个删除)
客户端编程
其中参数列表如下:
注意:创建ZooKeeper会话的时候需要注册一个美人watcher事件监听。
4. watcher
watcher 的注册过程:
客户端向ZooKeeper服务注册一个watcher,并且将watcher存储在客户端。
ZKWatcherManager进行管理,当zk的服务端触发Watcher事件后,通知客户端,客户端从ZKWatcherManager中拿出处理逻辑代码执行。
处理逻辑代码也就是:process(WatchedEvent event),回调process的时候,watchedEvent包含了三部分信息:通知状态,事件类型,节点路径。重点看前两者
通知状态就是tcp连接情况,事件类型就是连接上以后znode改变情况。
总结
客户端连接需要三个过程:
-
初始化,也就是准备环境;
-
创建会话,也就是发送连接;
-
响应,也就是等待反馈。
要分清客户端的网络线程是clientcnxn来维护连接。服务器端也有网络线程叫做servercnxn。他们互相通信的最小单元就是packet包,pacjet封装了ip端口等连接信息外,还有请求类型,还有watcher信息。
5. 通信协议
ZooKeeper通信协议如下:
请求
请求:包含请求头和请求体
-
请求头:包含xid,一个会话它自己发起的顺序号,自己维护;type请求类型,创建、读取、修改等;
-
请求体:根据请求类型不同,所以请求体也不同,但是请求体就是参数。
6. 选举Leader
首先选举leader时候存在的集中服务器状态(注意:选举期间所有节点都处于looking状态)
选举的基本术语:
这个就是为什么ZooKeeper集群是单数的原因
进行pk投票,规则如下:
-
Follower可以参与选举,发起的选举数据格式是:(myid,zxid),他们先给自己投一票,然后发送给其他节点机器,其他的节点机器接收到这个选项,进行pk投票;
-
pk下来然后把比自己打的发送给其他节点,就是属于投了一票,
-
每个节点都统计别人投自己票数,如果超过一半投票,就给其他机器发送暂停投票,然后宣布自己成为leader改变状态成leading(zab里面状态),其他follower状态就是(follower),
-
如果服务器是运行期间leader挂掉,一开始所有的follower改状态为looking,然后进行投票。类似上面的投票机制。主要是pk机制,半数以上同意。
7. 会话
在ZooKeeper中客户端成功连接服务器端就会产生一个会话。
会话有几个状态:连接成功,连接超时重试,关闭连接。
当去创建一个会话的时候,服务端会生成一个sessionid,timeout,isclose并保存在服务端的zkdatabase中,sessionid是全局唯一的来表示唯一的一个会话。如果发起一个事务就会生成自增zxid。zxid来顺序执行事务。服务器对于会话恢分桶管理,根据预计下次超时时间相同的会话分桶在一块。
相同的超时时间的会话分在一个桶里管理,也就是分区
超时判断:如果没有执行这些命令,客户端会自己主动去发送心跳,告诉服务端会话还有效,服务端不断去激活会话。心跳时间:time/3。如果会话超时,服务端标记为已经关闭,进行清理,包括临时的数据节点。重新连接的要求是在超时之内,如果客户端连接上服务端其中一台会话还是有效的。
8. 数据初始化
zk是树结构,并且保存的数据在内存中,zk并且会记录操作日志、内存数据,并且定时snapshot到硬盘上进行数据快照。当集群启动的时候,进行数据初始化。
-
首先读取磁盘上快照到内存中,然后找最大zxid,加载日志到内存中,对比快照中的zxid和zxid。
-
如果zxid较大,把内存中的数据进行日志操作,改变zxid成为最大zxid。
9. 数据同步
数据同步就是follower去leader上同步数据,因为leader一个提议只需要n/2+1,所以还有一些机器没收到(就是没有投票给leader的follower),这些没收到的机器发起一个请求去同步数据
同步数据分两种:一种是差异同步,另一种是全量同步。
大数据学习总结系列的下篇文章是Hive
更多关于hadoop,spark和机器学习文章请关注本文公众号: