从Paxos到ZooKeeper-初识ZooKeeper

来源:互联网 发布:初中生编程 编辑:程序博客网 时间:2024/06/04 01:35

一、初识ZooKeeper

1.ZooKeeper介绍

    ZooKeeper是一个开源的分布式协调服务,由雅虎公司创建,其设计目标是将复杂易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,以一系列简单易用的接口提供的用户使用

    雅虎研究院的研究人员发现雅虎内部很多大型系统都需要依赖类似的系统进行分布式协调,但这些系统往往存在单点问题,所以他们就希望开发一个通用的无单点问题的分布式协调框架,使开发人员集中精力处理业务逻辑

(1)ZooKeeper保证的特性

  • 顺序一致性

        由同一个客户端发起的事务请求严格按照其发起顺序应用到ZooKeeper中

  • 原子性

        事务请求的处理结果在集群中的所有机器上的应用情况一致,也就是说所有机器都成功应用了某个事务或都没有应用某个事务

  • 单一视图

        无论客户端连接的是ZooKeeper集群中哪个服务器看到的服务端数据模型都是一致的

  • 可靠性

        服务端成功应用事务后,事务对服务端状态的变更将一直保留下来,除非另一个事务再次操作相关数据

  • 实时性

        ZooKeeper能够保证在一定时间段内,客户端最终一定能够从服务端读取到最新的数据状态

(2)ZooKeeper设计目标

    ZooKeeper致力于提供高可用、高性能、具有严格顺序访问控制的分布式协调服务

  • 简单数据模型

        ZooKeeper使分布式程序能够通过一个共享的、树形结的名字空间来进行相互协调

        树形结构的名字空间是指ZooKeeper服务器内存中的一个数据模型,由系列ZNode数据结构组成,类似于文件系统,但是和磁盘文件系统不同的是,ZooKeeper将全量数据存储在内存中来实现高吞吐量,减少延时的目的

  • 能够构建集群

        组成ZooKeeper集群的每台机器都会在内存中维护当前的服务器状态,相互通信,只要集群中超过一半的机器能够正常运行,整个集群就能够对外正常提供服务

        客户端程序选择集群中任何一台及其创建TCP连接,一旦连接断开,客户端会自动连接到集群中的其他机器

  • 顺序访问

        对于客户端的情求,ZooKeeper会分配一个全局唯一的递增编号,通过编号来反映事务操作的先后顺序

  • 高性能

        ZooKeeper将全量数据存储在内存中,直接服务于客户端的所有非事务请求,尤其适合以读操作为主的应用场景

2. ZooKeeper中的基本概念

  • 集群角色

        通常在分布式系统中,集群中每台机器都有自己的角色,如典型的Master/Slave模式中将能够处理写操作的机器称为Master,通过异步复制方式获取最新数据提供读服务的机器称为Slave

        而在ZooKeeper中,引入了Leader、Follower、Observer三个角色。Leader服务器为客户端提供读写服务,Follower和Observer都能提供读服务,但是Observer不参与Leader选举过程,也不参与写操作的”过半写成功”策略,能够在不影响写性能的情况下提升读性能

  • 会话

        ZooKeeper中,客户端和服务器之间建立了TCP长连接,在第一次建立连接开始,会话的生命周期也随之开始。客户端和服务器使用心跳检测保持有效会话,客户端向ZooKeeper服务器发送请求并接受响应,以及接受来自服务器的Watch事件通知都通过该连接实现

        会话可以通过sessionTimout值来设置客户端会话的超时时间,客户端连接断开后只要在sessionTimeout时间内连接上集群中任何一台服务器,则之前创建的会话仍然有效

  • 数据节点

        ZooKeeper中节点分为两类:构成集群的机器(及机器节点)、数据模型中的数据单元(数据节点)

        ZooKeeper中的数据模型是一棵树,由/进行分割的路径就是一个数据节点Znode,每个Znode都会保存自己的数据内容及系列属性信息

        对于数据节点也有分类:持久节点、临时节点。其中持久节点是指一旦节点创建后,除非主动进行ZNode的移除操作,否则将该ZNode将一直保存在ZooKeeper上;临时节点的生命周期和客户端会话绑定,一旦会话失效,客户端创建的所有临时节点都会移除

  • 事件监听器

        事件监听器Watcher是ZooKeeper中的重要特性,ZooKeeper允许用户在指定节点上注册Watcher,在特定事件触发时,ZooKeeper服务端会将事件通知到感兴趣的客户端上去。

        该机制是ZooKeeper实现分布式协调服务的重要特性

  • ACL(Access Control Lists 访问控制列表)

        ZooKeeper采用ACL策略进行权限管理,定义了CREATE、READ、WRITE、DELETE、ADMIN(设置节点ACL的权限)五种权限

