天天看点

ZooKeeper分布式一致性协调服务框架+过半数存货原则

zookeeper

什么是zookeeper?

分布式一致性协调服务框架

换言之,也可以zookeeper看成一个小型的分布式文件系统,

但是与FastDFS不同,zookeeper只适合用来存储一些小型的数据或者配置信息

提供配置信息管理,命名服务,分布式同步

zookeeper安装

1.zookeeper是纯java的所以需要JDK环境

2.单机安装-配置data/log路径后启动即可

zookeeper的文件系统

文件系统的数据结构

zookeeper底层是一个树形结构,用来存储数据

和Linux,Window等系统不同,Linux和Window中有文件和文件夹的概念,文件夹下面才能有文件,文件下面不能有文件,文件夹本身不存放数据,文件本身用来进行数据存储;

zookeeper中的结点,没有文件夹和文件之分,所有结点都可以进行数据存储,同时也可以拥有子节点;

每个结点称之为ZNode

ZNode的分类

1.临时节点-ephemeral:

临时节点由某个客户端创建,如果该客户端断开了和zookeeper服务器的连接,则该临时节点就会自动删除;

注意:临时节点不能有子节点

2.持久性节点-persistent:

持久化的节点会永久存在于文件系统中,除非客户端显示的删除该节点;该节点是最常见的节点;

3.顺序节点:

3.1临时顺序节点-ephemeral_sequential:

和临时节点有相同的特点,唯一的区别在于该节点名称会自动维护一个编号

3.2持久顺序节点-persistent_sequential:

和持久化的节点由相同的特点,唯一的区别在于该节点名称会自动维护一个编码

zookeeper文件系统操作命令

1…/zkCli.sh ip -p port;

进入命令行

2.ls path;

查看某个路径下的子节点情况,在zookeeper中只能写绝对路径,所有的路径都必须从/出发

3.create -s(顺序节点) -e(临时节点) path(路径) data(数据) acl(权限);

创建新节点,数据不能为空

4.get path;

查看指定路径对应的节点数据(数据部分+描述部分)

5.set path data [version]

修改指定节点的数据

6.delete path data

删除指定节点的数据

Java如何操作zookeeper

引入依赖然后,创建 zookeeper对象操作即可

zookeeper的通知(watch)机制

什么是通知机制?

客户端可以选择对某个ZNode进行监听,当这个ZNode发生变化时(本身的添加删除,修改以及子ZNode的变化),会主动通知监听了这个ZNode的客户端,zookeeper的通知机制有一次性触发原则,ZNode发生变化后,一旦通知了客户端,则断开客户端的监听,如果需要继续监听节点的变化,则必须重新发起监听

监听方法

自定义类MyWatch实现Wathcer接口,实现zookeeper的通知回调方法

//判断abc是否存在,并设置一个监听
//可以监听到节点创建,节点的内容修改,节点的删除
//但是不能监听到子节点的变化
zookeeper.exists("/abc",new MyWatch());

//无法监听到节点的创建,如果abc不存在则报错
//可以监听当前节点的内容修改,删除
zookeeper.getData("/abc",new MyWatch(),null);

//无法监听到节点的创建,如果abc不存在则报错
//无法监听节点本身的变化
//可以监听子节点的变化,子节点的添加和删除
//但是不包含内容变化,也不包括孙子节点的变化
zookeeper.getChildren("/abc",new MyWatch());
           
watch类型

1.数据watch

exists();

getData();

2.孩子watch

getChildren();

注意:不同的API监听的动作不同

事件类型

None:断开连接

NodeCreated:t添加

NodeDeleted:删除

NodeDataChanged:只和版本号有关

NodeChildrenChanged:子节点创建或删除

ZooKeeper的运用场景(重点)

1.配置文件统一管理

对分布式系统来说,有很多服务部署在不同的服务器上,不同的服务器有自己一套配置,如果需要配置进行调整,则需要对多台服务器逐个的修改,是不便于管理的

在zookeeper中创建/Configuration持久化节点,将配置信息放在其中

每个客户端都监听(Watch机制)该持久节点,如果有新的配置信息,开发者只需要上传到zookeeper这个节点上(更新节点的配置数据),一旦节点内容修改,每个应用都会得到zookeeper的通知,然后从中获得新的配置信息,在系统中完成配置更新;

2.集群管理

所谓集群管理无在乎两点:是否有机器退出和加入,选举master

在某些集群中可能需要其他集群服务器的状态,比如有机器加入或退出集群等,这个时候就可以通过zookeeper进行集群的统一管理

所有机器约定在父目录/GroupMembers下创建临时节点,每一个节点就代表一台机器,然后监听父目录节点的子节点的变化消息

一旦有机器添加和删除,每个机器都会收到通知,接受通知后,每个机器可以在查询节点信息,就可以知道哪个节点添加或者删除,就知道哪个机器进入或退出了,然后进行集群的配置

master选举的话我们一般通过在父节点创建顺序临时节点,选择编号最小的机器即可

3.分布式锁

实现方式:

1.保持独占:单进程

