
Zookeeper是一个分布式数据管理与协调服务,目标是可以提供高性能、高可用和顺序访问控制的能力,同时也是为了解决分布式环境下数据一致性的问题。
在一致性协议方面,注重CP。
首先,Zookeeper集群中有几个关键的概念,Leader、Follower和Observer,Zookeeper中通常只有Leader节点可以写入,Follower和Observer都只是负责读,但是Follower会参与节点的选举和过半写成功,Observer则不会,他只是单纯的提供读取数据的功能。
通常这样设置的话,是为了避免太多的从节点参与过半写的过程,导致影响性能,这样Zookeeper只要使用一个几台机器的小集群就可以实现高性能了,如果要横向扩展的话,只需要增加Observer节点即可。
ZooKeeper建议集群节点个数为奇数,只要超过一半的机器能够正常提供服务,那么整个集群都是可用的状态。
Zookeeper中数据存储于内存之中,这个数据节点就叫做Znode,他是一个树形结构,比如/a/b/c类似。
而Znode又分为持久节点、临时节点、顺序节点三大类。
持久节点是指只要被创建,除非主动移除,否则都应该一直保存在Zookeeper中。
临时节点不同的是,他的生命周期和客户端Session会话一样,会话失效,那么临时节点就会被移除。
还有就是临时顺序节点和持久顺序节点,除了基本的特性之外,子节点的名称还具有有序性。
会话自然就是指Zookeeper客户端和服务端之间的通信,他们使用TCP长连接的方式保持通信,通常,肯定会有心跳检测的机制,同时他可以接受来自服务器的Watch事件通知。
用户可以在指定的节点上注册Wather,这样在事件触发的时候,客户端就会收到来自服务端的通知。
Zookeeper使用ACL来进行权限的控制,包含以下5种:
CREATE,创建子节点权限
DELETE,删除子节点权限
READ,获取节点数据和子节点列表权限
WRITE,更新节点权限
ADMIN,设置节点ACL权限
所以,ZooKeeper通过集群的方式来做到高可用,通过内存数据节点Znode来达到高性能,但是存储的数据量不能太大,通常适用于读多写少的场景。
Zookeeper可以提供分布式数据的发布/订阅功能,依赖的就是Wather监听机制。
客户端可以向服务端注册Wather监听,服务端的指定事件触发之后,就会向客户端发送一个事件通知。
他有几个特性:
Zookeeper通过ZAB原子广播协议来实现数据的最终顺序一致性,他是一个类似2PC两阶段提交的过程。
由于Zookeeper只有Leader节点可以写入数据,如果是其他节点收到写入数据的请求,则会将之转发给Leader节点。
主要流程如下:
Leader收到请求之后,将它转换为一个proposal提议,并且为每个提议分配一个全局唯一递增的事务ID:zxid,然后把提议放入到一个FIFO的队列中,按照FIFO的策略发送给所有的Follower
Follower收到提议之后,以事务日志的形式写入到本地磁盘中,写入成功后返回ACK给Leader
Leader在收到超过半数的Follower的ACK之后,即可认为数据写入成功,就会发送commit命令给Follower告诉他们可以提交proposal了
ZAB包含两种基本模式,崩溃恢复和消息广播。
整个集群服务在启动、网络中断或者重启等异常情况的时候,首先会进入到崩溃恢复状态,此时会通过选举产生Leader节点,当集群过半的节点都和Leader状态同步之后,ZAB就会退出恢复模式。之后,就会进入消息广播的模式。
Leader的选举可以分为两个方面,同时选举主要包含事务zxid和myid,节点主要包含3个状态
首先,每个节点都会对自己进行投票,然后把投票信息广播给集群中的其他节点
节点接收到其他节点的投票信息,然后和自己的投票进行比较,首先zxid较大的优先,如果zxid相同那么则会去选择myid更大者,此时大家都是LOOKING的状态
投票完成之后,开始统计投票信息,如果集群中过半的机器都选择了某个节点机器作为leader,那么选举结束
最后,更新各个节点的状态,leader改为LEADING状态,follower改为FOLLOWING状态
如果开始选举出来的leader节点宕机了,那么运行期间就会重新进行leader的选举。
leader宕机之后,非observer节点都会把自己的状态修改为LOOKING状态,然后重新进入选举流程
生成投票信息(myid,zxid),同样,第一轮的投票大家都会把票投给自己,然后把投票信息广播出去
接下来的流程和上面的选举是一样的,都会优先以zxid,然后选择myid,最后统计投票信息,修改节点状态,选举结束。
还是会存在的,可以分成3个场景来描述这个问题。
因为ZooKeeper是过半成功即代表成功,假设我们有5个节点,如果123节点写入成功,如果这时候请求访问到4或者5节点,那么有可能读取不到数据,因为可能数据还没有同步到4、5节点中,也可以认为这算是数据不一致的问题。
解决方案可以在读取前使用sync命令。
这也就是数据同步说过的问题。
leader刚生成一个proposal,还没有来得及发送出去,此时leader宕机,重新选举之后作为follower,但是新的leader没有这个proposal。
这种场景下的日志将会被丢弃。
如果发送proposal成功了,但是在将要发送commit命令前宕机了,如果重新进行选举,还是会选择zxid最大的节点作为leader,因此,这个日志并不会被丢弃,会在选举出leader之后重新同步到其他节点当中。
不可以。在 ZooKeeper 集群中,必须有奇数个节点才能选举出主节点。因为在偶数个节点的情况下,如果有一半的节点失去连接,集群就会失去 quorum,无法正常工作。因此,建议集群节点数为 3、5、7 等奇数个。
Zookeeper字面上理解就是动物管理员,Hadoop生态圈中很多开源项目使用动物命名,那么需要一个管理员来管理这些“动物”。
在集群的管理中Zookeeper起到非常重要的角色,他负责分布式应用程序协调的工作。
Zookeeper管理集群会选举一个Leader节点(可参考FastLeader选举算法,即快速选举Leader节点),Leader节点主要负责整个Zookeeper集群的运行管理,Follower负责管理具体的数据存储与读取。
Zookeeper主要提供以下四点功能:统一命名服务、配置管理、集群管理、共享锁和队列管理,用于高效的管理集群的运行。
1 统一命名服务
命名服务指通过指定的名字获取资源或者服务提供者的信息。分布式应用中,通常需要有一套完整的命名规则,既能够产生唯一的名称又便于识别和记忆。通常情况下使用树形的名称结构是一个理想的选择,树形的名称结构是一个有层次的目录结构,即对人友好又不会重复。
Zookeeper集群中统一由Leader节点(图中M节点)来管理所有Follower节点(图中的S1和S2节点)的命名空间。Zookeeper提供统一的命名服务,他不对外提供数据也不存储数据,他只提供一套统一的命名规则,运行在Zookeeper之上的服务需要遵循这一套命名规则。其中较为常见的就是一些分布式服务框架中的服务地址列表。通过调用ZK提供的创建节点的接口(API),能够很容易创建一个全局唯一的路径(path),这个path就可以作为一个名称。命名服务(NameService)已经是Zookeeper内置的功能,你只要调用Zookeeper的API就能实现。如调用create接口就可以很容易创建一个目录节点。
遵循Leader统一管理命名规则下,集群中数据读写的方式:
11写数据,一个客户端进行写数据请求时,会指定Zookeeper集群节点,如果是Follower接收到写请求,会把请求转发给Leader,Leader通过内部的Zab协议进行原子广播,直到所有Zookeeper节点都成功写了数据,然后Zookeeper会给Client发回写完响应。
12读数据,因为集群中Zookeeper按照统一的命名空间,所有Zookeeper节点呈现相同的命名空间视图(文件目录名称结构),所以读数据的时候请求任意一台Zookeeper节点都一样。
2 配置管理
配置的管理在分布式应用环境中很常见,例如同一个应用需要在多台服务器上运行,但是它们的应用系统的某些配置相同的,如果要修改这些相同的配置项,就必须同时修改每台运行这个应用系统的PC Server,这样非常麻烦而且容易出错。像这样的配置信息完全可以交给Zookeeper来管理,处理起来非常便捷。
配置的管理包含发布和订阅两个过程,顾名思义就是将数据发布到ZK节点上,供订阅者动态获取数据,实现配置信息的集中管理和动态更新。
如图所示,将配置信息保存在Zookeeper(Leader节点)的某一个目录中,然后将所有需要修改的应用机器订阅该Zookeeper(Leader节点)节点,一旦Leader节点发布新配置信息,每台订阅的机器就会收到Zookeeper的通知,然后从Zookeeper获取新的配置信息应用到系统中,完成配置的集中统一管理。
3 集群管理
Zookeeper在集群管理中主要是集群监控和Leader选举。
31集群管理
这通常用于那种对集群中机器状态、 , 机器在线率有较高要求的场景,能够快速对集群中机器变化做出响应。这样的场景中,往往有一个监控系统,实时检测集群机器是否存活。过去的做法通常是:监控系统通过某种手段(比如ping)定时检测每个机器,或者每个机器自己定时向监控系统汇报"我还活着"。
这种做法可行,但是存在两个比较明显的问题:
1)集群中机器有变动的时候,牵连修改的东西比较多。
2)有一定的延时。
利用ZooKeeper中两个特性,就可以实施另一种集群机器存活性监控系统:
1)客户端在示例节点A上注册一个监控者(Watcher),那么如果A的子节点变化了,会通知该客户端。
2)创建EPHEMERAL类型的节点,一旦客户端和服务器的会话结束或过期,那么该节点就会消失。
32Leader选举:
Leader选举即从大量集群节点中选举一个Leader节点,是zookeeper中最为经典的使用场景,在分布式环境中选举的Leader节点好快会直接影响集群的效率。Leader节点主要负责相同的业务应用分布在不同的机器上共用的逻辑模型和数据的调配,优秀的调配方案可以大大减少重复运算,提高性能降低集群的负载。
利用ZooKeeper中两个特性,就可以实施另一种集群中Leader选举:
1)利用ZooKeeper的强一致性,能够保证在分布式高并发情况下节点创建的全局唯一性,即:同时有多个客户端请求创建Leader节点,最终一定只有一个客户端请求能够创建成功。利用这个特性,就能很轻易的在分布式环境中进行集群的Leader选举了。
2)另外,这种场景演化一下,就是动态Leader选举。这就要用到EPHEMERAL_SEQUENTIAL类型节点的特性了,这样每个节点会自动被编号。允许所有请求都能够创建成功,但是创建节点会为每个节点安排顺序,每次选取序列号最小的那个机器作为Leader。
小结
Zookeeper作为Hadoop主要的组件,在集群管理方面为我们提供了解决方案。通过对统一命名服务、配置管理和集群管理的阅读,我们能够清晰的理解Zookeeper的核心内容。针对共享锁和队列服务偏技术实现,有兴趣的可以进一步研究。
Zookeeper在大数据集群中解决集群管理的问题,磨刀不误砍柴工,了解完工具我们下一次分享一些具体的实效应用。
ZooKeeper 节点是有生命周期的,这取决于节点的类型。在 ZooKeeper 中,节点类型可以分为持久节点(PERSISTENT )、临时节点(EPHEMERAL),以及时序节点(SEQUENTIAL ),具体在节点创建过程中,一般是组合使用,可以生成以下 4 种节点类型。
持久节点(PERSISTENT)
所谓持久节点,是指在节点创建后,就一直存在,直到有删除 *** 作来主动清除这个节点——不会因为创建该节点的客户端会话失效而消失。
持久顺序节点(PERSISTENT_SEQUENTIAL)
这类节点的基本特性和上面的节点类型是一致的。额外的特性是,在ZK中,每个父节点会为他的第一级子节点维护一份时序,会记录每个子节点创建的先后顺序。基于这个特性,在创建子节点的时候,可以设置这个属性,那么在创建节点过程中,ZK会自动为给定节点名加上一个数字后缀,作为新的节点名。这个数字后缀的范围是整型的最大值。
临时节点(EPHEMERAL)
和持久节点不同的是,临时节点的生命周期和客户端会话绑定。也就是说,如果客户端会话失效,那么这个节点就会自动被清除掉。注意,这里提到的是会话失效,而非连接断开。另外,在临时节点下面不能创建子节点。
临时顺序节点(EPHEMERAL_SEQUENTIAL)
可以用来实现分布式锁
客户端调用create()方法创建名为“_locknode_/guid-lock-”的节点,需要注意的是,这里节点的创建类型需要设置为EPHEMERAL_SEQUENTIAL。
客户端调用getChildren(“_locknode_”)方法来获取所有已经创建的子节点,注意,这里不注册任何Watcher。
客户端获取到所有子节点path之后,如果发现自己在步骤1中创建的节点序号最小,那么就认为这个客户端获得了锁。
如果在步骤3中发现自己并非所有子节点中最小的,说明自己还没有获取到锁。此时客户端需要找到比自己小的那个节点,然后对其调用exist()方法,同时注册事件监听。
之后当这个被关注的节点被移除了,客户端会收到相应的通知。这个时候客户端需要再次调用getChildren(“_locknode_”)方法来获取所有已经创建的子节点,确保自己确实是最小的节点了,然后进入步骤3。
Zookeeper是一种分布式协调服务。所谓分布式协调服务就是在分布式系统中共享配置、协调锁资源,提供命名服务。
Zookeeper的数据模型和数据结构当中的树类似,很像文件系统的目录。Zookeeper的数据存储也是基于节点,这种节点叫做Znode。Znode的引用方式是路径引用,类似于文件路径:/动物/人
常见的API:
create 创建节点
delete 删除节点
exists 判断节点是否存在
getData 获取一个节点的数据
getChildren 获取节点下的所有节点
Zookeeper客户端在请求读 *** 作的时候,可以选择是否设置Watch。Watch理解成是注册在特定Znode上的触发器。当这个Znode发生改变,即调用了create、delete、setData方法时,会触发Znode上注册的对应事件,请求Watch的客户端会接收到异步通知。
具体交互过程:
1、客户端调用getData方法,watch参数是true。服务端接到请求,返回节点数据。并且在对应的哈希表里插入被Watch的Znode路径,以及Watcher数组。
2、当被Watch的Znode已删除,服务端会查找哈希表,根据key找到该Znode对应的所有Watcher,异步通知客户端,并且删除哈希表中对应的Key-Value。
为了防止单机故障,Zookeeper可以维护一个集群。Zookeeper Service集群时一主多从结构。
更新数据时,先更新到主节点(节点指服务器,而不是Znode),再同步到从节点。
读取数据时,直接读取任意从节点。
为保证主从节点的数据一致性,Zookeeper采用了ZAB协议,这种协议非常类似于一致性算法Paxos和Raft。
ZAB即Zookeeper Atomic Broadcast,有效解决了Zookeeper集群崩溃恢复以及主从同步数据的问题。
Zab协议既不是强一致性,也不是弱一致性,而是处于两者之间的单调一致性。它依靠事务ID和版本号,保证了数据的更新和读取是有序的。
ZAB协议所的三种节点状态:
1)Looking:选举状态
2)Following:Follower节点(从节点)所处的状态
3)Leading:Leader节点(主节点)所处状态
三种算法:leaderElection/AuthFastLeaderElection/FastLeaderElection
1)Leader election
3)Discovery
4)Synchronization
Zookeeper常规情况下更新数据的时候,由Leader广播到所有Follower。其过程如下:
1)客户端发出写入数据请求给任意Follower
2)Follower把写入数据请求转发给Leader
3)Leader采用二阶段提交方式,先发送Propose广播给Follower。
4)Follower接到Propose消息,写入日志成功后,返回ACK消息给Leader
5)Leader接到半数以上ACK消息,返回成功给客户端,并且广播Commit请求给Follower。
原文链接: >
分布式锁: 分布式锁是控制分布式系统之间同步访问共享资源的一种方式,如果不同的系统化或者同一个系统的不同主机之间共享一个或者一组资源,那么在访问这些资源的时候,往往需要通过一些互斥手段防止彼此之间的干扰,以保证一致性,这种情况就需要使用分布式锁。
排他锁: 核心是如何保证当前有且仅有一个事务获取到锁,并且锁释放之后,所有正在等待获取锁的事务都能够被通知到。
定义和获取锁: 在zk中,通过一个数据节点来表示一个锁(因为在zk中数据节点是唯一的),zk会保证在所有客户端中,最终只有一个客户端能够创建一个节点成功,最终只有一个客户端能够创建成功,那么久可以认为这个客户端获得了锁。同时没有获取到锁的客户端就需要到相应节点上注册一个子节点变更的watcher监听,以便实时的监听lock节点的变更情况。
释放锁: 由于定义锁的节点是一个临时节点,因此存在两种情况释放锁1、当前获取锁的客户端机器发生宕机了。zk就会把该临时节点删除2、正常执行完业务逻辑,客户端会主动将自己创建的临时节点删除。而无论什么情况下面删除了节点,zk都会通知所有在该节点上注册了子节点变更watcher将的客户端。这些客户端在接收到通知后,会再次重新发起分布式锁获取,即重复“获取锁过程”。
(获取锁和释放锁流程)
共享锁: 称读锁。如果事务T对数据对象O加了共享锁,那么当前的事务只能对O进行读取 *** 作,其他事务也只能对这个数据对象加共享锁-直到该数据对象上的所有共享锁都被释放。
定义锁: 同样是使用zk上的数据节点来表示一个锁,是一个类似“/share_lock/[hostname]-请求类型-序号”的临时顺序节点。
获取锁: 在需要获取共享锁时候,所有客户端都会到/share_lock这个节点下面创建一个临时顺序节点,如果当前是读请求,那么就是例如/share_lock/19216801-R-0000000001的节点;如果是写请求,那么就会创建例如/share_lock/19216801-W-0000000001的节点。
判断读写顺序: 不同事务都可以同时对一个数据对象进行读写 *** 作,而更新 *** 作必须在当前没有任何事务进行读写 *** 作的情况下面进行。基于这个原则可以通过下面四个步骤来确定分布式读写顺序:
释放锁: 和排他锁一样。
加锁情况:
(1)实现流程
(2)源码解读
1、InterProcessMutex构造函数
2、加锁
InterProcessMutexclass
3、锁的可重入性
4、抢夺锁
参考资料:
《从Paxos到Zookeeper 分布式一致性原理与实践》》
>
主动到服务端拉取。客户端接收到这个消息通知之后,再次调用getData接口来获取新的数据内容,需要主动到服务端获取最新的数据。zk主动到服务端拉取保证收到通知后才能获取最新数据。zk是一个文件目录,里面只能存储少量的数据。目录中的每一个节点(每一个文件或者文件夹)称之为node。
以上就是关于ZooKeeper - 常见问题全部的内容,包括:ZooKeeper - 常见问题、zk集群2个节点能选主吗、大数据Hadoop之ZooKeeper认识等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)