Zookeeper学习

1. 什么是zookeeper?
zookeeper是一个分布式的,开源的"分布式应用程序协调服务"。它包含了一个简单的原语集,分布式应用程序可以基于它实现同步服务、配置维护、命名服务等。
zookeeper是hadoop的一个子项目。在分布式应用中,由于工程师不能很好滴使用“锁”机制,以及基于消息的协调机制不适合在某些应用中使用,因此,需要有一种可靠的、可扩展的、分布式的、可配置的协调机制来统一系统的状态。zookeeper的目的就在于此。

2. zookeeper中的角色
    -- 领导者(leader): 负责进行投票的发起和决议,更新系统状态
    -- 学习者(Learner):
        -- 跟随者(Follower): Follower用于接手客户请求,并向客户端返回结果,在选主过程中参与投票。
        -- 观察者(Observer): Observer可以接手客户端连接,将写请求转发给leader节点。但observer不参与投票,只同步leader的状态。observer的目的是为了扩展系统,提高读取速度。
    -- 客户端(Client):请求发起方

3. zookeeper的设计目的
    -- 最终一致性:client无论连接到哪个server,展示给它的都是同一个视图,这是zookeeper的最重要的功能。
    -- 可靠性:具有简单、健壮、良好的性能,如果消息m被一台服务器接收,那么它将被所有的服务器接收。
    -- 实时性:zookeeper保证客户端将在一个时间间隔范围内,获得服务器的更新信息,或者服务器失效的信息。但由于网络延时等原因,zookeeper不能保证两个客户端能同事得到刚更新的数据,如果需要更新最新数据,应该在读数据之前调用sync()接口
    -- 等待无关(wait-free): 慢的或者失效的client不得干预快速的client的请求,使得每个client都能有效的等待。
    -- 原子性:更新只能成功或者失败,没有中间状态
    -- 顺序性:包括全局有序和偏序两种:
        -- 全局有序:如果一台服务器上消息a在消息b前发布,则在所有server上消息a都在b前被发布
        -- 偏序:如果一个消息b在消息a后被同一个发送者发布,a必将排在b前面。

4. zookeeper的工作原理
zookeeper的核心是原子广播,这个机制保障了各个server之间的同步。实现这个机制的协议叫Zab协议。zab协议有两者模式:恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,zab就进入了恢复模式,当领导者被选出来后,且大多数server完成了和leader的状态同步后,恢复模式就结束了。状态同步保证了leader和server具有相同的系统状态。

为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都要在被提出的时候加上zxid. 实现中的zxid是一个64位的数字,它的高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它会有一个新的epoch. 低32位用于递增计数。

每个server的工作过程中有三种状态:
    -- looking: 当前server不知道leader是谁,正在搜寻。
    -- leading: 当前server纪委选举出来的leader
    -- following: leader已经选举出来,当前server与之同步。

4.1 选主流程
当leader崩溃或者leader失去大多数的follower, 这时zookeeper进入恢复模式,需要重新选举出一个新的Leader,让所有的server都恢复到一个正确的状态。
zookeeper的选举算法有两种:
    -- basic paxos
    -- fast paxos (系统默认算法)
1)basic c:
    -- 选举线程由当前server发起选举的线程担任,其主要作用是对投票结果进行统计,并选出推荐的server
    -- 选举线程首先向所有的server发起一次询问(包括自己)
    -- 选举线程收到回复后,验证是否是自己发起的询问(验证zxid是否一致),然后获取对方的id(myid), 并存储到当前询问对象列表中,最后获取对方提议的leader的相关信息(id, zxid), 并将这些信息存储到当次选举的投票记录表中。
    -- 收到所有server的回复后,就计算出zxid最大的那个server, 并将这个server相关信息设置成下一次要投票的server.
    -- 线程将当前zxid最大的server设置为当前server要推荐的Leader,如果此时获胜的server获得大于或等于n/2 + 1的server票数,设置当前推荐的Leader为获胜的leader,将根据获胜的server相关信息设置自己的状态,否则,继续这个过程,直到leader被选举出来。

