Zookeeper

一、What

  • 一个主从架构的分布式框架
  • 给分布式框架提供协调服务(service)

作用

  • 提供简版文件系统来存储数据
  • 维护和监控存储的数据状态变化,通过监控数据状态变化达到基于数据的集群管理
  • 主要用来解决分布式集群中应用系统的一致性问题

应用场景

1. 主备切换
2. 节点的上下线感知
3. 统一命名服务
4. 状态同步服务
5. 集群管理
6. 分布式应用配置管理

二、基本概念

ZooKeeper=简版文件系统(Znode)+原语+通知机制(Watcher)

  • ZK文件系统
    基于类似于文件系统的目录节点树方式的数据存储
  • 原语
    提供类linux指令进行操作
  • Watcher(监听器)

数据节点ZNode

数据节点本质就是目录

持久节点 临时节点
非有序节点 create create -e
有序节点 create -s create -s -e
  1. 持久节点(无序)
    节点创建以后,即便连接断开,除非主动删除,不然会一直存在
  2. 持久节点(有序)
    创建节点的时候加上 -s ,会默认的在目录后加上数字
    防止同一目录创建同名ZNode导致失败
  3. 临时节点(无序)
    节点创建以后,一旦连接断开会自动删除
    创建节点的时候通过 -t 指定
  4. 持久节点(有序)
    同上

会话

与zk交互时会建立TCP长连接,称为会话
建立会话后,如果超过SessionTimeout时间,两者间没有通信,会话超时
特点:同一个会话里执行的指令是有序的;不同会话之间的指令是无序的

事务zxid

  • 每个对数据的增删改操作都会生成一个对应的zxid
  • zxid全局唯一,并且是自增的
  • zxid通常是由64位数字,epoch+counter组成

Watch监视与通知

方式一(轮询):ZooKeeper以远程服务的方式,被客户端访问;客户端以轮询的方式获得znode数据,效率会比较低(代价比较大)

方式二(通知机制):客户端在znode上注册一个Watcher监视器,当znode上数据出现变化,watcher监测到此变化,通知客户端

  1. Watch作用流程
  • 客户端在服务器端,注册的事件监听器
  • watcher用于监听znode上的某些事件
  • 比如znode数据修改、节点增删等
  • 当监听到事件后,watcher会触发通知客户端
  1. 节点上下线原理
    ① 节点1(client1)创建临时节点
    ② 节点2(client2)在临时节点,注册监听器watcher
    ③ 当client1与zk集群断开连接,临时节点会被删除
    ④ watcher发送消息,通知client2,临时节点被删除的事件
    用到的zk特性:Watcher+临时节点
    好处:通过这种方式,检测和被检测系统不需要直接关联(如client1与client2),而是通过ZK上的某个节点进行关联,大大减少了系统耦合

三、HDFS HA方案

工作原理

ZooKeeper使用原子广播协议叫做Zab(ZooKeeper Automic Broadcast)协议

  • Zab协议有两种模式
    • 恢复模式(选主):因为ZooKeeper是主从架构;当ZooKeeper集群没有主的角色leader时,从众多服务器中选举leader时,处于此模式
    • 广播模式(同步):当集群有了leader后,客户端向ZooKeeper集群读写数据时,集群处于此模式
  • 为了保证事务的顺序一致性,ZooKeeper采用了递增的事务id号(zxid)来标识事务,所有提议(proposal)都有zxid

监听器

  • 注册:客户端向ZooKeeper集群注册监听器

  • 监听事件:监听器负责监听特定的事件

  • 回调函数:当监听器监听到事件的发生后,调用注册监听器时定义的回调函数

HA原理

HDFS HA方案,主要分两部分:

①元数据同步

  • 在同一个HDFS集群,运行两个互为主备的NameNode节点。
  • 一台为主Namenode节点,处于Active状态,一台为备NameNode节点,处于Standby状态。
  • 只有Active NameNode对外提供读写服务,Standby NameNode会根据Active NameNode的状态变化,在必要时切换成Active状态。
  • JournalNode集群
    • 在主备切换过程中,新的Active NameNode必须确保与原Active NamNode元数据同步完成,才能对外提供服务
    • 所以用JournalNode集群作为共享存储系统;
    • 当客户端对HDFS做操作,会在Active NameNode中edits.log文件中作日志记录,同时日志记录也会写入JournalNode集群;负责存储HDFS新产生的元数据
    • 当有新数据写入JournalNode集群时,Standby NameNode能监听到此情况,将新数据同步过来
    • Active NameNode(写入)和Standby NameNode(读取)实现元数据同步
    • 另外,所有datanode会向两个主备namenode做block report