二、ZooKeeper的ZAB协议

1. ZAB协议简介

    上节从Paxos到ZooKeeper-一致性协议之Paxos算法中讲到过Paxos算法,但ZooKeeper并没有完全采用Paxos而是使用了ZooKeeper Atomic Broadcast(ZooKeeper原子消息广播协议)作为其数据一致性的核心算法,ZAB不向Paxos算法那样作为一种通用的分布式一致性算法,而是特别为ZooKeeper设计的奔溃可恢复的原子消息广播算法,基于ZAB协议,ZooKeeper实现了一种主备模式的系统框架来保持集群中各副本之间数据的一致性

    ZooKeeper使用单一的主线程接受并处理客户端的所有事务请求,并采用ZAB原子广播协议将服务器数据状态变更以事务Proposal的形式广播道所有副本进程中

    由于在分布式环境中,顺序执行的状态变更之间可能存在一定依赖,所以需要ZAB协议能够保证全局的变更序列被顺序应用,某个状态变更执行前它所依赖的变更都应该被处理了

    主进程在任何时候都可能崩溃退出或重启,因此ZAB协议需要能够保证在出现主进程出现异常情况是系统依然能够正常工作

2. 协议简单介绍

    ZAB协议的核心是定义了改变ZooKeeper服务器数据状态的事务请求的处理方式

所有事物请求由全局唯一的Leader服务器处理,而余下服务器则称为Follower服务器
Leader服务器负责将客户端事务请求转换成一个事务Proposal,并将Proposal分发给所有Follower服务器
Leader服务器等待Follower服务器反馈,当超过半数的Follower服务器正确反馈后,Leader向所有Follower发送Commit消息,要求将前一个Proposal进行提交

    ZAB协议包括两种基本模式:崩溃恢复和消息广播。当Leader服务器出现网络终端、崩溃退出或重启等情况时,ZAB协议会从消息广播模式进入恢复模式选举产生新的Leader服务器,当选举产生了新的leader服务器并且集群中已经有超过半数的机器与新Leader服务器完成了数据同步后,ZAB协议退出恢复模式进入消息广播模式

    当新的ZooKeeper服务器启动后加入集群中如果集群中已经存在Leader服务器在进行消息广播,则新加入的服务器就会找到Leader所在服务器,并与其进行数据同步后参与到消息广播流程中去

    Leader服务器接收到客户端事务请求后会生成事务提案并发起一轮广播协议;如果集群中其他机器接收到客户端事务请求,则会首先将该事务请求转发给Leader服务器

    机器要成为新的Leader,必须获取过半进程(包括Leader自己)的支持,在ZAB协议运行过程中,前后会出现多个Leader,同一个进程也可能多次成为Leader

