一篇文章带你深入理解Zookeeper

随着互联网技术的发展,大型网站需要的计算能力和存储能力越来越高。网站架构逐渐从集中式转变成分布式。

虽然分布式和集中式系统相比有很多优势,比如能提供更强的计算、存储能力,避免单点故障等问题。但是由于采用分布式部署的方式,就经常会出现网络故障等问题,并且如何在分布式系统中保证数据的一致性和可用性也是一个比较关键的问题。

分布式的工作方式有点类似于团队合作。当有一项任务分配到某个团队之后,团队内部的成员开始各司其职,然后把工作结果统一汇总给团队主管,由团队主管再整理团队的工作成果汇报给公司。

但是,日常工作中,如果两个员工或用户对某件事产生了分歧,通常我们的做法是找上级,去做数据和信息的同步。

那么对于我们的服务呢,多个节点之间数据不同步如何处理?

对于分布式集群来说,这个时候,我们通常一个能够在各个服务或节点之间进行协调的服务或中间人

架构设计中,没有一个问题不能通过增加一个抽象层来解决的,如果有,那就增加两层。

集群管理

我们可以一起看看,协调服务中的佼佼者--ZooKeeper

zookeeper起源

最初,在Hadoop生态中,会存在很多的服务或组件(比如hive、pig等),每个服务或组件之间进行协调处理是很麻烦的一件事情,急需一种高可用高性能数据强一致性的协调框架。

因此雅虎的工程师们创造了这个中间程序,但中间程序的命名却愁死了开发人员,突然想到hadoop中的大多是动物名字,似乎缺乏一个管理员,这个程序的功能有是如此的相似。因此zookeeper诞生。

Zookeeper是一个开放源码的分布式服务协调组件,是Google Chubby的开源实现。是一个高性能的分布式数据一致性解决方案。他将那些复杂的、容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并提供一系列简单易用的接口给用户使用。

zookeeper提供了哪些特性,以便于能够很好的完成协调能力的处理呢?

功能与特性

数据存储

zookeeper提供了类似Linux文件系统一样的数据结构。每一个节点对应一个Znode节点,每一个Znode节点都可以存储1MB(默认)的数据。

客户端对zk的操作就是对Znode节点的操作。

zookeeper数据结构

  • Znode:包含ACL权限控制、修改/访问时间、最后一次操作的事务Id(zxid)等等
  • 说有数据存储在内存中,在内存中维护这么一颗树。
  • 每次对Znode节点修改都是保证顺序和原子性的操作。写操作是原子性操作。

举个例子,在注册中心中,可以通过路径"/fsof/服务名1/providers"找到"服务1"的所有提供者。

每一个Znode节点又根据节点的生命周期与类型分为4种节点。

  • 生命周期:当客户端会话结束的时候,是否清理掉这个会话创建的节点。持久-不清理,临时-清理。
  • 类型:每一个会话,创建单独的节点(例子:正常节点:rudytan,顺序编号节点:rudytan001,rudytan002等等)

监听机制

zookeeper除了提供对Znode节点的处理能力,还提供了对节点的变更进行监听通知的能力。

监听机制的步骤如下:

  1. 任何session(session1,session2)都可以对自己感兴趣的znode监听。
  2. 当znode通过session1对节点进行了修改。
  3. session1,session2都会收到znode的变更事件通知。

节点常见的事件通知有:

  • session建立成功事件
  • 节点添加
  • 节点删除
  • 节点变更
  • 子节点列表变化

需要特别说明的是:

一次监听事件,只会被触发一次,如果想要监听到znode的第二次变更,需要重新注册监听。

到这里,我们了解到zookeeper提供的能力,那我们在哪些场景可以使用它?如何使用它呢?

应用场景

zookeeper用得比较多的地方可能是,微服务的集群管理与服务注册与发现。

注册中心

  • 依赖于临时节点
  • 消费者启动的时候,会先去注册中心中全量拉取服务的注册列表。
  • 当某个服务节点有变化的时候,通过监听机制做数据更新。
  • zookeeper挂了,不影响消费者的服务调用。

目前还有个比较流行的服务Eureka也可以做注册中心,他们有什么优势和劣势呢?

注册中心的对比

通过上面的架构图,可以发现Eureka不同于zk中的节点,Eureka中的节点每一个节点对等。是个AP系统,而不是zk的CP系统。在注册中心的应用场景下,相对于与强数据一致性,更加关心可用性。