②主备切换

  • 每个NameNode节点上各有一个ZKFC进程
  • ZKFC即ZKFailoverController,作为独立进程存在,负责控制NameNode的主备切换
  • ZKFC会监控NameNode的健康状况,当发现Active NameNode异常时,通过Zookeeper集群进行namenode主备选举,完成Active和Standby状态的切换
    • ZKFC在启动时,同时会初始化HealthMonitor和ActiveStandbyElector服务
    • ZKFC同时会向HealthMonitor和ActiveStandbyElector注册相应的回调方法(如上图的①回调、②回调)
    • HealthMonitor定时调用NameNode的HAServiceProtocol RPC接口(monitorHealth和getServiceStatus),监控NameNode的健康状态,并向ZKFC反馈
    • ActiveStandbyElector接收ZKFC的选举请求,通过Zookeeper自动完成namenode主备选举
    • 选举完成后回调ZKFC的主备切换方法对NameNode进行Active和Standby状态的切换

主备切换过程

  • ① 启动NameNode,ZKFC,此时两个NameNode的状态都是竞选状态
  • ② 两个ZKFC分别通过ActiveStandbyElector发起NameNode的选举
    通过zookeeper的写一致性以及临时节点来实现
  • ③ 发起主备选举的时候,ActiveStandbyElector会尝试在zookeeper的某个目录下创建一个临时节点,zookeeper的写一致性会保证只有一个节点创建成功
  • ④ 创建成功的ActiveStandbyElector通过回调方式通知ZKFC,将对应的NameNode切换为Active状态;创建失败的也通过同样方式将NameNode切换为Standby状态
  • ⑤ 无论是否创建成功,这些ActiveStandbyElector都会监听那个目录;
    当Active NameNode对应的HealthMonitor监控到NameNode异常时,会告知ZKFC,ZKFC通过ActiveStandbyElector删除所创建的临时节点,以及目录A
    若是ZKFC是因为异常断开的连接,那么目录A还会存在
  • ⑥ 此时处于Standby的NameNode会监控到这个消息
    它首先会通过判断目录A是否存在来确认情况
    如果是正常关闭的,则发起主备选举,成功创建临时节点,并且将NameNode的状态切换为Active
    如果是异常关闭的,则会
    1、通过RPC调用,试图让之前的Active的NameNode切换为StandBy
    2、隔离:① 发送kill指令 ② 使用hadoop的隔离方式

脑裂
在分布式系统中双主现象又称为脑裂,由于Zookeeper的“假死”、长时间的垃圾回收或其它原因都可能导致双Active NameNode现象,此时两个NameNode都可以对外提供服务,无法保证数据一致性

  • 隔离
    对于生产环境,这种情况的出现是毁灭性的,必须通过自带的隔离(Fencing)机制预防此类情况
  • 原理
    • ActiveStandbyElector成功创建ActiveStandbyElectorLock临时节点后,额外创建一个ActiveBreadCrumb持久节点

    • ActiveBreadCurmb持久节点保存Active NameNode的服务器信息

    • 当Active NameNode正常状态下断开与Zookeeper Session,会一并删除临时节点ActiveStandbyElectorLock和ActiveBreadCurmb持久节点

    • 如果是异常断开的,那么此时临时节点ActiveStandbyElectorLock不存在,但是ActiveBreadCurmb持久节点还存在;Standby节点会收到监听器发来的提醒将要从Standby切换成Active时,会先通过ActiveBreadCurmb里的服务器信息做隔离
      1、通过RPC调用,试图让之前的Active的NameNode切换为StandBy
      2、隔离(hadoop提供这两种隔离):① 发送kill指令 ② 使用hadoop的隔离方式

      只有成功地fencing之后,选主成功的ActiveStandbyElector才会回调ZKFC的becomeActive方法transitionToActive将对应的NameNode切换为Active,开始对外提供服务

四、Zookeeper架构

ZooKeeper服务器四种状态:

  • looking:服务器处于寻找Leader群首的状态

  • leading:服务器作为群首时的状态

  • following:服务器作为follower跟随者时的状态

  • observing:服务器作为观察者时的状态

1、安其内

全新leader选举(重启集群)
原则:集群超过半数的服务器启动后,才能选出leader
选举规则:

  1. 初始化:每个节点都投自己一票,然后向其他所有节点发送自己票的信息
  2. 交换投票信息:接收其他节点的选举信息,与自己的那票进行比较
    投票信息vote信息结构为(serverId, zxid)
    会先比较zxid,zxid大的那台服务器胜出(zxid越大意味存储了更多的数据)
    若是zxid相同则serverId大的那台服务器会胜出
    比较结束后,每台服务器会更新自己的投票信息,继续给其他服务器发送
  3. 决定投票结果:假设服务器B接收到超过半数的票选举自己,则自己从looking切换为leading,其他服务器从looking切换为following
  4. 当服务器C启动时,发现已有Leader,不再选举,直接从Looking改为Following

全新leader选举(leading挂掉或者出现网络分区)

攘其外

