文章标题,请和目录名保持一致
title: “zookeeper”
发布日期
date: 2024-10-23T20:00:00+08:00
权重
weight: 3
是否为草稿,如果是草稿,在系统时间未到发布日期前不显示
draft: false
description: “深入浅出zookeeper”
目录名
slug: “zookeeper”
标签
tags: [“zookeeper”, “zookeeper详细笔记”]
系列
是否是一个连续系列中的文档,页面会出现:部署教程 - 这篇文章属于一个选集
series: [“zookeeper”]
该文章在系列中的顺序
series_order: 1
一.集群与分布式
集群:将一个任务部署在多个服务器,每个服务器都能独立完成该任务。例如:饭店后厨有三个厨师,他们每个人都会洗菜、切菜和炒菜,即使饭店同时来了很多客人也能轻松应对,这就是集群。
分布式:将一个任务拆分成若干个子任务,由若干个服务器分别完成这些子任务,每个服务器只能完成某个特定的子任务。例如:饭店后厨有三个厨师,洗菜、切菜和炒菜三个子任务分别由每个人独立完成,一个人洗菜,一个人切菜,一个人炒菜,这就是分布式。
从概念上就可以看出两者最主要的区别就是分布式是将一种业务拆分成多个子业务部署在多台服务器上,进而对外提供服务;而集群就是将多台服务器组合在一起提供同一种服务。
集群强调在多台服务器位置集中,并且容易统一管理;而分布式没有具体要求,不论放置在哪个位置,只要通过网络连接起来就行。集群是一种物理形态,即多台服务器在一起提供一种服务;而分布式是一种工作方式,即一个程序或业务分解到多台服务器分别完成。
总结:集群是通过提高单位时间内执行的任务数来提升效率,分布式是以缩短单个任务的执行时间来提升效率。
二.CAP原则
1.CAP定义
现如今,对于多数大型互联网应用,主机众多、部署分散,而且现在的集群规模越来越大,节点只会越来越多,所以节点故障、网络故障是常态,因此分区容错性也就成为了一个分布式系统必然要面对的问题。
解决了分区容错性,随之而来又产生了新的问题,那就是如何在保证了数据安全(一致,不易丢失)的同时,又让我们的分布式环境满足可用性呢?这就是著名的 CAP 原则。
CAP 原则又称 CAP 定理,指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。
CAP 由 Eric Brewer 在 2000 年 PODC 会议上提出。该猜想在提出两年后被证明成立,成为我们熟知的 CAP 定理。CAP三者不可兼得。
特性定理Consistency一致性,也叫数据原子性,系统在执行某项操作后仍然处于一致的状态。在分布式系统中,更新操作执行成功后所有的用户都应该读到最新值,这样的系统被认定为具有强一致性。等同于所有节点访问同一份最新的数据副本。Availability可用性,每一个操作总是能够在一定时间内返回结果,这里需要注意的是“一定时间内”和"返回结果"。一定时间指的是在可以容忍的范围内返回结果,结果可以是成功或者失败,但不保证获取的数据是最新数据。Partition tolerance分区容错性,分布式系统在遇到任何网络分区故障的时候,仍然能够对外提供满足一致性和可用性的
服务,除非整个网络环境都发生了故障。这里可以理解为是否可以对数据进行分区,这是考虑到性能和可伸缩性。
2.取舍策略
CAP 三个特性只能满足其中两个,那么取舍的策略就共有三种:
- CA without P:如果不要求 P(不允许分区),则 C(强一致性)和 A(可用性)是可以保证的。但放弃 P 的同时也就 意味着放弃了系统的扩展性,也就是分布式节点受限,没办法部署子节点,这是违背分布式系统设计的初衷的。
- CP without A:如果不要求 A(可用),相当于每个请求都需要在服务器之间保持强一致,而 P(分区)会导致同步时 间无限延长(也就是等待数据同步完才能正常访问服务),一旦发生网络故障或者消息丢失等情况,就要牺牲用户的 体验,等待所有数据全部一致了之后再让用户访问系统。设计成 CP 的系统其实不少,最典型的就是分布式数据库。 对于分布式数据库来说,数据的一致性是最基本的要求,因为如果连这个标准都达不到,那么直接采用关系型数据库 就好,没必要再浪费资源来部署分布式数据库。
- AP without C:要高可用并允许分区,则需放弃一致性。一旦产生分区,节点之间可能会失去联系,为了高可用,每 个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。典型的应用就如某米的抢购手机场景,可能前 几秒你浏览商品的时候页面提示是有库存的,当你选择完商品准备下单的时候,系统提示你下单失败,商品已售完。 这其实就是先在 A(可用性)方面保证系统可以正常的服务,然后在数据的一致性方面做了些牺牲,虽然多少会影响 一些用户体验,但也不至于造成用户购物流程的严重阻塞。
3.总结
现如今,对于多数大型互联网应用,主机众多、部署分散,而且现在的集群规模越来越大,节点只会越来越多,所以
节点故障、网络故障是常态,因此分区容错性也就成为了一个分布式系统必然要面对的问题。那么就只能在 C 和 A 之间进
行取舍。但对于传统的项目就可能有所不同,拿银行的转账系统来说,涉及到金钱的对于数据一致性不能做出一丝的让
步,C 必须保证,出现网络故障的话,宁可停止服务。而互联网非金融项目普遍都是基于 AP 模式。
总而言之,没有最好的策略,好的系统应该是根据业务场景来进行架构设计的,只有适合的才是最好的。
三.BASE理论
1.介绍
CAP 理论已经提出好多年了,难道真的没有办法解决这个问题吗?也许可以做些改变。比如 C 不必使用那么强的一致
性,可以先将数据存起来,稍后再更新,实现所谓的 “最终一致性”。
这个思路又是一个庞大的问题,同时也引出了第二个理论 BASE 理论。
BASE:全称 Basically Available(基本可用),Soft state(软状态),和 Eventually consistent(最终一致性)三个短
语的缩写,来自 ebay 的架构师提出。
BASE 理论是对 CAP 中一致性和可用性权衡的结果,其来源于对大型互联网分布式实践的总结,是基于 CAP 定理逐步
演化而来的。其核心思想是:
既然无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达
到最终一致性(Eventual consistency)。
- Basically Available(基本可用) 基本可用是指分布式系统在出现故障的时候,允许损失部分可用性(例如响应时间、功能上的可用性)。需要注意的 是,基本可用绝不等价于系统不可用。 响应时间上的损失:正常情况下搜索引擎需要在 0.5 秒之内返回给用户相应的查询结果,但由于出现故障(比如系统 部分机房发生断电或断网故障),查询结果的响应时间增加到了 1~2 秒。 功能上的损失:购物网站在购物高峰(如双十一)时,为了保护系统的稳定性,部分消费者可能会被引导到一个降级 页面。
- Soft state(软状态) 什么是软状态呢?相对于原子性而言,要求多个节点的数据副本都是一致的,这是一种 “硬状态”。 软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。分布式存储中一般一份数据会有多个副 本,允许不同副本数据同步的延时就是软状态的体现。
- Eventually consistent(最终一致性)系统不可能一直是软状态,必须有个时间期限。在期限过后,应当保证所有副本保持数据一致性。从而达到数据的最 终一致性。这个时间期限取决于网络延时,系统负载,数据复制方案设计等等因素。 实际上,不只是分布式系统使用最终一致性,关系型数据库在某个功能上,也是使用最终一致性的,比如备份,数据 库的复制都是需要时间的,这个复制过程中,业务读取到的值就是旧值。当然,最终还是达成了数据一致性。这也算是一 个最终一致性的经典案例。
2.总结
总的来说,BASE 理论面向的是大型高可用可扩展的分布式系统,和传统事务的 ACID 是相反的,它完全不同于 ACID
的强一致性模型,而是通过牺牲强一致性来获得可用性,并允许数据在一段时间是不一致的。
四.数据的一致性
1.定义
复制是导致出现数据一致性问题的唯一原因,因为单节点系统很容易就可以达成一致性,而一些分布式系统通过复制
数据来提高系统的可靠性和容错性,将数据的不同的副本存放在不同的机器,这样的多节点系统一致性就成为了问题。
在数据有多份副本的情况下,如果网络、服务器或者软件出现故障,会导致部分副本写入成功,部分副本写入失败。
这就造成各个副本之间的数据不一致,数据内容冲突。应用系统需要对分布式数据处理系统的数据不一致性有所了解并进
行某种意义上的补偿和纠错,以避免出现应用系统数据不正确。
2. 模型
- 强一致性:要求无论更新操作实在哪一个副本执行,之后所有的读操作都要能获得最新的数据。
- 弱一致性:用户读到某一操作对系统特定数据的更新需要一段时间,我们称这段时间为“不一致性窗口”。
- 最终一致性:是弱一致性的一种特例,保证用户最终能够读取到某操作对系统特定数据的更新。
- 从客户端来看,有可能暂时获取的不是最新的数据,但是最终还是能访问到最新的
- 从服务端来看,数据存储并复制到整个系统超过半数的节点,以保证数据最终一致
五.Paxos算法
1.简介
- Paxos算法是Leslie Lamport宗师提出的一种基于消息传递的分布式一致性算法,使其获得2013年图灵奖。
- Paxos在1990年提出,被广泛应用于分布式计算中,Google的Chubby,Apache的Zookeeper都是基于它的理论来实现的
- Paxos算法解决的问题是分布式一致性问题,即一个分布式系统中的各个进程如何就某个值(决议)达成一致。
- 传统节点间通信存在着两种通讯模型:共享内存(Shared memory)、消息传递(Messages passing),Paxos是一个 基于消息传递的一致性算法。
2. 算法描述
Paxos 描述了这样一个场景:
- 有一个叫做 Paxos 的小岛(Island)上面住了一批居民(Islander);
- 岛上面所有的事情由一些特殊的人决定,他们叫做议员(Senator);
- 议员的总数(Senator Count)是确定的,不能更改;
- 岛上每次环境事务的变更都需要通过一个提议(Proposal),每个提议都有一个编号(PID),这个编号是一直增长的,不能倒 退;
- 每个提议都需要超过半数((Senator Count)/2 +1)的议员同意才能生效(少数服从多数);
- 每个议员只会同意大于当前编号的提议,包括已生效的和未生效的;
- 如果议员收到小于等于当前编号的提议,他会拒绝,并告知对方:你的提议已经有人提过了。这里的当前编号是每个议员在 自己记事本上记录的编号,他会不断更新这个编号;
- 整个议会不能保证所有议员记事本上的编号总是相同的; - 现在议会有一个目标:保证所有的议员对于提议都能达成一致的看法。 现在议会开始运作,所有议员一开始记事本上面记录的编号都是0。有一个议员发了一个提议:将电费设定为1元/度。他首先看了一下记事本,嗯,当前提议编号是0,那么我的这个提议的编号就是1,于是他给所有议员发消息:1号提议,设定电费1元/度。其他议员收到消息以后查了一下记事本,哦,当前提议编号是0,这个提议可接受,于是他记录下这个提议并回复:我接受你的1号提议,同时他在记事本上记录:当前提议编号为1。发起提议的议员收到了超过半数的回复,立即给所有人发通知:1号提议生效!收到的议员会修改他的记事本,将1好提议由记录改成正式的法令,当有人问他电费为多少时,他会查看法令并告诉对方:1元/度。- 再看冲突的解决:假设总共有三个议员S1-S3,S1和S2同时发起了一个提议:1号提议,设定电费。S1想设为1元/度, S2想设为 2元/度。结果S3先收到了S1的提议,于是他做了和前面同样的操作。紧接着他又收到了S2的提议,结果他一查记事本,咦,这个提议的编号小于等于我的当前编号1,于是他拒绝了这个提议:对不起,这个提议先前提过了。于是S2的提议被拒绝,S1正式发布了提议: 1号提议生效。S2向S1或者S3打听并更新了1号法令的内容,然后他可以选择继续发起2号提议。
3.Paxos推断
- 小岛(Island) 服务器集群
- 议员(Senator) 单台服务器
- 议员的总数(Senator Count)是确定的
- 提议(Proposal) 每一次对集群中的数据进行修改
- 每个提议都有一个编号(PID),这个编号是一直增长的
- 每个提议都需要超过半数((Senator Count)/2 +1)的议员同意才能生效
- 每个议员只会同意大于当前编号的提议
- 每个议员在自己记事本上面记录的编号,他不断更新这个编号
- 整个议会不能保证所有议员记事本上的编号总是相同的
- 议会有一个目标:保证所有的议员对于提议都能达成一致的看法。
- 前期投票(>1/2),后期广播(all)
- Paxos算法 数据的全量备份 弱一致性 => 最终一致性
4.算法模型延伸
如果Paxos岛上的议员人人平等,在某种情况下会由于提议的冲突而产生一个“活锁”(所谓活锁我的理解是大家都没有死,都在
动,但是一直解决不了冲突问题)。Paxos的作者在所有议员中设立一个总统,只有总统有权发出提议,如果议员有自己的提
议,必须发给总统并由总统来提出.
活锁问题:
这个时候就需要有主模型。
1.有主模型下,如果用户请求数据到非主节点,非主节点会请求主节点以拉取最新数据。
对应如下情况:
情况一:屁民甲(Client)到某个议员(ZK Server)那里询问(Get)某条法令的情况(ZNode的数据),议员毫不犹豫的拿出他的
记事本(local storage),查阅法令并告诉他结果,同时声明:我的数据不一定是最新的。你想要最新的数据?没问题,等
着,等我找总统Sync一下再告诉你。
- 数字编号(议员 ID,ZooKeeper 中叫 myid):为了快速选出总统
- 事务编号(会议 ID,ZooKeeper 中叫 ZXID):为了确定谁的数据是最全的
2.有主模型下,选主过程:先比较 ZXID,如果 ZXID 相同再比较 myid,选择公共最新数据的PID的最大id的节点。
总统突然挂了,议员接二连三的发现联系不上总统,于是各自发表声明,推选新的总统,总统大选期间政府停业,拒
绝屁民的请求。
1.集群初始化时主节点的选举过程
2.集群正常运行时,主节点宕机,重新选举过程
3.集群工作过程中因为网络波动,主节点和其他节点不在一个网段,集群重新选举一个主节点,此时上一个主节点网络恢复了,这个有2个主节点,选择标记大的为主节点。
4.分为主节点,从节点,观察者的集群架构
5.无主和有主模型对比
- 无主集群模型
- 人人都会发送指令,投票
- 投票人数有可能导致分区(分不同阵营),
- 6个节点 33对立
- 类似于以前党争
- 事务编号混乱,每个节点都有可能有自己的提议
- 提议的编号不能重复和小于
- 有主集群模型
- 只能有一个主发送指令,发送提议
- 单主会单点故障,肯定有备用的方案
- 重新选举,议员会把票投给数字编号和事务编号都大于自己的议员
- 数字编号(议员 ID,ZooKeeper 中叫 myid):为了快速选出总统
- 事务编号(会议 ID,ZooKeeper 中叫 ZXID):为了确定谁的数据是最全的
- 选主过程:先比较 ZXID,如果 ZXID 相同再比较 myid
- 如果存在多个主就会脑裂 过半原则:选主过程中,如果某个议员获得了超过半数的选票,才可以成为主
- 议员同步数据只需要从主节点同步
- 节点越多业务能力越强,但是选举速度也会越慢减少参与选举和投票的人数(例如 ZooKeeper 的 Observer) 主要集群中节点数目高于1/2+1,集群就可以正常运行
六.ZAB协议
6.1. 背景
ZooKeeper 最早起源于雅虎研究院的一个研究小组。当时,研究人员发现,在雅虎的很多大型系统基本都需要依赖一
个类似的系统来进行分布式协调,但是这些系统都存在分布式单点问题,所以雅虎的开发人员就试图开发出一个通用的无
单点问题的分布式协调框架,以便让开发人员将精力集中在处理业务逻辑上。
于是,ZooKeeper 就诞生了!
ZooKeeper 的出现不仅解决了分布式系统下数据一致性的问题,而且经历过线上验证,无论是从性能、易用性、稳定
性上来说,都是工业级产品的标准。可以说在分布式系统中具有不可替代的核心地位,例如 Hadoop、HBase、Kafka 等大
型分布式系统都已经将 ZooKeeper 作为其核心组件,用于分布式协调。
6.2. 简介
ZAB 协议,全称 ZooKeeper Atomic Broadcast(ZooKeeper 原子广播协议)。它是专门为分布式协调服务——ZooKeeper
设计的一种支持崩溃恢复和原子广播的协议。
ZAB 协议借鉴了 Paxos 算法,而 ZooKeeper 正是通过 ZAB 协议来保证分布式事务的最终一致性。基于该协议,
ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。
主备系统架构模型,就是指只有一个 Leader 节点负责处理外部的写事务请求,然后 Leader 节点将数据同步到其他
Follower 节点和 Observer 节点。接下来我们详细介绍一下这三种角色。
6.3. 三种角色
- Leader:负责整个 ZooKeeper 集群工作机制中的核心,主要工作有以下两个:事务请求的唯一调度和处理者,保证集 群事务处理的顺序性集群内部各服务器的调度者。
- Follower:它是 Leader 的追随者,其主要工作有三个:处理客户端的非实物请求,转发事务请求给 Leader 服务器参 与事务请求 Proposal 的投票参与 Leader 选举投票。
- Observer:是 ZooKeeper 自 3.3.0 开始引入的一个角色,它不参与事务请求 Proposal 的投票,也不参与 Leader 选举投 票,只提供非事务的服务(查询),通常在不影响集群事务处理能力的前提下提升集群的非事务处理能力。
6.4. 两种模式
ZAB 协议的包括两种模式:崩溃恢复、原子广播。
6.4.1. 崩溃恢复之数据恢复
当整个集群正在启动时,或者当 Leader 节点出现网络中断、崩溃等情况时,ZAB 协议就会进入恢复模式并选举产生新
的 Leader,当 Leader 服务器选举出来后,并且集群中有过半的机器和该 Leader 节点完成数据同步后(同步指的是数
据同步,用来保证集群中过半的机器能够和 Leader 服务器的数据状态保持一致),ZAB 协议就会退出恢复模式。
当集群中已经有过半的 Follower 节点完成了和 Leader 状态同步以后,那么整个集群就进入了消息广播模式。这个时
候,在 Leader 节点正常工作时,启动一台新的服务器加入到集群,那这个服务器会直接进入数据恢复模式,和 Leader
节点进行数据同步。同步完成后即可正常对外提供非事务请求的处理。
在整个消息广播中,Leader 会将每一个事务请求转换成对应的 Proposal 来进行广播,并且在广播事务 Proposal 之前,
Leader 服务器会首先为这个事务 Proposal 分配一个全局单递增的唯一ID,称之为事务 ID(即 ZXID),由于 ZAB 协议需
要保证每一个消息的严格的顺序关系,因此必须将每一个 Proposal 按照其 ZXID 的先后顺序进行排序和处理。
6.4.2. 消息广播之原子广播
在 ZooKeeper 集群中,数据副本的传递策略就是采用消息广播模式。Leader 服务器将客户端事务请求转化成一个
Prososal(提议),并将该 Proposal 分发给集群中所有的 Follower 服务器。也就是向所有 Follower 节点发送数据广播
请求(或数据复制)。
ZooKeeper 中数据副本的同步方式与二段提交相似,但是却又不同。二段提交要求协调者必须等到所有的参与者全部
反馈 ACK 确认消息后,再发送 Commit 消息。要求所有的参与者要么全部成功,要么全部失败。二段提交会产生严重
的阻塞问题。
而在 ZAB 协议中 Leader 等待 Follower 的 ACK 反馈消息“只要半数以上的 Follower 成功反馈即可,不需要收到全部
Follower 的反馈”。
6.5. 总结
整个 ZAB 协议一共定义了三个阶段:
- 发现:要求 ZooKeeper 集群必须选举出一个 Leader,同时 Leader 会维护一个 Follower 可用列表。将来客户端可以和 这些 Follower 节点进行通信。
- 同步:Leader 要负责将本身的数据与 Follower 完成同步,做到多副本存储。这样便体现了 CAP 中的一致性和分区容 错。Follower 将队列中未处理完的请求消费完成后,写入本地事务日志中。
- 广播:Leader 可以接受客户端新的事务 Proposal 请求,将新的 Proposal 请求广播给所有的 Follower。
三个阶段执行完为一个周期,在 ZooKeeper 集群的整个生命周期中,这三个阶段会不断进行,如果 Leader 崩溃或因其它原因导致 Leader 缺失,ZAB 协议会再次进入阶段一。
七. ZooKeeper集群搭建
首先将三台虚拟机切换至相互免秘钥快照(keyfree),然后将准备好的 ZooKeeper 安装包上传至服务器。
server.1 中的 1 是 myid 文件中的内容,2888 用于集群内部通信,3888 用于选举 Leader。
zookeeper常见命令
一、zk服务命令
1. 启动ZK服务: bin/zkServer.sh start
2. 查看ZK服务状态: bin/zkServer.sh status
3. 停止ZK服务: bin/zkServer.sh stop
4. 重启ZK服务: bin/zkServer.sh restart
5. 连接服务器: zkCli.sh -server 127.0.0.1:2181
二、zk客户端命令
1.ls -- 查看某个目录包含的所有文件,例如:
[zk: 127.0.0.1:2181(CONNECTED)1]ls /
ls /path
2.create -- 创建znode,并设置初始内容,例如:
[zk: 127.0.0.1:2181(CONNECTED)1] create /test "test"
Created /test
创建一个新的 znode节点“ test ”以及与它关联的字符串
create /path data 默认创建持久节点
create -s /path data 创建顺序节点
create -e /path data 创建临时节点
create /parent/sub/path /data
4.get -- 获取znode的数据,如下:
[zk: 127.0.0.1:2181(CONNECTED)1] get /test
get /path
get /path0000000018 访问顺序节点必须输入完整路径
5.set -- 修改znode内容,例如:
[zk: 127.0.0.1:2181(CONNECTED)1]set /test "ricky"set /path /data
6.delete -- 删除znode,例如:
[zk: 127.0.0.1:2181(CONNECTED)1] delete /test
delete /path 删除没有子节点的节点
rmr /path 移除节点并且递归移除所有子节点
7.quit -- 退出客户端
8.help -- 帮助命令
八.ZooKeeper存储模型
10.1. 存储结构
- zookeeper是一个树状结构,维护一个小型的数据节点znode
- 数据以keyvalue的方式存在,目录是数据的key
- 所有的数据访问都必须以绝对路径的方式呈现
[zk: localhost:2181(CONNECTED)10]stat /yjx
666 当前节点的值
cZxid = 0xf00000013
创建这个节点的事务id,ZXID是一个长度64位的数字,
低32位是按照数字递增,即每次客户端发起一个proposal,低32位的数字简单加1。
高32位是leader周期的epoch编号
ctime = Mon Dec 09 17:33:06 CST 2019 创建时间
mZxid = 0xf00000013 最后一次修改节点数据的事务ID
mtime = Mon Dec 09 17:33:06 CST 2019 修改时间
pZxid = 0xf00000014 子节点的最新事务ID
cversion =1 对此znode的子节点进行的更改次数
dataVersion = 对此znode的数据所作的修改次数
aclVersion = 对此znode的acl更改次数
ephemeralOwner = 0x0 (持久化节点)0x16ee9fc0feb0001(临时节点)
dataLength =3 数据的长度
numChildren =1 子节点的数目
10.2. 节点的分类
- 持久化节点(PERSISTENT) - 默认创建的就是持久化节点
- 临时节点(Ephemral) - 只要创建节点的会话有效,节点就不会失效- 可以被所有的客户端所查看- 事务编号和临时节点编号是一致的- create -e- 一旦会话结束,临时节点也会被自动删除,一般这个功能用于判断节点和服务器是否保持连接
- 序列化节点(Sequential) - 在名字的后面添加一个序列号(有序)- create -s
九.ZooKeeper监听机制
语法格式: addWatch [-m mode] path # optional mode is one of [PERSISTENT,
PERSISTENT_RECURSIVE] - default is PERSISTENT_RECURSIVE 。
addWatch 的作用是针对指定节点添加事件监听,支持两种模式:
PERSISTENT :持久化订阅,针对当前节点的修改和删除事件,以及当前节点的子节点的新增和删除事件。
PERSISTENT_RECURSIVE :持久化递归订阅,在 PERSISTENT 的基础上,增加了子节点修改的事件触发,以及子节
点的子节点的数据变化都会触发相关事件(满足递归订阅特性)。默认模式
PERSISTENT 模式案例演示:
# 创建节点[zk: localhost:2181(CONNECTED)0] create /bigdata 100
Created /bigdata
# 监听节点,使用 PERSISTENT 模式[zk: localhost:2181(CONNECTED)1] addWatch -m PERSISTENT /bigdata
# 修改当前节点会触发监听事件[zk: localhost:2181(CONNECTED)2]set /bigdata 200
WATCHER:: # 触发监听事件 NodeDataChanged
WatchedEvent state:SyncConnected type:NodeDataChanged path:/bigdata
# 创建子节点会触发监听事件[zk: localhost:2181(CONNECTED)3] create /bigdata/zk 300
WATCHER:: # 触发监听事件 NodeChildrenChanged
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/bigdata
Created /bigdata/zk
# 修改子节点不会触发监听事件[zk: localhost:2181(CONNECTED)4]set /bigdata/zk 301# 删除子节点触发监听事件[zk: localhost:2181(CONNECTED)5] delete /bigdata/zk
WATCHER:: # 触发监听事件 NodeChildrenChanged
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/bigdata
# 删除当前节点会触发监听事件[zk: localhost:2181(CONNECTED)6] delete /bigdata
WATCHER:: # 触发监听事件 NodeDeleted
WatchedEvent state:SyncConnected type:NodeDeleted path:/bigdata
PERSISTENT_RECURSIVE 模式案例演示:
# 创建节点[zk: localhost:2181(CONNECTED)0] create /bigdata 100
Created /bigdata
# 监听节点,不指定模式默认采用 PERSISTENT_RECURSIVE 模式[zk: localhost:2181(CONNECTED)1] addWatch /bigdata
# 修改当前节点会触发监听事件[zk: localhost:2181(CONNECTED)2]set /bigdata 200
WATCHER:: # 触发监听事件 NodeDataChanged
WatchedEvent state:SyncConnected type:NodeDataChanged path:/bigdata
# 创建子节点会触发监听事件[zk: localhost:2181(CONNECTED)3] create /bigdata/zk 30
WATCHER:: # 触发监听事件 NodeCreated
WatchedEvent state:SyncConnected type:NodeCreated path:/bigdata/zk
Created /bigdata/zk
# 创建子节点的子节点会触发监听事件[zk: localhost:2181(CONNECTED)4] create /bigdata/zk/test 400
WATCHER:: # 触发监听事件 NodeCreated
WatchedEvent state:SyncConnected type:NodeCreated path:/bigdata/zk/test
Created /bigdata/zk/test
# 修改子节点会触发监听事件[zk: localhost:2181(CONNECTED)5]set /bigdata/zk 301
WATCHER:: # 触发监听事件 NodeDataChanged
WatchedEvent state:SyncConnected type:NodeDataChanged path:/bigdata/zk
# 修改子节点的子节点会触发监听事件[zk: localhost:2181(CONNECTED)6]set /bigdata/zk/test 401
WATCHER:: # 触发监听事件 NodeDataChanged
WatchedEvent state:SyncConnected type:NodeDataChanged path:/bigdata/zk/test
# 删除子节点的子节点触发监听事件[zk: localhost:2181(CONNECTED)7] delete /bigdata/zk/test
WATCHER:: # 触发监听事件 NodeDeleted
WatchedEvent state:SyncConnected type:NodeDeleted path:/bigdata/zk/test
# 删除子节点和当前节点都会触发监听事件[zk: localhost:2181(CONNECTED)8] deleteall /bigdata
WATCHER:: # 触发监听事件 NodeDeleted
WatchedEvent state:SyncConnected type:NodeDeleted path:/bigdata/zk
WATCHER:: # 触发监听事件 NodeDeleted
WatchedEvent state:SyncConnected type:NodeDeleted path:/bigdata
仔细观察,两种模式的 WatchedEvent 稍微有些不同。
十.ZooKeeper应用场景
- 场景一:统一命名服务。 有一组服务器向客户端提供某种服务,我们希望客户端每次请求服务端都可以找到服务端集群中某一台服务器,这样 服务端就可以向客户端提供客户端所需的服务。对于这种场景,我们的程序中一定有一份这组服务器的列表,每次客 户端请求时候,都是从这份列表里读取这份服务器列表。那么这分列表显然不能存储在一台单节点的服务器上,否则 这个节点挂掉了,整个集群都会发生故障,我们希望这份列表时高可用的。高可用的解决方案是:这份列表是分布式 存储的,它是由存储这份列表的服务器共同管理的,如果存储列表里的某台服务器坏掉了,其他服务器马上可以替代 坏掉的服务器,并且可以把坏掉的服务器从列表里删除掉,让故障服务器退出整个集群的运行,而这一切的操作又不 会由故障的服务器来操作,而是集群里正常的服务器来完成。这是一种主动的分布式数据结构,能够在外部情况发生 变化时候主动修改数据项状态的数据机构。,它和javaEE里的JNDI服务很像
- 场景二:分布式锁服务。 当分布式系统操作数据,例如:读取数据、分析数据、最后修改数据。在分布式系统里这些操作可能会分散到集群里 不同的节点上,那么这时候就存在数据操作过程中一致性的问题,如果不一致,我们将会得到一个错误的运算结果, 在单一进程的程序里,一致性的问题很好解决,但是到了分布式系统就比较困难,因为分布式系统里不同服务器的运 算都是在独立的进程里,运算的中间结果和过程还要通过网络进行传递,那么想做到数据操作一致性要困难的多。 Zookeeper提供了一个锁服务解决了这样的问题,能让我们在做分布式数据运算时候,保证数据操作的一致性。
- 场景三:配置管理。 在分布式系统里,我们会把一个服务应用分别部署到n台服务器上,这些服务器的配置文件是相同的(例如:我设计 的分布式网站框架里,服务端就有4台服务器,4台服务器上的程序都是一样,配置文件都是一样),如果配置文件的 配置选项发生变化,那么我们就得一个个去改这些配置文件,如果我们需要改的服务器比较少,这些操作还不是太麻 烦,如果我们分布式的服务器特别多,比如某些大型互联网公司的hadoop集群有数千台服务器,那么更改配置选项就 是一件麻烦而且危险的事情。这时候zookeeper就可以派上用场了,我们可以把zookeeper当成一个高可用的配置存储 器,把这样的事情交给zookeeper进行管理,我们将集群的配置文件拷贝到zookeeper的文件系统的某个节点上,然后 用zookeeper监控所有分布式系统里配置文件的状态,一旦发现有配置文件发生了变化,每台服务器都会收到 zookeeper的通知,让每台服务器同步zookeeper里的配置文件,zookeeper服务也会保证同步操作原子性,确保每个服 务器的配置文件都能被正确的更新。
- 场景四:为分布式系统提供故障修复的功能。 集群管理是很困难的,在分布式系统里加入了zookeeper服务,能让我们很容易的对集群进行管理。集群管理最麻烦 的事情就是节点故障管理,zookeeper可以让集群选出一个健康的节点作为master,master节点会知道当前集群的每台 服务器的运行状况,一旦某个节点发生故障,master会把这个情况通知给集群其他服务器,从而重新分配不同节点的 计算任务。Zookeeper不仅可以发现故障,也会对有故障的服务器进行甄别,看故障服务器是什么样的故障,如果该 故障可以修复,zookeeper可以自动修复或者告诉系统管理员错误的原因让管理员迅速定位问题,修复节点的故障。 大家也许还会有个疑问,master故障了,那怎么办了?zookeeper也考虑到了这点,zookeeper内部有一个“选举领导者 的算法”,master可以动态选择,当master故障时候,zookeeper能马上选出新的master对集群进行管理。
十一.最终一致性细节分类
- 因果一致性(Casual Consistency) 如果进程A通知进程B它已更新了一个数据项,那么进程B的后续访问将返回更新后的值,且一次写入将保证取代前一 次写入。 与进程A无因果关系的进程C的访问,遵守一般的最终一致性规则。 查询微博和评论
- 读己之所写一致性(read-your-writes) 当进程A自己更新一个数据项之后,它总是访问到更新过的值,绝不会看到旧值。这是因果一致性模型的一个特例。 读自己的数据都从主服务器去读取,读其他人的数据再从从服务器去读取 发表微博与修改微博
- 会话(Session)一致性 这是上一个模型的实用版本,它把访问存储系统的进程放到会话的上下文中。只要会话还存在,系统就保证“读己之 所写”一致性。如果由于某些失败情形令会话终止,就要建立新的会话,而且系统的保证不会延续到新的会话。 确保会话内访问的都是最新的 登录场景
- 单调(Monotonic)读一致性。 如果进程已经看到过数据对象的某个最新值,那么任何后续访问都不会返回在那个值之前的值。 不会读取最旧的数据 秒杀场景
- 单调写一致性。 系统保证来自同一个进程的写操作顺序执行。要是系统不能保证这种程度的一致性,就非常难以编程了。 按照顺序完成数据的书写 细节分类
- 因果一致性(Casual Consistency) 如果进程A通知进程B它已更新了一个数据项,那么进程B的后续访问将返回更新后的值,且一次写入将保证取代前一 次写入。 与进程A无因果关系的进程C的访问,遵守一般的最终一致性规则。 查询微博和评论
- 读己之所写一致性(read-your-writes) 当进程A自己更新一个数据项之后,它总是访问到更新过的值,绝不会看到旧值。这是因果一致性模型的一个特例。 读自己的数据都从主服务器去读取,读其他人的数据再从从服务器去读取 发表微博与修改微博
- 会话(Session)一致性 这是上一个模型的实用版本,它把访问存储系统的进程放到会话的上下文中。只要会话还存在,系统就保证“读己之 所写”一致性。如果由于某些失败情形令会话终止,就要建立新的会话,而且系统的保证不会延续到新的会话。 确保会话内访问的都是最新的 登录场景
- 单调(Monotonic)读一致性。 如果进程已经看到过数据对象的某个最新值,那么任何后续访问都不会返回在那个值之前的值。 不会读取最旧的数据 秒杀场景
- 单调写一致性。 系统保证来自同一个进程的写操作顺序执行。要是系统不能保证这种程度的一致性,就非常难以编程了。 按照顺序完成数据的书写 打游戏副本场景
版权归原作者 m0_63924864 所有, 如有侵权,请联系我们删除。