分布式锁

  • 依赖于临时顺序节点
  • 判断当前client的顺序号是否是最小的,如果是获取到锁。
  • 没有获取到锁的节点监听最小节点的删除事件(比如lock_key_001)
  • 锁释放,最小节点删除,剩余节点重新开始获取锁。
  • 重复步骤二到四。

redis和db也能创建分布式锁,那有什么异同呢?

分布式锁的对比

分布式锁可以参考文章: 分布式锁(redis/mysql)、分布式锁的几种实现方式

具体差异比较:

从理解的难易程度角度(从低到高)

数据库 > 缓存(Redis) > Zookeeper

从实现的复杂性角度(从低到高)

Zookeeper >= 缓存(Redis) > 数据库

从性能角度(从高到低)

缓存(Redis) > Zookeeper >= 数据库

从可靠性角度(从高到低)

Zookeeper > 缓存(Redis) > 数据库

集群管理与master选举

  • 依赖于临时节点
  • zookeeper保证无法重复创建一个已存在的数据节点,创建成功的client为master。
  • 非master,在已经创建的节点上注册节点删除事件监听。
  • 当master挂掉后,其他集群节点收到节点删除事件,进行重新选举
  • 重复步骤二到四

当然还有其他应用场景,不一一列举了。

有人说,zookeeper可以做分布式配置中心、分布式消息队列,看到这里的小伙伴们,你们觉得合适么?

到这里,可以基本上满足基于zk应用开发的理论知识储备。

高性能高可用强一致性保障

高性能-分布式集群

 

高性能,我们通常想到的是通过集群部署来突破单机的性能瓶颈。对于zk来说,就是通过部署多个节点共同对外提供服务,来提供读的高性能。

  • Master/Slave模式。
  • 在zookeeper中部署多台节点对外提供服务,客户端可以连接到任意一个节点。
  • 每个节点的数据都是一样的。
  • 节点根据角色分为Leader节点与Learner节点(包括Follower节点与Observer节点)。
  • 集群中,只有一个Leader节点,完成所有的写请求处理。
  • 每次写请求都会生成一个全局的唯一的64位整型的事务ID(可以理解为全局的数据的版本号)。
  • Learner节点可以有很多,每个Leaner可以独自处理读请求,转写请求到Leader节点。
  • 当Leader节点挂掉后,会从Follower节点中通过选举方式选出一个Leader提供对外服务。
  • Follower节点与Observer节点区别在于不参与选举和提议的事务过半处理。
  • 集群通常是按照奇数个节点进行部署(偶然太对容灾没啥影响,浪费机器)。

数据一致性(zab协议-原子广播协议)

通过集群的部署,根据CAP原理,这样,可能导致同一个数据在不同节点上的数据不一致。zookeeper通过zab原子广播协议来保证数据在每一个节点上的一致性。原子广播协议(类似2PC提交协议)大概分为3个步骤。

  • Leader包装写请求,生成唯一zxid,发起提议,广播给所有Follower。
  • Follower收到提议后,写入本地事务日志,根据自身情况,是否同意该事务的提交。
  • Leader收到过半的Follower同意,自己先添加事务。然后对所有的Learner节点发送提交事务请求。

需要说明的是,zookeeper对数据一致性的要求是:

  • 顺序一致性:严格按照事务发起的顺序执行写操作。
  • 原子性:所有事务请求的结果在集群中的所有节点上的应用情况是一致的。
  • 单一视图:客户端访问任何一个节点,看到的数据模型都是一致的。
  • 实时性:保证在极小一段时间客户端最终可以从服务读取最新数据状态(如果要实时,需要客户端调用syn方法)。

可用性-leader选举(zab协议-崩溃恢复协议)

在整个集群中,写请求都集中在一个Leader节点上,如果Leader节点挂了咋办呢?

当集群初始化或Follower无法联系上Leader节点的时候,每个Follower开始进入选举模式。选举步骤如下:

  1. Follower节点第一次投票先投自己,然后将自己的选票广播给剩余的Follower节点。
  2. Follower节点接收到其他的选票。
  3. 选票比较:比较自己的与接收的选票的投票更有。
  4. 如果资金的选票不是最优选票,变更自己的选票,投最优选票的节点。
  5. 统计自己收到的选票,如果某个节点获得了过半的节点的投票。确认该节点为新的Leader节点。
  6. 确认Leader节点后,每个节点变更自己的角色。完成投票选举。