读操作

  • 常见的读取操作,如ls /查看目录;get /zktest查询ZNode数据
  • 读操作
    • 客户端先与某个zk任意一台服务器建立Session
    • 然后,直接从此ZK服务器读取数据,并返回客户端即可
    • 关闭Session

写操作

  • ① 与zk任意一台服务器建立Session建立连接
  • ② follower将写请求转发给leader(不执行)
  • ③ leader收到消息后,发起proposal提案
  • ④ 每台服务器都会收到proposal后会记录这次操作并向leader返回同意,但不执行
  • ⑤ 超过半数quorum同意,则leader提交commit提案,leader执行该操作
  • ⑥ leader通知所有节点也commit提交该提案;所有节点在所在服务器执行该操作
  • ⑦ client连接的那台follower响应Client

五、原理

quorum仲裁

  • 什么是仲裁quorum?
    • 发起proposal时,只要多数派同意,即可生效
  • 为什么要仲裁?
    • 多数据派不需要所有的服务器都响应,proposal就能生效
    • 提高集群的响应速度
  • quorum数如何选择?
    • 集群节点数 / 2 + 1

为什么集群节点数强烈建议奇数个?
5节点的比6节点的集群

  • 容灾能力一样,
  • quorum小,响应快
  • 偶数个如果被网络分区平分,则不能提供服务

网络分区和脑裂

  • 网络分区:网络通信故障,集群被分成了2部分
  • 脑裂:
    • 原leader处于一个分区;
    • 另外一个分区选举出新的leader
    • 集群出现2个leader

ZAB算法

  1. 每个节点都有一个计时器(150毫秒~300毫秒之间的随机数),时间到后会发起选举的操作

  2. 非leader节点会定时的向leader节点发送心跳,leader收到心跳后会返回信息,非leader节点收到这个信息后会重置计时器

  3. 当发生网络分区并且leader处于少数的那边时,其他follower会进行选举,假设B服务器选举成功,那么它会和其他follower进行zxid的比较

    ① 假设服务器C的zkid比服务器B的少10个,那么服务器B会将这十个操作封包发给服务器C来执行
    ② 假设服务器D的zxid比服务器B多10个,那么服务器B会让它将这十个记录都删除
    做完以上操作后,服务器B才会从follower切换成leader,并且将epoch里的值进行加1,zxid进行重置

  4. 当网络恢复了之后,旧leader比较路径下的epoch值的时候,发现已经有新的leader产生,会将自己切换成follower,并且进行数据的同步

状态同步

完成选举后,zk之间会进行状态同步操作

    1. leader构建NEWLEADER封包,包含leader最大zxid值,广播给其他follower
    1. follower收到后会跟自己最大zxid比较,若是比它小则进行同步操作
    1. leader给每个需要同步的follower创建LearnerHandler同步线程,负责进行同步操作
    1. leader主线程等待LearnerHandler线程处理结果
    1. 只有当大部分follower完成同步,该集群才对外提供服务,相应写请求
    1. LearnerHandler线程处理逻辑
      1. 接收follower封包FOLLOWERINFO,包含此follower最大zxid(代称f-max-zxid)
      1. f-max-zxid与leader最大zxid(代称l-max-zxid)比较
      1. 若相等,说明当前follower是最新的
      1. 另外,若在判断期间,有没有新提交的proposal
        1. 如果有,那么会发送DIFF封包将有差异的数据同步过去.同时将follower没有的数据逐个发送COMMIT封包给follower要求记录下来.
        1. 如果follower数据id更大,那么会发送TRUNC封包告知截除多余数据.
        1. 如果这一阶段内没有提交的提议值,直接发送SNAP封包将快照同步发送给follower.
      1. 以上消息完毕之后,发送UPTODATE封包告知follower当前数据就是最新的了
      1. 再次发送NEWLEADER封包宣称自己是leader,等待follower的响应.

分布式锁

    1. 所有需要获取锁的引用都在 /locker路径下创建一个有序临时节点
    1. 该路径下序号最小的应用获取该锁,其他应用分别监视比自己小一点的那个ZNode
    1. 当序号最小的那个应用操作完后,断开连接时,比它稍微大一点的那个应用会获取锁

分布式锁主要是应用了zk的一致性、临时节点、watch监视器这几个特性来保证的

WHO

  1. NameNode使用ZooKeeper实现高可用.
  2. Yarn ResourceManager使用ZooKeeper实现高可用.
  3. 利用ZooKeeper对HBase集群做高可用配置
  4. kafka使用ZooKeeper(仅限0.9以及之前版本)
    • 保存消息消费信息比如offset.
    • 用于检测崩溃
    • 主题topic发现
    • 保持主题的生产和消费状态

常用操作

# 使用ZooKeeper自带的脚本,连接ZooKeeper的服务器
zkCli.sh -server node01:2181,node02:2181,node03:2181

#创建节点,并指定数据(必须要指定数据)
create /kkb kkb
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容