一、ZooKeeper是什么?
1、开源的分布式协调服务
使用分布式系统就无法避免对节点管理的问题(需要实时感知节点的状态、对节点进行统一管理等等),而由于这些问题处理起来可能相对麻烦和提高了系统的复杂性,ZooKeeper作为一个能够通用解决这些问题的中间件就应运而生了。
2、从设计模式角度来理解
ZooKeeper是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,一旦这些数据的状态发生变化,Zookeeper 就将负责通知已经在Zookeeper上注册的那些观察者做出相应的反应。
3、实现原理
zookeeper = 文件系统 + 通知机制。
二、Zookeeper的作用
1、统一配置管理
比如现在有A.yml,B.yml,C.yml配置文件,里面有一些公共的配置,但是如果后期对这些公共的配置进行修改,就需要修改每一个文件,还要重启服务器,比较麻烦。
现在将这些公共配置信息放到Zookeeper中,修改Zookeeper的信息,会通知A,B,C配置文件,很方便。
2、统一命名服务
这个的理解其实跟域名一样,在某一个节点下放一些ip地址,我现在只需要访问Zookeeper的一个Znode节点就可以获取这些ip地址。
3、同一集群管理
分布式集群中状态的监控和管理,使用Zookeeper来存储。
4、分布式协调
这个是我们最常用的,比如把多个服务提供者的信息放在某个节点上,服务的消费者就可以通过ZK调用。
服务节点动态上下线
如果提供者宕机,就会删除在Zookeeper的节点,然后Zookeeper通知给消费者。
5、软负载均衡
6、动态选举Master
Zookeeper会每次选举最小编号的作为Master,如果Master挂了,自然对应的Znode节点就会删除。然后让新的最小编号作为Master,这样就可以实现动态选举的功能了。
三、Zookeeper文件系统
ZooKeeper的数据结构,跟Unix文件系统非常类似,可以看做是一颗树,每个节点叫做Znode,每一个Znode只能存1MB数据,数据只是配置信息。
每一个节点可以通过路径来标识,结构图如下:
节点主要有4种类型:
1、临时目录节点:客户端与Zookeeper断开连接后,该节点被删除。
2、临时顺序编号目录节点:基本特性同临时节点,只是增加了顺序属性,节点名后边会追加一个由父节点维护的自增整型数字。
3、持久化目录节点:客户端与Zookeeper断开连接后,该节点依旧存在。
4、持久化顺序编号目录节点:基本特性同持久节点,只是增加了顺序属性,节点名后边会追加一个由父节点维护的自增整型数字。
四、通知机制 (监听机制)
Zookeeper可以提供分布式数据的发布/订阅功能,依赖的就是Wather监听机制。
客户端可以向服务端注册Wather监听,服务端的指定事件触发之后,就会向客户端发送一个事件通知。
1、具体步如下:
(1)客户端向服务端注册Wather监听。
(2)保存Wather对象到客户端本地的WatherManager中。
(3)服务端Wather事件触发后,客户端收到服务端通知,从WatherManager(watcher管理器)中取出对应Wather对象执行回调逻辑。
2、主要监听2方面内容:
(1)监听Znode节点的数据变化:就是那个节点信息更新了。
(2)监听子节点的增减变化:就是增加了一个Znode或者删除了一个Znode。
五、Zookeeper特性
1、一次性:一旦一个Wather触发之后,Zookeeper就会将它从存储中移除。
2、客户端串行:客户端的Wather回调处理是串行同步的过程,不要因为一个Wather的逻辑阻塞整个客户端。
3、轻量:Wather通知的单位是WathedEvent,只包含通知状态、事件类型和节点路径,不包含具体的事件内容,具体的时间内容需要客户端主动去重新获取数据。
六、Zookeeper集群
- Leader:负责写数据。(写数据都有事务)。
- Follower:负责读数据,节点的选举和过半写成功。(读数据没有事务)。
- Observer:只负责读。
从上面的角色种,我们可以总结Zookeeper节点的工作状态(服务状态)
- LOOKING:寻 找 Leader 状态。当服务器处于该状态时,它会认为当前集群中没有 Leader,因此需要进入 Leader 选举状态。
- FOLLOWING:跟随者状态。表明当前服务器角色是 Follower。
- LEADING:领导者状态。表明当前服务器角色是 Leader。
- OBSERVING:观察者状态。表明当前服务器角色是 Observer。
zxid:全局事务ID,分为两部分:
(1)纪元(epoch)部分:epoch代表当前集群所属的哪个leader,leader的选举就类似一个朝代的更替,你前朝的剑不能斩本朝的官,用epoch代表当前命令的有效性。
(2)计数器(counter)部分,是一个全局有序的数字,是一个递增的数字。
七、写数据原理
1、写给leader,leader再通知其他节点。
2、写给follower,follower没有写的权限,交给leader写,leader再通知。
3、半数机制:比如上图,zookeeper在通知其他节点写的时候,达到半数就通知客户端写完成。不需要全部写完成。所以集群的数量一般是奇数。
八、Zookeeper怎么保证数据一致性?
由于Zookeeper只有Leader节点可以写入数据,如果是其他节点收到写入数据的请求,则会将之转发给Leader节点。
Zookeeper通过ZAB协议来实现数据的最终顺序一致性,他是一个类似2PC两阶段提交的过程。ZAB有2种模式:消息广播,崩溃恢复(选举)。
一般我们正常是消息广播:
第一阶段:广播事务阶段
1、Leader收到请求之后,将它转换为一个proposal提议,并且为每个提议分配一个事务ID:zxid。
2、然后把提议放入到一个FIFO的队列中,按照FIFO的策略发送给所有的Follower。
3、Follower收到提议之后,以事务日志的形式写入到本地磁盘中,写入成功后返回ACK给Leader。
第二阶段:广播提交操作
Leader在收到超过半数的Follower的ACK之后,即可认为数据写入成功,就会发送commit命令给Follower告诉他们可以提交proposal了。
本文转载自微信公众号「哪吒编程」,可以通过以下二维码关注。转载本文请联系哪吒编程公众号。