
图解ZooKeeper,注册中心、负载均衡、通知机制、集群、写原理,
作者 | 哪吒
来源 |哪吒编程(ID:gh_61b183bcf690)
大家好,我是哪吒。
本系列为SpringCloud微服务系列,上一期分享了 图解Nginx,系统架构演变 + Nginx反向代理与负载均衡,今天分享ZooKeeper,读哪吒编程,品技术人生。
一、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了。
