超级详细的zookeeper的集群搭建

ZooKeeper集群搭建有两种方式:

- 伪分布式集群搭建:
所谓伪分布式集群搭建ZooKeeper集群其实就是在一台机器上启动多个ZooKeeper,在启动每个ZooKeeper时分别使用不同的配置文件zoo.cfg来启动,每个配置文件使用不同的配置参数(clientPort端口号、dataDir数据目录.
在zoo.cfg中配置多个server.id,其中ip都是当前机器,而端口各不相同,启动时就是伪集群模式了。
这种模式和单机模式产生的问题是一样的。也是用在测试环境中使用。

- 完全分布式集群搭建:
多台机器各自配置zoo.cfg文件,将各自互相加入服务器列表,每个节点占用一台机器

架构图
在这里插入图片描述

1.准备三台电脑(虚拟机)

  • 安装三个linux虚拟机

  • 配置虚拟网卡(三台电脑配置一个虚拟网卡)(虚拟网卡ip为:192.168.174.1)

  • 为每台虚拟机配置静态ip地址

三台虚拟机分别是:192.168.174.128、192.168.174.129、192.168.174.130

关闭防火墙:service iptables stop

-1.1查看是否已经安装jdk

命令:rpm -qa|grep java

没有安装记得要安装jdk

  • 上传jdk到linux

  • 解压jdk

命令: tar -vxf jdk-8u181-linux-i586.tar.gz

- 1.2、配置环境变量

命令:cd / 退回根目录

命令:cd etc

命令:vim profile (编辑etc/profile文件,将如下配置粘贴到文件中)

#set java environment
JAVA_HOME=/usr/local/jdk1.8.0_181
CLASSPATH=.:$JAVA_HOME/lib.tools.jar
PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME CLASSPATH PATH 
  • 重新加载profile文件,即激活profile文件

命令:source profile

2、安装zookeeper到虚拟机并解压

2.1配置zookeeper

  • 创建data目录

命令:cd zookeeper (进入zookeeper目录)

命令:mkdir data

  • 修改conf/zoo.cfg

命令:cd conf (进入conf目录)

命令:cp zoo_sample.cfg zoo.cfg(复制zoo_sample.cfg,文件名为zoo.cfg)
在这里插入图片描述

命令:vim zoo.cfg (修改zoo.cfg)

内容:

修改:

dataDir = /usr/local/zookeeper/data

添加:

server.1=192.168.174.128:2182:3182
server.2=192.168.174.129:2182:3182
server.3=192.168.174.130:2182:3182

在这里插入图片描述

  • 在data目录创建创建myid

命令:cd … (退出conf目录)

命令: cd data (进入data目录)

命令:vim myid(修改myid文件,分别设置为1,2,3)

3、启动zookeeper

命令:cd … (退出data目录)

命令:cd bin(进入bin路径)

命令: ./zkServer.sh start

3.1查看zookeeper状态

命令:./zkServer.sh status

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
4.leader选举

在领导者选举的过程中,如果某台ZooKeeper获得了超过半数的选票,则此ZooKeeper就可以成为Leader了。

  • 服务器1启动,给自己投票,然后发投票信息,由于其它机器还没有启动所以它收不到反馈信息,服务器1的状态一直属于Looking(选举状态)。
  • 服务器2启动,给自己投票,同时与之前启动的服务器1交换结果,
    每个Server发出一个投票由于是初始情况,1和2都会将自己作为Leader服务器来进行投票,每次投票会包含所推举的服务器的myid和ZXID,使用(myid, ZXID)来表示,此时1的投票为(1, 0),2的投票为(2, 0),然后各自将这个投票发给集群中其他机器。

接受来自各个服务器的投票集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票、是否来自LOOKING状态的服务器
处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行PK,PK规则如下
· 优先检查ZXID。ZXID比较大的服务器优先作为Leader。
· 如果ZXID相同,那么就比较myid。myid较大的服务器作为Leader服务器
由于服务器2的编号大,更新自己的投票为(2, 0),然后重新投票,对于2而言,其无须更新自己的投票,只是再次向集群中所有机器发出上一次投票信息即可,此时集群节点状态为LOOKING。

统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息

  • 服务器3启动,进行统计后,判断是否已经有过半机器接受到相同的投票信息,对于1、2、3而言,已统计出集群中已经有3台机器接受了(3, 0)的投票信息,此时投票数正好大于半数,便认为已经选出了Leader,
    改变服务器状态。一旦确定了Leader,每个服务器就会更新自己的状态,如果是Follower,那么就变更为FOLLOWING,如果是Leader,就变更为LEADING
    所以服务器3成为领导者,服务器1,2成为从节点。

ZXID: 即zookeeper事务id号。ZooKeeper状态的每一次改变, 都对应着一个递增的Transaction id, 该id称为zxid

4.1测试集群

第一步:3台集群,随便挑选一个启动,执行命令./zkCli.sh
在这里插入图片描述
第二步:添加节点数据
在这里插入图片描述
第三步:找另一台机器,测试查询,可以获取hello节点的数据
在这里插入图片描述
也可以使用代码测试

@Test
public void createNode() throws Exception {
  	RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
  	CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.174.128:2181", 3000, 3000, retryPolicy);
  	client.start();
  	client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/bbb/b1","haha".getBytes());
  	client.close();
}

@Test
public void updateNode() throws Exception {
  	//创建失败策略对象
  	RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,1);
  	CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.174.129:2181",1000,1000,retryPolicy);
  	client.start();
  	//修改节点
  	client.setData().forPath("/bbb/b1", "fff".getBytes());
  	client.close();
}

@Test
public void getData() throws Exception {
  	RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 1);
  	CuratorFramework client =
    CuratorFrameworkFactory.newClient("192.168.174.130:2181",1000,1000, retryPolicy);
  	client.start();
  	// 查询节点数据
  	byte[] bytes = client.getData().forPath("/bbb/b1");
  	System.out.println(new String(bytes));
  	client.close();
}

@Test
public void deleteNode() throws Exception {
  	RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 1);
  	CuratorFramework client =
    CuratorFrameworkFactory.newClient("192.168.174.130:2181",1000,1000, retryPolicy);
  	client.start();
  	// 递归删除节点
  	client.delete().deletingChildrenIfNeeded().forPath("/bbb");
  	client.close();
}

测试使用任何一个IP都可以获取

测试如果有个机器宕机,(./zkServer.sh stop),会重新选取领导者。

代码交流 2020