- 什么是Zookeeper?
(1)分布式的协调服务,开源,主要作用为分布式应用提供一致性服务。在java中常用语服务的注册中心。
(2)zookeeper=文件系统+通知机制
2.zookper三种角色
Leader(领导者):为客户端提供读和写操作,负责投票的发起和决议,更新系统状态。Zookeeper中推选Leader 就是为了保持数据的一致性,都已leader节点上的数据为准。
Foller(跟随者):为客户端提供读服务,负责投票的发起和决议更新状态系统,若接收到写服务则转发给Leader。
Observe :作用于Flolower一样但是不参与投票。
- Leader选举
(1)Leader选举(票数大于总服务器一般的服务器为Leader)
Eg:
A B C D E
第一次 A启动 A———A
第二次 B启动 A———A
B———B
无法选出Leader,更改投票信息(Serverid小投给Serverid大的)
A——-B
B——-B 无法选出
第三次 C启动 C——-C 无法选出
更改投票 A——-C
B——–C
C———-C ,C获得3票,为Leader。
D,E启动,不需要选了。
(2)关于脑裂
1.防止由脑裂造成的集群不可用。
- 假如zookeeper集群有 5 个节点,发生了脑裂,脑裂成了A、B两个小集群:
(a) A : 1个节点 ,B :4个节点 , 或 A、B互换
(b) A : 2个节点, B :3个节点 , 或 A、B互换
② 假如zookeeper集群有4个节点同样发生脑裂,脑裂成了A、B两个小集群:
(a) A:1个节点 , B:3个节点, 或 A、B互换
(b) A:2个节点 , B:2个节点
什么是脑裂?
集群中出现了两个Leader。
为什么会出先这种情况
ZooKeeper内部通过心跳机制来确定leader的状态,由于网络原因,导致心跳监测超时。
1. 这时follower认为leader出现了故障,但是leader节点并没有故障,这就是假死状态。
2. leader节点假死后,ZooKeeper通知所有follower节点进行选举。这时出现一个新leader,这时集群中就出现了两个leader。
3. ZooKeeper将新leader信息通知给所有的follower节点和client。
4. 如果部分client获得了新的节点信息,而部分没有获得,这时client向ZooKeeper发送写请求时,ZooKeeper内部就会出现不一致。
解决方案:
1. Quorums法:通过设置法定人数, 进而确定集群的容忍度, 当集群中存活的节点少于法定人数, 集群将不可用
2. 冗余通信:集群中采用多种通信方式, 防止一种通信方式失效导致集群中的节点无法通信.
3. 通过共享资源的方式, 将所有共享资源添加到集群中, 能对共享资源进行写操作(即加锁)的节点就是leader节点.
ZooKeeper默认采用了Quorums的方式。
具体解决思路:ZooKeeper维护了一个叫epoch的变量, 每当新leader产生时, epoch都会递增, followers如果确认了新的leader存在, 同时也会知道其epoch的值 —— 它们会拒绝epoch小于现任leader的epoch的所有旧leader的任何请求.
(3)在容错能力相同的情况下,奇数台更节省资源。**
#### ZooKeeper 的读写机制
Zookeeper是由多个server组成的集群,一个leader,多个follower,每个server保存一份数据副本,数据是一致的,分布式读写, 更新请求转发,由leader实施。更新请求顺序进行,来自同一个client的更新请求按其发送顺序依次执行(FIFO机制)。数据更新原子性,一次数据更新要么成功,要么失败。
写流程:
![1564397760105](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1564397760105.png)
(1)Client向Zookeeper的server1发送一个写请求,客户端写数据到服务器1上;
(2)如果server1不是Leader,那么server1会把接收到的写请求转发给Leader;然后Leader会将写请求转发给每个server;
(3)当Leader收到集群半数以上的节点写成功的消息后,说明该写操作执行成功;
(4)被访问的server1进一步通知client数据写成功,这时,客户端就知道整个写操作成功了。
#### Zookeeper Shell
– 启动ZK服务: zkServer.sh start
– 查看ZK状态: zkServer.sh status
– 停止ZK服务: zkServer.sh stop
– 重启ZK服务: zkServer.sh restart
#### Zookeeper API
连接服务器:ZooKeeper(String connectString,int sessionTimeout,Watcher watcher)
创建节点:String create(final String path,byte[] data,List<ACL>acl,CreateModel createModel);
删除节点:void delete(final String path,int version);
3个节点,需要两个节点存活才能正常工作,允许一台出现宕机。
4个节点,需要3和节点存活才能正常工作。 允许一台出现宕机。