ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google
的Chubby
一个开源的实现。node
Apache ZooKeeper is an effort to develop and maintain an open-source server which enables highly reliable distributed coordination.
mysql
ZooKeeper以Fast Paxos
(帕克索斯)算法为基础,让集群中的每一个zk实例数据保持一致。通常部署集群,机器数设置为奇数个,更容易知足>N/2的投票条件。nginx
/
├── app1
│ ├── p_1
│ ├── p_2
│ └── p_3
└── app2
复制代码
相似操做系统文件夹的树型模型,与文件夹的区别在于,每一个节点上可存储数据(不超过
1M
),每一个节点上的数据可带版本号。redis
zNode
节点类型2
个划分维度:按节点是否可持久化存储,分为持久节点与临时节点;按节点序号是否可顺序递增(相似mysql
的auto_increment
),分为顺序节点及非顺序节点,算法
注:3.6.0版本之后,还新增了Container Nodes
(容器节点),该节点的特色是,若是其下的全部子节点都被删除,该节点也会在未来某个时间被删除。sql
ZooKeeper has the notion of container nodes. Container nodes are special purpose nodes useful for recipes such as leader, lock, etc. When the last child of a container is deleted, the container becomes a candidate to be deleted by the server at some point in the future.
安全
持久节点
(client
建立持久节点后,就算与zk
断开,节点仍然保存在zk
中)
bash持久顺序节点
(eg: /order/quartz/wm000001 , /order/quartz/wm000002, /order/quartz/wm000003...)
架构临时节点
(client
与zk
断开链接后,节点自动删除)
并发临时顺序节点
Created event
(节点建立事件)Deleted event
(节点删除事件)Changed event
(节点的数据变化事件) -zkClient.subscribeChildChanges();
//订阅子节点的变化zkClient.subscribeDataChanges();
//订阅某节点的数据变化(包括数据被删除)事件zkClient.subscribeStateChanges();
//订单状态变化(状态包括:链接,断开,认证失败等等)以上为经常使用事件,其它事件请参考官方文档。实际使用中,不多用原生写法来监听事件,而是借助一些第三方的开源zk客户端,好比zkClient来监听事件。
ACL(Access Control List)
权限控制
Create、Read、Write、Delete、Admin
简称crwda
。其中:Delete
是指对子节点是否具备删除权限,其它4种权限指对自身节点的操做权限。world:
默认方式,无限制,全世界均能访问。auth:
在上下文中添加受权用户。digest:
用户名/密码认证ip: ip
地址认证要点:配置信息保存在
db
与zk
中(保险起见,数据安全性更高),弄一个后台管理界面,对配置修改后,先保存到db
,而后同步写入zk
的节点中。应用启动时,先连到zk
上读取节点中的配置,同时监听节点的数据变化,当配置变化时,获得实时通知。
(Single Point of Failure,SPOF)
└── ./OrderNoService
├── A0000001
10.0.0.1:8001
└── A0000002
10.0.0.2:8001
复制代码
多个服务实例,启动时在
zk
上临时顺序节点,服务的调用方约定取最小节点为Master
,当master
挂掉后,节点自动删除,调用方获得事件通知,取新的最小节点来调用(
至关于slave
提高为master)
上图中,左边为传统中心化的架构,缺点是每次有新的服务实例加入或下线,都要调整
nginx
中心节点的配置(
不论是人工,仍是借助工具自动)
,不利于云时代的动态弹性调整,并且总体的可用性强依赖于中心节点,一旦中心节点(
中心集群)
全挂掉,系统就不可用了。
Order
└── 3456890
├── 000001
├── 000002
└── 000003
复制代码
原理:以多个程序运行实例同时在处理订单
3456890
为例,每一个程序运行实例处理前,建立一个临时顺序节点,而后检查本身建立的节点是否为最小,若是不是,代表没抢到锁,若是是,表示抢到了锁,抢到锁的程序处理完之后,删除该节点表示释放锁。同时,其它处于等候状态的程序,为了实时获得锁的释放通知,均监听父节点Order/3456890
的子节点变化,发现子节点变化时,重复刚才的检测过程,直到本身建立的节点变成最小为止。 与redis SETNX
之类的分布式锁相比,zk
的分布式锁,还能实现解决Top N
之类的有限资源竞争问题(相似并发中的信号量)。好比:一堆程序要打印,可是只有2台打印机(或者打印队列的长度只有2,最多同时只能容许2个程序提交打印任务), 相似刚才的思路 ,能够检测最小的前2个节点,只有建立最小前2个节点的程序,才认为是拿到了信号,容许提交打印任务。
Queue
└── Queue1
├── 000001
├── 000002
└── 000003
复制代码
如上图,建立
Queue/Queue1
作为一个队列(或Topic
),而后每建立一个顺序节点,视为一条消息(节点存储的数据即为消息内容),生产者每次建立一个新节点,作为消息发送,消费者监听Queue1
的子节点变化(或定时轮询),每次取最小节点当作消费消息,处理完后,删除该节点。至关于实现了一个FIFO
(先进先出)的队列。 注:zk
框架强制的是CP
(一致性),而非专为高并发、高性能场景设计的,若是在高并发,qps
很高的状况下,分布式队列需酌情考虑。
id
Order
└── OrderId
├── 000001
├── 000002
└── 000003
复制代码
思路:每次要生成一个新
Id
时,建立一个持久顺序节点,建立操做返回的节点序号,即为新Id
,而后把比本身节点小的删除便可。
目前不少开源项目,几乎都是或多或少依赖
zookeeper
,好比:dubbo,disconf,kafka,...
分布式环境中,
zk
能用于什么场景,基本上取决于开发人员的想象力!