(1)消息广播

    ZAB协议的消息广播过程使用的是一个原子广播协议,类似于2PC,2PC相关内容在从Paxos到ZooKeeper-一致性协议之2PC、3PC中有讲到,消息广播协议是基于具有FIFO特性的TCP协议来进行网络通信的,所以能够保证消息广播过程中接受和发送的顺序性

    针对客户端的事务请求,Leader服务器会为其生成对应的事务Proposal,在广播Proposal之前会为事务分配一个全局递增的唯一ID(ZXID事务ID),并且在消息广播过程中,为每个Follower分配独立的队列,根据FIFO将Proposal放入队列中,将其发送给Follower机器;Follower接收到事务Proposal后首先以事务日志形式写入到本地磁盘,写入成功后反馈Ack响应给Leader服务器;当Leader服务器接收到半数以上Ack响应后会广播Commit消息给Follower通知进行事务提交,同时Leader自身也会完成对事务的提交

    与2PC不同的是,在ZAB协议的二阶段提交过程中,移除了中断逻辑,当过半的Follower服务器反馈Ack之后就开始提交事务Proposal,而这种简化的2PC无法处理Leader崩溃导致的数据不一致问题,所以引入了崩溃恢复模式

(2)崩溃恢复

    为了保证程序的正确运行,整个恢复过程结束后就需要选举出一个新的Leader服务器,ZAB协议需要高效且可靠的Leader选取算法,算法不仅仅需要让Leader自己知道自身已经被选,还需要让集群中的其他机器也能快速感知到新的Leader服务器

  • 基本特性

    ZAB协议的原子性规定了事务Proposal如果在一台机器上被处理成功,则在所有机器上都被处理成功,针对这种情况ZAB协议需要满足如下特性:

    • 确保已经在Leader上提交的事务最终被所有服务器提交

          假设事务得到了过半Follower的Ack反馈,但是Leader在将Commit发送给所有Follower之前就挂掉了(只发送了部分),ZAB协议需要保证事务最终能够在所有服务器上都被提交成功

    • 确保跳过那些已经被丢弃的事务

          假设Leader在提出了事务Proposal后就奔溃退出了,导致集群中其他服务器都没有收到该Proposal,则当之前作为Leader的机器恢复后加入到集群中时,ZAB协议需要保证丢失该Proposal

    *   针对以上要求,只需要让Leader选举算法能够保证选举出来的Leader服务器具有集群中所有机器中事务编号最高的Proposal就能够使得新Leader一定具有所有已经提交的Proposal

        举个栗子:假设上一个Leader提交了事务Proposal 1,2,3,当发送了部分Proposal3的Commit请求,提出事务Proposal4 的时候挂掉了,这个时候,集群中有部分机器了事务Proposal3的Commit消息而没有任何一台机器收到事务Proposal4,所以说在剩下的集群机器中,事务编号最大的就是Proposal3,根据ZAB保证的顺序性,Proposal1,2肯定也已经提交了,所以选择拥有最大编号3的机器一定具有所有已经提交的提案

  • 数据同步

        当完成Leader选举后,Leader服务器会首先确认事务日志中是否所有都已经被集群中过半的机器提交(是否完成数据同步)

        Leader服务器会为每个Follower服务器准备队列,并且将那些没有被各Follower同步的事务以Proposal消息的形式逐个发送给Follower服务器,接着紧跟一个Commit消息,当Follower服务器将所有未同步的事务同步过来并成功应用后,Leader服务器就会将该Follower服务器加入真正可用的Follower列表中

        上面是上一个Leader服务器Commit消息未发完全的正常情况下的数据同步逻辑,下面则是需要被丢弃的事务的数据同步逻辑

        ZAB协议的事务编号ZXID是一个64位的数字,其中高32位代表了Leader周期epoch的编号,当新的Leader被选取出来后会从本地日志中取出最大ZXID解析出上个Leader后期的epoch编号并进行加一操作,然后将后32为置0单调递增来生成新的ZXID。epoch编号能够区分Leader周期变化,避免不同Leader服务器提出相同ZXID编号,

        当包含上一个Leader周期中未提交过的食物Proposal的服务器启动后肯定无法成为Leader(当前集群中肯定有机器包含了拥有更高epoch的事务),而是作为Follower连接上Leader服务器,Leader服务器则会根据自己服务器上最后被提交的Proposal和该Follower对比,从而使得该Follower机器进行一个个回退操作,直到回退到被过半机器提交的最新的事务Proposal为止

        只有在充分完成崩溃恢复阶段后,新的主进程才可以生成新的事务消息广播