选举原则:谁的数据最新,谁就有优先被选为Leader的资格。

举个例子,假如现在zk集群有5个节点,然后挂掉了2个节点。剩余节点S3,S4,S6开始进行选举,他们的最大事务ID分别是6,2,6。定义投票结构为(投票的节点ID,被投节点ID,被投节点最大事务ID)。

  1. 初始状态,S3,S4,S5分别投自己,并带上自己的最大事务ID。
  2. S3,S4,S5分别对自己收到的2票与自己的1票做比较。
  3. S5发现自己的是最优投票,不变更投票,S3,S4发现S5的投票是最优解,更改投票。
  4. S3,S4广播自己变更的投票。
  5. 最后大家都确认了S5是Leader,S5节点状态变更为Leader节点,S3,S4变更为Follower节点。

到这里,就是选举的主要过程。

数据的持久化

  • zookeeper所有数据都存在内存中。
  • zookeeper会定期将内存dump到磁盘中,形成数据快照。
  • zookeeper每次的事务请求,都会先接入到磁盘中,形成事务日志。
  • 全量数据 = 数据快照 + 事务日志。

Zookeeper和CAP的关系

前面提到了zk在可用性、数据一致性、性能等方面都表现的很优秀,也介绍了其中的原理。

但是分布式系统的CAP理论告诉我们:任何软件系统都无法同时满足一致性、可用性以及分区容错性。

那么,Zookeeper其实也是一个分布式系统,那么也就要满足CAP理论,也就是说,虽然在各个方面,ZK可以说是做了很多努力,但是在极端情况下,Zookeeper也需要在这三者之间有一些权衡,那么Zookeeper在CAP中是如何取舍的呢?

ZooKeeper是个CP(一致性+分区容错性)的,即任何时刻对ZooKeeper的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性,但是它不能保证每次服务请求的可用性(注:也就是在极端环境下,ZooKeeper可能会丢弃一些请求,消费者程序需要重新请求才能获得结果)。

但是别忘了,ZooKeeper是分布式协调服务,它的职责是保证数据(注:配置数据,状态数据)在其管辖下的所有服务之间保持同步、一致,所以就不难理解为什么ZooKeeper被设计成CP而不是AP特性的了。

如果是AP的,那么将会带来恐怖的后果(注:ZooKeeper就像交叉路口的信号灯一样,你能想象在交通要道突然信号灯失灵的情况吗?)。

而且, 作为ZooKeeper的核心实现算法 Zab,就是解决了分布式系统下数据如何在多个服务之间保持同步问题的。

如果 ZooKeeper下所有节点都断开了,或者集群中出现了网络分割的故障(注:由于交换机故障导致交换机底下的子网间不能互访)。

那么ZooKeeper 会将它们都从自己管理范围中剔除出去,外界就不能访问到这些节点了,即便这些节点本身是“健康”的,可以正常提供服务的;所以导致到达这些节点的服务请求被丢失了。

原文地址:https://www.cnblogs.com/zhoudatong/p/10089114.html

时间: 2024-08-29 03:57:39

一篇文章带你深入理解Zookeeper的相关文章

一篇文章助你深入理解zookeeper

Zookeeper作为一个分布式协调系统提供了一项基本服务:分布式锁服务,分布式锁是分布式协调技术实现的核心内容.像配置管理.任务分发.组服务.分布式消息队列.分布式通知/协调等,这些应用实际上都是基于这项基础服务由用户自己摸索出来的. 1.Zookeeper在大数据系统中的常见应用 zookeeper作为分布式协调系统在大数据领域非常常用,它是一个很好的中心化管理工具.下面举几个常见的应用场景. 1.1.HDFS/YARN HA(分布式锁的应用):Master挂掉之后迅速切换到slave节点.

一篇文章带你深入理解什么是负载测试

介绍 任何软件开发项目接近完成的时候,它可能已经通过无数次测试了,特别是在测试和开发同时发生的敏捷测试环境下.无论你已经进行过多少轮测试,一旦你的应用程序已接近完成,那么只有一个办法知道你的软件是否可以满足真实用户群的实际需求,它就是负载测试.你可以使用负载测试工具来完成这项工作.负载测试是指给软件.应用程序或网站加上模拟的需求,以测试其在不同的环境下的运行状态的过程. 负载测试和性能测试 作为大家最了解且最常见的一种性能测试类型,负载测试即包括将常规压力施加到软件应用或 IT 系统,去看它们是