我们把zookeeper上的一个znode看做一把锁,所有的客户端同时创建一个lock临时节点,通过createNode()方法,谁创建成功,谁就获得锁了;业务操作结束后,释放锁删除该节点即可,就算客户端断开临时节点也会删除所以不用担心会形成死锁;

2.控制时序:加锁排队

创建一个父节点,所有的客户端在它下面创建顺序临时节点,我们保证编号最小的获得这个锁就可以了

4.命名服务(服务的发现和注册)

Dubbo使用的就是这个场景,基于ZooKeeper注册中心,命名服务

假设有一个A服务需要调用B服务,但是AB是两个互相独立的服务,A先完成,B还没有完成

A就可以主动获得zookeeper某个节点"/name",A就可以不需要再管了,B一旦完成,B直接去"/name"节点上将地址加入其中,A服务就监听到了节点内容的修改,就能够调用该地址

对于集群的负载均衡在父节点下面添加子节点就可以实现

Dubbo+ZooKeeper

在zookeeper的根目录下有/dubbo节点

/dubbo节点下面就是我们发布的服务节点

各个服务节点下面就有我们的服务信息,消费者,提供者,配置信息各种节点…

服务者节点中就存放了我们需要的调用地址,消费者一旦启动就会去其中获得调用地址,并且消费者也有地址但没有实际作用;

ZooKeeper集群,leader-follower

ZooKeeper集群由N台机器搭建,这些机器中一定会存在一个leader,其他的机器都是follower,所有客户端都可以随意连接集群中的任一机器;

对于内容修改操作,所有的follower都会收到leader的命令,由leader发起投票,票数超过一半以上则提交命令

集群搭建两种方式

伪集群模式

单机机器中启动多个ZooKeeper进程,并组成集群

步骤:

1.将单机装的zookeeper文件复制两份

2.在zookeeper/data中创建myid文件并编写id编码

3.修改zookeeper/conf/zoo.cfg核心配置文件port,以及data/log路径,还要配置

server.1=127.0.0.1:2888:3888

server.2=127.0.0.2:2889:3889

server.3=127.0.0.3:2890:3890

(这两个端口是集群内部通讯的端口)

真实集群就是不需要修改配置port和data路径

然后配置server的时候ip不一致

4.启动集群

./zkServer.sh status 查看服务状态,可知道leader/follower角色

集群模式

过半数存活原则

在zookeeper集群中,当存活的机器数量超过总机器的一半的时候,整个集群才能正常工作,否则拒绝访问

基于过半数存活原则,zookeeper的集群机器数量一定是奇数台,因为2N+1和2N+2的容灾能力是一样的,基于成本考虑2N+1台的选择方案更优

为什么zookeeper需要设计一个过半数存活机制?

为了防止网络脑裂,保证数据的强一致性

因为整个集群中,有可能因为网络问题"脑裂",导致整个集群分为2个甚至多个集群,如果没有过半数存活机制,那么整个zookeeper会变成多个集群,那么zookeeper提供的数据无法再保证数据一致性;

zookeeper集群角色

1.Leader领导者

2.Learner学习者:

Follower跟随者:

ObServer观察者:功能和追随者一致,响应客户端的命令,不能参加选举和投票环节

3.Client客户端

ZAB协议-原子消息广播协议

ZooKeeper作为高可用的一致性协调框架

自然的ZooKeeper也有着一致性算法的实现,ZooKeeper使用的是ZAB协议作为数据一致性的算法,ZAB(ZooKeeper Atomic Broadcast )

ZAB基础

Leader选举;

在ZooKeeper中所有的事务请求都由一个主服务器也就是Leader来处理,其他服务器为Follower,Leader将客户端的事务请求转换为事务Proposal,并且将Proposal分发给集群中其他所有的Follower,然后Leader等待Follwer反馈,当有过半数(>=N/2+1)的Follower反馈信息后,Leader将再次向集群内Follower广播Commit信息,Commit为将之前的Proposal提交;

ZAB协议的状态

Looking:选举状态

Leading:领导状态

Following:跟随状态

zookeeper配置详解

核心配置文件zoo.cfg

tickTime:心跳间隔时间,默认为2000ms

zookeeper中使用的基本时间单位, 毫秒值。

dataDir:数据目录。

修改为zookeeper安装目录下的data目录,data目录自己创建,当然也可以指定为别的目录。

initLimit:连接超时时间

Follower初始化连接时和Leader连接的超时时间。默认为10(10 * 2000ms(tickTime))

zookeeper集群中的包含多台server,其中一台为leader,其余的server为follower。

initLimit参数配置初始化连接时,follower和leader之间的最长心跳时间。

syncLimit:消息通信超时时间

该参数配置leader和follower之间发送消息,请求和应答的最大时间长度。

此时该参数设置为2,说明时间限制为2倍tickTime,即4000ms

集群配置详解

server.serverid=serverhost:leader_listent_port:quorum_port

serverid:myid

是当前zookeeper服务器的id(myid文件中写的编号)。

leader_listen_port:领导监听端口

通常叫做原子广播端口,是该服务器一旦成为leader之后需要监听的端口,用于接收来自follower的请求。

quorum_port:选举端口

通常叫做选举端口,是集群中的每一个服务器在最开始选举leader时监听的端口,用于服务器互相之间通信选举leader。

继续阅读