3.深入ZAB协议

    整个ZAB协议主要包括消息广播和崩溃恢复两个过程,进一步细分则可以分为三个阶段:发现、同步和广播,组成ZAB的每个分布式进程都会循环执行这三个阶段,这样的一个循环即为一个主进程周期

(1)发现

    阶段一主要就是Leader选举过程

Follower F将自己最后接受的事务Proposal的epoch值发送给准Leader L

准Leader L接受到过半Follower发送的epoch值后选择其中最大的epoch+1生成新的epoch值后再发送给这些Follower

Follower接受到新的epoch消息后,如果检测到当前epoch小于新的epoch,就将epoch赋予为新的epoch,同时向准Leader L发送Ack消息,该消息中包含了Follower更新后的epoch以及历史事务Proposal集合

Leader收到过半Follower的Ack后,从中选取一个Follower F(拥有最大的ZXID)使用其作为初始化事务集合I

(2)同步

    完成发现流程后则进入同步阶段

Leader L结合epoch和事务集合I为一个消息发送给所有Follower

Follower接收到Leader L的消息后,如果发现自身epoch不等于Leader发送消息中的epoch,就直接进入下一轮主进程周期循环;如果自身epoch等于Leader发送消息中的epoch,就会执行事务应用操作,然后反馈给Leader,表明自己已经接受并处理了所有事务Proposal

当Leader接收到过半Follower的反馈消息后,向所有Follower发送Commit消息

Follower接收到来自Leader的Commit消息后,依次处理并提交所有在事务集合I中未处理的事务

(3)广播

    完成同步阶段后,ZAB协议就可以开始接受客户端新的事务请求并进行消息广播

Leader L接受到客户端新的事务请求后,生成对应的事务Proposal,根据ZXID的顺序向所有Follower发送
Follower根据消息接受的先后顺序处理事务Proposal,并将其追加到自身已经处理过的事务集合中去(历史记录),之后再反馈给Leader
当Leader接收到过半Follower的Ack消息后会发送Commit消息给所有Follower,要求它们进行事务的提交
Follower F接受到Commit消息后,就会开始提交事务

这里写图片描述

    只有完成第二阶段即同步阶段,准Leader进程才能真正成为新的主进程周期的Leader

    在ZAB协议中,每个进程都可能处于三种状态:LOOKING、FOLLOWING、LEADING,其中LOOKING为Leader选举阶段,ZAB运行过程中,每个进程在这三个状态之间不断的转换

    Leader进程和所有Follower进程都会维持心跳检测,如果Leader在超时时间内无法从过半的Follower中检测到心跳,则Leader就会终止对当前周期的领导,并转入LOOKING状态;所有Follower也会放弃该Leader,同时转换到LOOKING状态,进行新一轮选举

4. ZAB和Paxos算法的联系与区别

(1)联系

两者都存在类似Leader的角色,负责协调多个Follower进程
Leader进程都会等待超过半数的Follower做出正确响应才提交提案

(2)区别

    Paxos算法中,主进程会进行两个阶段的工作:和其他进程通信收集上一个主进程提出的提案(读阶段);主进程提出自己的提案(写阶段)。而在Paxos算法基础上,ZAB协议添加了同步阶段(确保所有进程都完成之前所有事务的提交),同步阶段前,执行和Paxos读阶段类似的发现阶段;同步阶段后就会执行和Paxos算法类似的写阶段

    总的来讲,ZAB协议主要用于构建高可用的分布式数据主备系统;Paxos算法用与构造一个分布式一致性状态机系统

阅读全文
0 0
原创粉丝点击