avatar

目录
[精]zookeeper总结与思考

一、介绍

概述

Zookeeper是一个开源的分布式的,为分布式应用提供协调服务的Apache项目。多作为集群提供服务的中间件.

Zookeeper从设计模式角度来理解,是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生了变化,Zookeeper就负责通知已经在Zookeeper上注册的那些观察者做出相应的反应.

分布式系统: 分布式系统指由很多台计算机组成的一个整体。

这个整体一致对外,并且处理同一请求,系统对内透明,对外不透明。

内部的每台计算机都可以相互通信,例如使用RPC 或者是WebService。客户端向一个分布式系统发送的一次请求到接受到响应,有可能会经历多台计算机。

Zookeeper = 文件系统 + 通知机制

特点

中心化集群,但是中心化集群易出现单点故障。

zk特点

数据结构

zk数据结构

应用场景

提供的服务包括:统一命名服务、统一配置管理、统一集群管理、服务器节点动态上下线、软负载均衡等。

二、安装及操作

需要提前安装JDK

两种部署方式:本地模式(standalone),分布式模式

分布式安装部署

版本:zookeeper-3.4.10

1、规划

将在hadoop102、hadoop103和hadoop104三个节点上部署Zookeeper。

2、解压安装

三台服务器分别解压:tar -zxvf zookeeper-3.4.10.tar.gz

解压后生成zookeeper-3.4.10目录

3、配置服务器编号

  • 在zookeeper-3.4.10目录下创建zkData:mkdir -p zkData

  • 进入目录:cd zkData

  • 创建myid文件:touch myid

  • 编辑文件:vim myid

在文件中添加与server对应的编号:比如hadoop02添加2;

  • 在hadoop103、hadoop104上修改myid文件中内容为3、4

4、修改配置文件

  • zookeeper-3.4.10/conf这个目录下的zoo_sample.cfg重命名为zoo.cfg:mv zoo_sample.cfg zoo.cfg

  • 打开zoo.cfg文件:vim zoo.cfg

  • 在文件中修改数据存储路径配置:

dataDir=/opt/module/zookeeper-3.4.10/zkData

  • 并且增加如下配置:

#######################cluster##########################

server.2=hadoop102:2888:3888

server.3=hadoop103:2888:3888

server.4=hadoop104:2888:3888

  • 同步zoo.cfg配置文件到其他所有服务器

【配置参数解读】server.A=B:C:D

A是一个数字,表示这个是第几号服务器【myid】;

zk启动时读取myid文件,拿到里面的数据与zoo.cfg里面的配置信息比较从而判断到底是哪个server。

B是这个服务器的ip地址;

C是这个服务器与集群中的Leader服务器交换信息的端口2888;【副本】

D是万一集群中的Leader服务器挂了,需要一个端口来重新进行选举,选出一个新的Leader,而这个端口就是用来执行选举时服务器相互通信的端口3888。【选举信息】

【扩展】2181,客户端访问端口

5、相关操作

  • 三台服务器在zookeeper-3.4.10下分别启动:bin/zkServer.sh start

  • 查看状态:bin/zkServer.sh status

shell
1
2
3
4
5
6
7
8
9
10
11
12
[ys@hadoop102 zookeeper-3.4.10]# bin/zkServer.sh status
JMX enabled by default
Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode: follower
[ys@hadoop103 zookeeper-3.4.10]# bin/zkServer.sh status
JMX enabled by default
Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode: leader
[ys@hadoop104 zookeeper-3.4.5]# bin/zkServer.sh status
JMX enabled by default
Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode: follower

客户端命令行操作

启动客户端:bin/zkCli.sh

命令基本语法 功能描述
help 显示所有操作命令
ls path [watch] 使用 ls 命令来查看当前znode中所包含的内容
ls2 path [watch] (详细信息)查看当前节点数据并能看到更新次数等数据
create 普通创建
-s 含有序列
-e 临时(重启或者超时消失)
get path [watch] 获得节点的值
set 设置节点的具体值
stat 查看节点状态
delete 删除节点
rmr 递归删除节点

三、内部原理【重点】

选举机制【重点】

  • 半数机制:

    • 集群中半数以上机器存活,集群可用。所以Zookeeper适合安装奇数台服务器。
  • 内部投票选举:

    • Zookeeper虽然在配置文件中并没有指定Master和Slave。但是,Zookeeper工作时,是有一个节点为Leader,其他则为Follower,Leader是通过内部的选举机制临时产生的。

【举例】五台服务器组成的Zookeeper集群,它们的id从1-5,同时它们都是最新启动的,也就是没有历史数据,在存放数据量这一点上,都是一样的。这些服务器依序启动,则:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
因为一共5台服务器,只有超过半数以上,即最少启动3台服务器,集群才能正常工作。

(1)服务器1启动,发起一次选举。
服务器1投自己一票。此时服务器1票数一票,不够半数以上(3票),选举无法完成;
服务器1状态保持为LOOKING;

(2)服务器2启动,再发起一次选举。
服务器1和2分别投自己一票,此时服务器1发现服务器2的id比自己大,更改选票投给服务器2;
此时服务器1票数0票,服务器2票数2票,不够半数以上(3票),选举无法完成;
服务器1,2状态保持LOOKING;

(3)服务器3启动,发起一次选举。
与上面过程一样,服务器1和2先投自己一票,然后因为服务器3id最大,两者更改选票投给为服务器3;
此次投票结果:服务器1为0票,服务器2为0票,服务器3为3票。此时服务器3的票数已经超过半数(3票),服务器3当选Leader。
服务器1,2更改状态为FOLLOWING,服务器3更改状态为LEADING;