2)fast paxos: 在选举过程中,某server首先向所有server提议自己要成为leader, 当其他server收到提议后,解决epoch和zxid的冲突,并接受对方的提议,然后想对方发送接受提议完成的消息,重复这个流程,最后一定能选举出Leader。

4.2 同步流程
选完Leader后,zookeeper就进入同步过程
    -- leader等待server连接
    -- follwer连接leader,将最大的zxid发送给leader
    -- leader根据follower的zxid确定同步点
    -- 完成同步后,通知follower已经成为up-to-date状态
    -- follwer收到up-to-date消息后,又可以重新接受client的请求了。

4.3 工作流程
4.3.1 leader工作流程
    -- 恢复数据
    -- 维持与learner的心跳,接收learner请求,并判断learner的请求消息类型
    -- learner的消息类型主要有ping消息,request消息,ack消息,revalidate消息,根据不同的消息类型,进行不同的处理。
    ping消息是指learner的心跳信息,request消息是follwer发送的提议消息,包括写请求与同步请求,ack消息是对follower提议的回复,超过半数的follower通过,则commit该提议,revalidate消息用来延长session有效时间。
4.3.2 follower的工作流程
    -- 向leader发送请求(ping消息,request消息,ack消息,revalidate消息)
    -- 接收leader消息并进行处理
    -- 接收client请求,如果为写请求,发送给leader进行投票
    -- 返回client结果

observer和follower唯一的不同是,observer不会参与Leader发起的投票

5. zookeeper的主流应用场景
1)配置管理
集中式配置管理在应用集群中是非常常见的,一般商业公司内部都会实现一套集中的配置管理中心,应对不同的应用集群对于共享各自配置的需求,并且在配置变更时,能够通知到集群中的每一个机器。
zookeeper很容易实现这种集中式的配置管理,(app1是个集群,"/App1 znode"是集群中的一个节点)比如讲app1所有的配置 配置到 “/App1 znode"下,app1所有机器一启动,就对/App1 znode这个节点进行监控(zk.exist("/App1", true)), 并且实现回调方法watcher,那么zookeeper上"/App1 znode"节点下的配置数据发生变化时,app1集群的每个机器都会收到通知,watcher方法将会被执行,那么应用再取下数据即可(zk.getData("/App1", false, null))

2) 集群管理
应用集群中,我们常常需要让每一个机器知道集群中哪台机器是活着的,并且在集群机器因为宕机,网络中断等原因,能够不在人工介入的情况下,迅速通知到每一台机器。

zookeeper很容易实现这个功能。例如,在zookeeper服务器端有一个节点(znode)叫/app1ervers, 那么集群中每一个机器启动的时候,都去这个节点下创建一个临时节点(ephemeral),比如server1创建/app1serer/server1(可以使用ip, 保证不重复),server2创建/app1server/server2,然后server1和server2都watch /app1servers这个父节点,那么也就是这个父节点下的数据或者子节点变化都会通知该节点进行watch客户端。因为ephemeral类型的节点有一个重要特征,就是客户端和服务器端连接或者断掉或者session过期,都会使节点消失,那么在某一个机器挂掉或者断链的生活,其对应的节点就会消失,然后集群中所有对/app1servers进行watch的客户端都会收到通知,然后获取最新列表即可。

另外有一个应用场景就是集群选master,一旦master挂掉能够马上能从slave中选出一个master,实现步骤和前者一样,只是机器在启动的时候在APP1SERVERS创建的节点类型变为EPHEMERAL_SEQUENTIAL类型,这样每个节点会自动被编号

我们默认规定编号最小的为master,所以当我们对/APP1SERVERS节点做监控的时候,得到服务器列表,只要所有集群机器逻辑认为最小编号节点为master,那么master就被选出,而这个master宕机的时候,相应的znode会消失,然后新的服务器列表就被推送到客户端,然后每个节点逻辑认为最小编号节点为master,这样就做到动态master选举。









猜你喜欢

转载自doudou-001.iteye.com/blog/2284748