一篇文章带你了解spring框架

虽然现在流行用SpringBoot了,很多配置已经简化和封装了,但是对于Spring的一些基础我们了解一些是对我们自己的架构思想很有帮助的!接下来和笔者一起来探讨一下Spring框架吧! 1.什么是Spring框架?Spring框架有哪些主要模块? Spring框架是一个为Java应用程序的开发提供了综合.广泛的基础性支持的Java平台.Spring帮助开发者解决了开发中基础性的问题,使得开发人员可以专注于应用程序的开发.Spring框架本身亦是按照设计模式精心打造,这使得我们可以在开发环境中安

一篇文章带你入门Linux——马哥Linux基础学习笔记

1.课程体系: 中级: 初级:系统基础 中级:系统管理.服务安全及服务管理.Shell脚本: 高级: MySQL数据库: cache & storage 集群: Cluster lb: 4layer 7layer ha: 分布式: zookeeper 分布式文件系统 虚拟化技术: xen kvm Openstack:IAAS云: 运维工具: ansible puppet(ruby), saltstack(python) 监控工具: zabbix 大数据处理: hadoop spark, stor

什么是网络爬虫?有什么用?怎么爬?一篇文章带你领略python爬虫的魅力

网络爬虫也叫做网络机器人,可以代替人们自动地在互联网中进行数据信息的采集与整理.在大数据时代,信息的采集是一项重要的工作,如果单纯靠人力进行信息采集,不仅低效繁琐,搜集的成本也会提高. 此时,我们可以使用网络爬虫对数据信息进行自动采集,比如应用于搜索引擎中对站点进行爬取收录,应用于数据分析与挖掘中对数据进行采集,应用于金融分析中对金融数据进行采集,除此之外,还可以将网络爬虫应用于舆情监测与分析.目标客户数据的收集等各个领域. 当然,要学习网络爬虫开发,首先需要认识网络爬虫,本文将带领大家一起认识

一篇文章带你领略Android混淆的魅力

在 Android 日常开发过程中,混淆是我们开发 App 的一项必不可少的技能.只要是我们亲身经历过 App 打包上线的过程,或多或少都需要了解一些代码混淆的基本操作.那么,混淆到底是什么?它的好处有哪些?具体效果如何?别急,下面我们来一一探索它的"独特"魅力. 混淆简介 代码混淆(Obfuscated code)是将程序中的代码以某种规则转换为难以阅读和理解的代码的一种行为. 混淆的好处 混淆的好处就是它的目的:令 APK 难以被逆向工程,即很大程度上增加反编译的成本.此外,And

一篇文章带你了解JavaScript中的函数表达式,递归,闭包,变量,this对象,模块作用域

作者 | Jeskson 来源 | 达达前端小酒馆 定义函数的方式: 第一种为 函数声明: 第二种为 函数表达式. 语法: function functionName(arg0, arg1, arg2) { // 函数体 } 在Firefox,Safari,Chrome和Opera有效: 就是通过这个属性可以访问到这个函数指定的名字. console.log(functionName.name); // 'functionName' 函数声明: 它的一个重要特点就是:函数声明提升,就是在执行代码

[转载] 一篇文章带你了解Paxos算法

原文: http://dockone.io/article/640 [编者的话]本文是Quora上关于Paxos算法的回答,两位答者分别从不同的角度描述Paxos算法.Vineet Gupta的回答细致入微,更偏向理论.Russell Cohen用具体的例子讲解Paxos算法,相辅相成. Vineet Gupta的回答 有很多关于一致性(consensus)问题的解决方案,而这些解决方案中,我认为Paxos相对来说很好理解. 『达成一致性』最简单的例子就是结婚誓词: “你愿意.......”(男

一篇文章带你深入了解Dubbo分布式服务框架

一.产生的背景 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进.下面我们用一个图来具体说明架构和开发框架的演进过程.单一应用架构当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本.此时,用于简化增删改查工作量的数据访问框架(ORM)是关键. 垂直应用架构当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率.此时,用于加速前端