Zookeeper.01 - 简介
是什么?
Zookeeper 是一个开源的分布式协同服务系统。Zookeeper 的设计目标是将那些复杂且容易出错的分布式协同服务封装起来,抽象出一个高效可靠的原语集,并以一系列简单的接口提供给用户使用。
为什么要有分布式协同服务系统?
分布式协调技术,是为了解决分布式系统中多进程对临界资源的访问问题。
分布式协调技术主要用来解决分布式环境当中多个进程之间的同步控制,让他们有序的去访问某种临界资源,防止造成"脏数据"的后果。
当我们在第一台机器上挂载了一个临界资源(比如商品的数量),然后这三个物理分布的微服务都要竞争这个资源(即修改商品的数量),但我们又不希望他们同时进行访问,这时候我们就需要一个协调器,来让他们有序的来访问这个资源。这个协调器就是我们经常提到的那个锁。
比如说"微服务-1"在使用该资源的时候,会先去获得锁,"微服务 1"获得锁以后会对该资源保持独占,这样其他进程就无法访问该资源,"微服务 1"用完该资源以后就将锁释放掉,让其他进程来获得锁,那么通过这个锁机制,我们就能保证了分布式系统中多个进程能够有序的访问该临界资源。那么我们把这个分布式环境下的这个锁叫作分布式锁。
这个分布式锁也就是我们分布式协调技术实现的核心内容。
分布式锁要解决的问题
在分布式系统中最大的问题是,网络是不可靠的。
你对一个服务的调用失败了并不表示一定是失败的,可能是执行成功了,但是响应返回的时候失败了。
如果 A 和 B 都去调用 C 服务,在时间上 A 还先调用一些,B 后调用,那么最后的结果是不是一定 A 的请求就先于 B 到达呢?
为了实现分布式锁,zookeeper 出现了。
典型应用场景:
配置管理(configuration management)
ONS 服务
组成员管理(group membership)
各种分布式锁
需要注意的是,Zookeeper 适用于存储和协同相关的关键数据,不适合用于大数据量存储。
数据模型
层次模型 —— data tree
ZooKeeper 的数据模型是层次模型(Google Chubby 也是这么做的)。层次模型常见于文件系统。层次模型和 key-value 模型是两种主流的数据模型。ZooKeeper 使用文件系统模型主要基于以下两点考虑:
文件系统的树形结构便于表达数据之间的层次关系。
文件系统的树形结构便于为不同的应用分配独立的命名空间(namespace)
ZooKeeper 的层次模型称作 data tree,Data tree 的每个节点叫作 znode,不同于文件系统,每个节点都可以保存数据。每个节点都有一个版本(version),版本从 0 开始计数。
data tree 示例
在下图所示的 data tree 中有两个子树,一个用于应用 1(/app1)和另一个用于应用 2(/app2)应用 1 的子树实现了一个简单的组成员协议:每个客户端进程 pi;创建一个 znode p_i
在/app1 下,只要/app1/p_i
存在就代表进程 pi 在正常运行。
data tree 接口
Zookeeper 对外提供一个用来访问 data tree 的简化文件系统 API:
使用 UNIX 风格的路径名来定位 znode,例如 /A/X 表示 znode A 的子节点 x。
znode 的数据只支持全量写入和读取,没有像通用文件系统那样支持部分写入和读取。
data tree 的所有 API 都是 wait-free 的。即,正在执行中的 API 调用不会影响其他 API 的完成。
data tree 的 API 都是对文件系统的 wait-free 操作,不直接提供锁这样的分布式协同机制。但是 data tree 的 API 非常强大,可以用来实现多种分布式协同机制。
节点模型 - znode
前面我们说到,每一层都是一个节点,每个节点都可以保存数据,也都带有版本。除此之外,Zookeeper 还为 znode 提供了不同属性的设置,因此存在不同的类型的节点。
znode 分类
znode 可以使持久性的,也可以是临时性的:
持久性的 znode(PERSISTENT):这样的 znode 在创建之后即使发生 Zookeeper 集群宕机或者 client 宕机也不会丢失。
临时性的 znode(EPHEMERAL): client 宕机或者 client 在指定的 timeout 时间内没有给 Zookeeper 集群发消息,这样的 znode 就会消失。
znode 也可以是顺序性的。每一个顺序性的 znode 关联一个唯一的单调递增整数。这个单调递增整数是 znode 名字的后缀。如果上面两种 znode 具备顺序性,又会组成以下两种 znode:
持久顺序性的 znode(PERSISTENT-SEQUENTIAL):znode 除了具备持久性 znode 的特点之外,znode 的名字具备顺序性。
临时顺序性的 znode(EPHEMERAL-SEQUENTIAL):znode 除了具备临时性 znode 的特点之外,znode 的名字具备顺序性。
Zookeeper 主要有以上 4 种 znode。
watch 机制
做为一个分布式协调服务,要解决的第一个问题就是,如何让所有客户端感知到节点的变化。
要获取远端的变化情况,有 Push(推) 和 Pull(拉) 这两种方式。如果选用客户端 Pull 的方式,客户端需要不断轮询 Zookeeper 来查看是否有数据更新,但这在分布式环境中是非常耗时的。因此 Zookeeper 采用了 Push 的方式,并将这个方式命名为 watch 机制。
watch 提供一个让客户端获取最新数据的机制。客户端可以在读取数据的时候设置一个 watcher,这样在数据更新时,客户端就会收到通知。
下图就是一个 watch 机制的例子:
客户端 1 通过 get -w 命令来获取这个节点的值,并对节点的变化进行 watch 。
当客户端 2 通过 set 命令修改节点的值和版本号。
这个时候 Zookeeper 就会向客户端 1 推送通知。
客户端 1 就可以再执行一次 get 命令来获取 Zookeeper 上的最新值了。
版权声明: 本文为 InfoQ 作者【insight】的原创文章。
原文链接:【http://xie.infoq.cn/article/d278b76618d4705b1b16f1c3f】。文章转载请联系作者。
评论