(4)服务器4启动,发起一次选举。
此时服务器1,2,3已经不是LOOKING状态,不会更改选票信息。交换选票信息结果:服务器3为3票,服务器4为1票。
此时服务器4服从多数,更改选票信息为服务器3;
服务器4并更改状态为FOLLOWING;

(5)服务器5启动,同4一样投票给3,此时服务器3一共5票,服务器5为0票;
服务器5并更改状态为FOLLOWING;

最终Leader是服务器3,状态为LEADING;
其余服务器是Follower,状态为FOLLOWING。

参考文章: https://blog.csdn.net/weixin_43291055/article/details/95451357

选举机制文章推荐:

https://www.cnblogs.com/shuaiandjun/p/9383655.html

https://blog.csdn.net/wyqwilliam/article/details/83537139

节点类型

zk节点4大类型

监听器原理【重点】

监听器原理

写数据流程

写数据流程

【案例】监听服务器节点动态上下线/zk工作机制

zk工作机制

API操作:

1、maven依赖

xml
1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.10</version>
</dependency>

2、集群上创建/servers节点

shell
1
2
[zk: localhost:2181(CONNECTED) 10] create /servers "servers"
Created /servers

3、服务器端向Zookeeper注册

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import java.io.IOException;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids;

public class DistributeServer {

private static String connectString = "hadoop102:2181,hadoop103:2181,hadoop104:2181";
private static int sessionTimeout = 2000;
private ZooKeeper zk = null;
private String parentNode = "/servers";

// 创建到zk的客户端连接
public void getConnect() throws IOException{

zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {

@Override
public void process(WatchedEvent event) {

}
});
}

// 注册服务器
public void registServer(String hostname) throws Exception{

String create = zk.create(parentNode + "/server", hostname.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);

System.out.println(hostname +" is online "+ create);
}

// 业务功能
public void business(String hostname) throws Exception{
System.out.println(hostname+" is working ...");

Thread.sleep(Long.MAX_VALUE);
}

public static void main(String[] args) throws Exception {

// 1获取zk连接
DistributeServer server = new DistributeServer();
server.getConnect();

// 2 利用zk连接注册服务器信息
server.registServer(args[0]);

// 3 启动业务功能
server.business(args[0]);
}
}

4、客户端

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

public class DistributeClient {

private static String connectString = "hadoop102:2181,hadoop103:2181,hadoop104:2181";
private static int sessionTimeout = 2000;
private ZooKeeper zk = null;
private String parentNode = "/servers";

// 创建到zk的客户端连接
public void getConnect() throws IOException {
zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {

@Override
public void process(WatchedEvent event) {

// 再次启动监听
try {
getServerList();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

// 获取服务器列表信息
public void getServerList() throws Exception {

// 1获取服务器子节点信息,并且对父节点进行监听
List<String> children = zk.getChildren(parentNode, true);

// 2存储服务器信息列表
ArrayList<String> servers = new ArrayList<>();

// 3遍历所有节点,获取节点中的主机名称信息
for (String child : children) {
byte[] data = zk.getData(parentNode + "/" + child, false, null);

servers.add(new String(data));
}

// 4打印服务器列表信息
System.out.println(servers);
}

// 业务功能
public void business() throws Exception{

System.out.println("client is working ...");
Thread.sleep(Long.MAX_VALUE);
}

public static void main(String[] args) throws Exception {

// 1获取zk连接
DistributeClient client = new DistributeClient();
client.getConnect();

// 2获取servers的子节点信息,从中获取服务器信息列表
client.getServerList();

// 3业务进程启动
client.business();
}
}

四、其他

注意点:

1、zk常用端口号:

2181,客户端访问端口
2888,zk内部信息通讯(数据)
3888,zk选举专用

2、zk不能越级创建节点;

且创建节点一般要带有数据(除非数据是null),否则创建会失败

shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[zk: localhost:2181(CONNECTED) 1] create /ys/sss "666"
Node does not exist: /ys/sss
[zk: localhost:2181(CONNECTED) 2] create /ys "666"
Created /ys
...
[zk: localhost:2181(CONNECTED) 16] create /ss null
Created /ys
[zk: localhost:2181(CONNECTED) 17] ls /
[cluster, configs, controller, brokers, zookeeper, overseer, admin, isr_change_notification, controller_epoch, druid, aliases.json, live_nodes, collections, overseer_elect, spark, clusterstate.json, consumers, 【ss】, latest_producer_id_block, config, hbase, kylin]
[zk: localhost:2181(CONNECTED) 18] ls /ss
[]
[zk: localhost:2181(CONNECTED) 19] get /ss
null
...

常考面试题

  • 请简述ZooKeeper的选举机制

    半数机制:2n+1

    10 台服务器:3 台 zk

    20 台服务器:5 台 zk

    100 台服务器:11 台 zk

    【注意】台数并不是越多越好。 太多选举时间过长影响性能。

  • ZooKeeper的监听原理

  • ZooKeeper的常用命令

  • ZooKeeper的部署方式有哪几种?集群中的角色有哪些?集群最少需要几台机器?

    • 部署方式单机模式、集群模式
    • 角色:Leader和Follower
    • 集群最少需要机器数:3
文章作者: Yang4
文章链接: https://masteryang4.github.io/2020/05/14/%E7%B2%BE-zookeeper%E6%80%BB%E7%BB%93%E4%B8%8E%E6%80%9D%E8%80%83/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 MasterYangBlog
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论