参考:
分布式:
虽然分布式和集中式系统相比有很多优势,比如能提供更强的计算、存储能力,避免单点故障等问题。
但是由于采用分布式部署的方式,就经常会出现网络故障等问题,并且如何在分布式系统中保证数据的一致性和可用性也是一个比较关键的问题。
分布式的工作方式有点类似于团队合作。
当有一项任务分配到某个团队之后,团队内部的成员开始各司其职,然后把工作结果统一汇总给团队主管,由团队主管再整理团队的工作成果汇报给公司。
但是,日常工作中,如果两个员工或用户对某件事产生了分歧,通常我们的做法是找上级,去做数据和信息的同步。
那么对于我们的服务呢,多个节点之间数据不同步如何处理?
对于分布式集群来说,这个时候,我们通常一个能够在各个服务或节点之间进行协调的服务或中间人
架构设计中,没有一个问题不能通过增加一个抽象层来解决的,如果有,那就增加两层。
最初,在Hadoop生态中,会存在很多的服务或组件(比如hive、pig等),每个服务或组件之间进行协调处理是很麻烦的一件事情,急需一种高可用高性能数据强一致性的协调框架。
因此雅虎的工程师们创造了这个中间程序,但中间程序的命名却愁死了开发人员,突然想到hadoop中的大多是动物名字,似乎缺乏一个管理员,这个程序的功能有是如此的相似。因此zookeeper诞生。
Zookeeper 最早起源于雅虎研究院的一个研究小组。在当时,研究人员发现,在雅虎内部很多大型系统基本都需要依赖一个类似的系统来进行分布式协调,但是这些系统往往都存在分布式单点问题。所以,雅虎的开发人员就试图开发一个通用的无单点问题的分布式协调框架,以便让开发人员将精力集中在处理业务逻辑上,Zookeeper 就这样诞生了。后来捐赠给了 Apache
,现已成为 Apache
顶级项目。
Zookeeper是一个开放源码的分布式服务协调组件,是Google Chubby的开源实现。是一个高性能的分布式数据一致性解决方案。他将那些复杂的、容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并提供一系列简单易用的接口给用户使用。
分布式系统是一个硬件或软件组件分布在不同的网络计算机中上,彼此之间仅仅通过消息传递进行通信和协调的系统。
计算机系统从集中式到分布式的变革伴随着包括分布式网络、分布式事务、分布式数据一致性等在内的一系列问题和挑战,同时也催生了一大批诸如ACID
、CAP
和 BASE
等经典理论的快速发展。
为了解决分布式一致性问题,涌现出了一大批经典的一致性协议和算法,最为著名的就是二阶段提交协议(2PC),三阶段提交协议(3PC)和Paxos
算法。Zookeeper
的一致性是通过基于 Paxos
算法的 ZAB
协议完成的。
ZooKeeper 官网是这么介绍的:”Apache ZooKeeper 致力于开发和维护一个支持高度可靠的分布式协调的开源服务器“
ZooKeeper 是 Apache 软件基金会的一个软件项目,它为大型「分布式计算」提供开源的分布式配置服务、同步服务和命名注册。
ZooKeeper 是用于维护配置信息,命名,提供分布式同步和提供组服务的集中式服务。
所有这些类型的服务都以某种形式被分布式应用程序使用。每次实施它们时,都会进行很多工作来修复不可避免的 bug 和竞争条件。由于难以实现这类服务,因此应用程序最初通常会跳过它们,这会使它们在存在更改的情况下变得脆弱并且难以管理。即使部署正确,这些服务的不同实现也会导致管理复杂。
ZooKeeper 的目标是将这些不同服务的精华提炼为一个非常简单的接口,用于集中协调服务。
服务本身是分布式的,并且高度可靠。
服务将实现共识,组管理和状态协议,因此应用程序不需要自己实现它们。
ZooKeeper工作机制
ZooKeeper 从设计模式角度来理解:就是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,ZK 就将负责通知已经在 ZK 上注册的那些观察者做出相应的反应,从而实现集群中类似 Master/Slave 管理模式。
-
ZooKeeper:一个领导者(leader),多个跟随者(follower)组成的集群。
-
Leader 负责进行投票的发起和决议,更新系统状态。
-
Follower 用于接收客户请求并向客户端返回结果,在选举 Leader 过程中参与投票。
-
集群中只要有半数以上节点存活,Zookeeper 集群就能正常服务。
-
全局数据一致(单一视图):每个 Server 保存一份相同的数据副本,Client 无论连接到哪个 Server,数据都是一致的。
-
顺序一致性: 从同一客户端发起的事务请求,最终将会严格地按照顺序被应用到 ZooKeeper 中去。
-
原子性: 所有事务请求的处理结果在整个集群中所有机器上的应用情况是一致的,也就是说,要么整个集群中所有的机器都成功应用了某一个事务,要么都没有应用。
-
实时性,在一定时间范围内,client 能读到最新数据。
-
可靠性: 一旦一次更改请求被应用,更改的结果就会被持久化,直到被下一次更改覆盖。
-
简单的数据结构 :Zookeeper 使得分布式程序能够通过一个共享的树形结构的名字空间来进行相互协调,即Zookeeper 服务器内存中的数据模型由一系列被称为
ZNode
的数据节点组成,Zookeeper 将全量的数据存储在内存中,以此来提高服务器吞吐、减少延迟的目的。 -
可以构建集群 :Zookeeper 集群通常由一组机器构成,组成 Zookeeper 集群的每台机器都会在内存中维护当前服务器状态,并且每台机器之间都相互通信。
-
顺序访问 :对于来自客户端的每个更新请求,Zookeeper 都会分配一个全局唯一的递增编号,这个编号反映了所有事务操作的先后顺序。
-
高性能 :Zookeeper 和 Redis 一样全量数据存储在内存中,100% 读请求压测 QPS 12-13W
Zookeeper 数据模型的结构与 Unix 文件系统的结构相似,整体上可以看做是一棵树,每个节点称作一个 「ZNode」。每个 ZNode 默认能存储 1MB 的数据,每个 ZNode 都可以通过其路径唯一标识。
应用场景
ZooKeeper 是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能
- zookeeper用得比较多的地方可能是,微服务的集群管理与服务注册与发现。
在注册中心的应用场景下,相对于与强数据一致性,更加关心可用性。
2. 分布式锁
分布式锁的对比
具体差异比较:
从理解的难易程度角度(从低到高)数据库 > 缓存(Redis) > Zookeeper
从实现的复杂性角度(从低到高)Zookeeper >= 缓存(Redis) > 数据库
从性能角度(从高到低)缓存(Redis) > Zookeeper >= 数据库
从可靠性角度(从高到低)Zookeeper > 缓存(Redis) > 数据库
分布式锁
分布式锁,这个主要得益于 ZooKeeper 为我们保证了数据的强一致性。
锁服务可以分为两类,一个是保持独占,另一个是控制时序。
-
所谓保持独占,就是所有试图来获取这个锁的客户端,最终只有一个可以成功获得这把锁。通常的做法是把 zk 上的一个 znode 看作是一把锁,通过
create znode
的方式来实现。所有客户端都去创建/distribute_lock
节点,最终成功创建的那个客户端也即拥有了这把锁。 -
控制时序,就是所有试图来获取这个锁的客户端,最终都是会被安排执行,只是有个全局时序了。做法和上面基本类似,只是这里
/distribute_lock
已预先存在,客户端在它下面创建临时有序节点(这个可以通过节点的属性控制:CreateMode.EPHEMERAL_SEQUENTIAL
来指定)。ZK 的父节点(/distribute_lock
)维持一份 sequence,保证子节点创建的时序性,从而也形成了每个客户端的全局时序。
个人感觉还是用 Redis 实现分布式锁更加方便。
PS:阿里中间件团队:“其实,ZK 并非天生就是为这些应用场景设计的,都是后来众多开发者根据其框架的特性,利用其提供的一系列API接口(或者称为原语集),摸索出来的典型使用方法。”
3. 集群管理与master选举;统一集群管理
所谓集群管理无在乎两点:是否有机器退出和加入、选举 Master。
管理节点
-
分布式环境中,实时掌握每个节点的状态是必要的,比如我们要知道集群中各机器状态、收集各个机器的运行时状态数据、服务器动态上下线等。
-
交由 ZooKeeper 实现的方式
-
可将节点信息写入 ZooKeeper 上的一个 Znode
-
监听这个 Znode 可获取它的实时状态变化
-
典型应用:HBase 中 Master 状态监控和选举。(TODO:图应该是注册和Register and watch)
Master选举
在分布式环境中,相同的业务应用分布在不同的机器上,有些业务逻辑(例如一些耗时的计算,网络I/O处理),往往只需要让整个集群中的某一台机器进行执行,其余机器可以共享这个结果,这样可以大大减少重复劳动,提高性能,于是这个master选举便是这种场景下的碰到的主要问题。
利用 Zookeeper 的强一致性,能够很好的保证在分布式高并发情况下节点的创建一定是全局唯一的,即:同时有多个客户端请求创建 /currentMaster
节点,最终一定只有一个客户端请求能够创建成功。Zookeeper 通过这种节点唯一的特性,可以创建一个 Master 节点,其他客户端 Watcher 监控当前 Master 是否存活,一旦 Master 挂了,其他机器再创建这样的一个 Master 节点,用来重新选举。
4. 统一命名服务
在分布式系统中,通过使用命名服务,客户端应用能够根据指定名字来获取资源或服务的地址,提供者等信息。被命名的实体通常可以是集群中的机器,提供的服务地址,进程对象等等——这些我们都可以统称他们为名字(Name)。其中较为常见的就是一些分布式服务框架(如RPC、RMI)中的服务地址列表。通过调用 Zookeeper 提供的创建节点的 API,能够很容易创建一个全局唯一的 path,这个 path 就可以作为一个名称。
阿里巴巴开源的分布式服务框架 Dubbo 就使用 ZooKeeper 来作为其命名服务,维护全局的服务地址列表。
5.数据发布与订阅(配置中心)
发布与订阅模型,即所谓的配置中心,顾名思义就是发布者将数据发布到 ZooKeeper 节点上,供订阅者动态获取数据,实现配置信息的集中式管理和动态更新。例如全局的配置信息,服务式服务框架的服务地址列表等就非常适合使用。
-
分布式环境下,配置文件管理和同步是一个常见问题
-
一个集群中,所有节点的配置信息是一致的,比如 Hadoop 集群、集群中的数据库配置信息等全局配置
-
对配置文件修改后,希望能够快速同步到各个节点上。
-
配置管理可交由 ZooKeeper 实现
-
-
可将配置信息写入 ZooKeeper 上的一个 Znode
-
各个节点监听这个 Znode
-
一旦 Znode 中的数据被修改,ZooKeeper 将通知各个节点
6. 软负载均衡
分布式系统中,负载均衡是一种很普遍的技术,为了保证高可用性,通常同一个应用或同一个服务的提供方都会部署多份,达到对等服务。可以是硬件的负载均衡,如 F5,也可以是软件的负载,我们熟知的 Nginx,或者这里介绍的 Zookeeper。
-
7.分布式协调/通知
Zookeeper 中特有的 「Watcher」 注册与异步通知机制,能够很好的实现分布式环境下不同机器,甚至不同系统之间的协调和通知,从而实现对数据变更的实时处理。
使用方法通常是不同系统都对 ZK 上同一个 znode 进行注册,监听 znode 的变化(包括 znode 本身内容及子节点的),其中一个系统 update 了 znode,那么另一个系统能够收到通知,并作出相应处理。
-
心跳检测中可以让检测系统和被检测系统之间并不直接关联起来,而是通过 ZK 上某个节点关联,减少系统耦合;
-
系统调度模式中,假设某系统有控制台和推送系统两部分组成,控制台的职责是控制推送系统进行相应的推送工作。管理人员在控制台作的一些操作,实际上是修改了 ZK 上某些节点的状态,而 ZK 就把这些变化通知给他们注册 Watcher 的客户端,即推送系统,于是,作出相应的推送任务。
3. 你要知道的概念
-
ZooKeeper 本身就是一个分布式程序(只要半数以上节点存活,ZooKeeper 就能正常服务)。
-
为了保证高可用,最好是以集群形态来部署 ZooKeeper,这样只要集群中大部分机器是可用的(能够容忍一定的机器故障),那么 ZooKeeper 本身仍然是可用的。
-
ZooKeeper 将数据保存在内存中,这也就保证了高吞吐量和低延迟(但是内存限制了能够存储的容量不太大,此限制也是保持 znode 中存储的数据量较小的进一步原因)。
-
ZooKeeper 是高性能的。在“读”多于“写”的应用程序中尤其的高性能,因为“写”会导致所有的服务器间同步状态。(“读”多于“写”是协调服务的典型场景。)
-
ZooKeeper 底层其实只提供了两个功能:
-
-
管理(存储、读取)用户程序提交的数据
-
为用户程序提交数据节点监听服务
-
这里引入一个简单的例子,逐个介绍一些 ZK 中的概念。
在分布式系统中经常会遇到这种情况,多个应用读取同一个配置。例如:Client1,Client2 两个应用都会读取配置 B 中的内容,一旦 B 中的内容出现变化,就会通知 Client1 和 Client2。
一般的做法是在 Client1,Client2 中按照时钟频率询问 B 的变化,或者使用观察者模式来监听 B 的变化,发现变化以后再更新两个客户端。那么 ZooKeeper 如何协调这种场景?
这两个客户端连接到 ZooKeeper 的服务器,并获取其中存放的 B。保存 B 值的地方在 ZooKeeper 服务端中就称为 ZNode。
参考:
《从Paxos到ZooKeeper 分布式一致性原理与实践》
《阿里中间件团队博客》http://jm.taobao.org/2011/10/08/1232/
《Zookeeper官方文档》https://zookeeper.apache.org/doc/
《尚硅谷Zookeeper》
https://cloud.tencent.com/developer/article/1578401