ZooKeeper 集群搭建

ZooKeeper 概述

Zookeeper 是一个开源的分布式服务协调框架,由Apache软件基金会开发和维护。以下是对Zookeeper的主要概述:

  1. 设计目标

    • 提供分布式环境中的数据一致性。
    • 为分布式应用程序提供协调服务。
    • 简化复杂分布式系统的构建和管理。
  2. 功能特性

    • 数据模型:Zookeeper使用一个树形结构的数据模型(Znode),每个节点可以存储数据并具有版本号。
    • 一致性保证:Zookeeper保证在客户端看到的数据是一致的,提供顺序一致性、原子性和单一系统映像等特性。
    • 分布式锁:通过临时节点和 watches(监视器)机制,Zookeeper可以实现分布式锁,确保在分布式环境中对共享资源的互斥访问。
    • 集群管理:Zookeeper可以用于管理集群中的节点,如监控节点状态、动态加入或移除节点。
    • 配置管理:应用程序可以在Zookeeper中存储和获取配置信息,使得配置变更能够快速传播到所有相关节点。
    • 命名服务:Zookeeper可以作为命名服务,为分布式系统中的资源提供唯一的标识符。
  3. 工作原理

    • Zookeeper集群由一组相互协作的服务器组成,这些服务器共同维护一个具有相同数据副本的内存数据库。
    • 客户端与Zookeeper集群进行交互,读取数据、写入数据或者注册 watches以监听数据变化。
    • Zookeeper通过投票机制实现容错和领导选举,确保在部分服务器故障时仍能提供服务。
  4. 应用场景

    • 在Hadoop和HBase等大数据处理框架中,Zookeeper用于管理集群状态和协调任务。
    • 作为服务发现工具,帮助微服务架构中的服务注册和发现。
    • 在分布式消息队列系统中,如Kafka,用于Broker和Consumer的协调。

总的来说,Zookeeper在分布式系统中扮演着关键的角色,通过提供可靠的数据管理和协调服务,简化了分布式应用程序的开发和运维。

选举机制

1)集群中半数以上机器存活,集群可用。所以 Zookeeper 一般安装奇数台服务器,因为假设有 2N + 1 台机器只要 N + 1 台存活,集群就可用,再加一台也还是 N + 1 台,并不会提高集群可用性能,浪费资源。

2)服务器具有4种状态,分别是LOOKINGFOLLOWINGLEADINGOBSERVING

  • LOOKING:寻找Leader状态。当服务器处于该状态时,当前集群中没有Leader,因此需要进入Leader选举状态。
  • FOLLOWING:跟随者状态。表明当前服务器角色是Follower
  • LEADING:领导者状态。表明当前服务器角色是Leader
  • OBSERVING:观察者状态。表明当前服务器角色是ObserverObserver不参与投票和选举过程。

3)选举过程:假设有五台服务器组成的 Zookeeper 集群,它们的 id1 - 5。如果这些服务器依序启动**(第一次启动)**

  • 服务器 1 启动,发起选举
    • 服务器先投给自己一票,然后判断是否过半,显然不够,选举无法完成,服务器 1 状态保持为 LOOKING
  • 服务器 2 启动,发起选举
    • 服务器 2 先投给自己一票,然后与最开始启动的服务器 1 进行通信,互相交换自己的选举结果, id 值更大的服务器 2 胜出,服务器 1 将选票改投给 服务器 2,此时服务器 10 票,服务器 22 票,还不够半数,选举无法完成,服务器状态 1、2 保持为 LOOKING
  • 服务器 3 启动,发起选举
    • 服务器 3 先投给自己一票,根据上述方法同理服务器 1、2 都会改投服务器 3,此时服务器 10 票,服务器 20 票,服务器 33 票,(3/5) 超过半数,服务器 3 当选为 Leader。服务器状态 1、2 更改状态为 FOLLOWDING,服务器 3 更改状态为 LEADING
  • 服务器 4 启动,发起选举
    • 服务器先投给自己一票,此时已经存在 Leader 了,服务器 1、2、3 不会再改投了。所以投票结果为:服务器 33 票,服务器 41 票。服务器 4 服从多数,更改状态为 FOLLOWING
  • 服务器 5 启动,发起选举
    • 与服务器 4 同理,更改状态为 FOLLOWING

搭建前准备

下载地址:Index of /dist/zookeeper (apache.org)

文档地址:Apache ZooKeeper

这里选择 Zookeeper-3.5.7 版本进行搭建,自行配置 JDK7 或更高版本

分布式配置

分布式配置与伪分布式配置,主要有以下区别,其余配置均相同:

  • 伪分布式所使用的端口必须不同,分布式端口可以相同。
  • 伪分布式统一使用一个IP,分布式需要根据当前网络IP配置。

以下为分布式与伪分布式配置对比(以3个服务器节点为例):这里选择分布式配置

配置伪分布式分布式
clienPort2181;2182;21832181;2181;2181
server.1127.0.0.1:2888:3888hadoop102:2888:3888
server.2127.0.0.1:2889:3889hadoop103:2888:3888
server.3127.0.0.1:2890:3890hadoop104:2888:3888

分布式安装

先在 hadoop102 上操作最后分发文件,改个 myid 就行,也可以使用 MultiExec 功能一次向所有终端发送命令

解压缩并重命名

tar -zxvf apache-zookeeper-3.5.7-bin.tar.gz -C /opt/
mv /opt/apache-zookeeper-3.5.7-bin /opt/zookeeper-3.5.7

配置环境

vim /etc/profile.d/zookeeper.sh

添加下述内容:

export ZOOKEEPER_HOME=/opt/zookeeper-3.5.7
export PATH=$PATH:$ZOOKEEPER_HOME/bin

更新环境变量

source /etc/profile

配置服务器编号

hadoop102myid 设置为 1hadoop1032hadoop1043

mkdir -p $ZOOKEEPER_HOME/tmp/data
echo 1 > $ZOOKEEPER_HOME/tmp/data/myid

配置文件

$ZOOKEEPER_HOME/conf 这个目录下的 zoo_sample.cfg 复制为 zoo.cfg

cp $ZOOKEEPER_HOME/conf/zoo_sample.cfg $ZOOKEEPER_HOME/conf/zoo.cfg

修改配置

vim $ZOOKEEPER_HOME/conf/zoo.cfg

修改数据存储路径

dataDir=/opt/zookeeper-3.5.7/tmp/data

添加下述配置

server.1=hadoop102:2888:3888
server.2=hadoop103:2888:3888
server.3=hadoop104:2888:3888

下述配置参数含义

server.A=B:C:D
  • A 数字,表示这个是第几号服务器;即集群模式下配置的 myid
  • B 服务器的 IP 地址;
  • C 服务器与集群中的 Leader 服务器交换信息的端口;
  • D 当集群中的 Leader 服务器挂了,需要重新选举出一个新的 Leader 时,在这个端口进行服务器相互通信;
  • 2181:对外提供服务端口;
  • 2888:内部数据同步端口;
  • 3888:Leader 挂了,重新选举端口。

集群分发 zookeeper 目录和配置文件

xsync $ZOOKEEPER_HOME
xsync /etc/profile.d/zookeeper.sh

最后不要忘记去 hadoop102,hadoop104 上将 myid 改为 2,3 ,其他集群如果使用 $ZOOKEEPER_HOME 需要先 source /etc/profile 更新一下环境变量

[user@hadoop103 ~]$ echo 2 > $ZOOKEEPER_HOME/tmp/data/myid
[user@hadoop104 ~]$ echo 3 > $ZOOKEEPER_HOME/tmp/data/myid

操作集群

在每个服务器上启动 Zookeeper

[user@hadoop102 zookeeper-3.5.7]$ zkServer.sh start
[user@hadoop103 zookeeper-3.5.7]$ zkServer.sh start
[user@hadoop104 zookeeper-3.5.7]$ zkServer.sh start

使用 jpsall 查看进程,QuorumPeerMain 就是 Zookeeper 集群的启动入口类,用来加载配置启动 QuorumPeer 线程的

[user@hadoop102 ~]$ ./jpsall
=============== hadoop102 ===============
11507 QuorumPeerMain
12988 Jps
=============== hadoop103 ===============
14498 Jps
12887 QuorumPeerMain
=============== hadoop104 ===============
12471 Jps
11086 QuorumPeerMain

查看集群状态,按照半数选举机制三个服务器中第二个启动的集群就是 Leader

[user@hadoop102 zookeeper-3.5.7]$ zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower

[user@hadoop103 zookeeper-3.5.7]$ zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: leader

[user@hadoop104 zookeeper-3.5.7]$ zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower

此时可以尝试将 hadoop103 断掉按照投票机制应当是 hadoop104 当选 Leader

编写脚本

vim zk.sh

给执行权限

chmod 777 zk.sh

添加如下内容:

#!/bin/bash

if [ $# -lt 1 ]
then
    echo "No Args Input..."
    exit ;
fi

case $1 in
"start")
        echo "=========== 启动 zookeeper 集群 ==========="
        echo "------------- hadoop102 -----------------"
        ssh hadoop102 "$ZOOKEEPER_HOME/bin/zkServer.sh start"
        echo "------------- hadoop103 -----------------"
        ssh hadoop103 "$ZOOKEEPER_HOME/bin/zkServer.sh start"
        echo "------------- hadoop104 -----------------"
        ssh hadoop104 "$ZOOKEEPER_HOME/bin/zkServer.sh start"
;;
"stop")
        echo "=========== 关闭 zookeeper 集群 ==========="
        echo "------------- hadoop102 -----------------"
        ssh hadoop102 "$ZOOKEEPER_HOME/bin/zkServer.sh stop"
        echo "------------- hadoop103 -----------------"
        ssh hadoop103 "$ZOOKEEPER_HOME/bin/zkServer.sh stop"
        echo "------------- hadoop104 -----------------"
        ssh hadoop104 "$ZOOKEEPER_HOME/bin/zkServer.sh stop"
;;
"status")
        echo "=========== 查看 zookeeper 状态 ==========="
        echo "------------- hadoop102 -----------------"
        ssh hadoop102 "$ZOOKEEPER_HOME/bin/zkServer.sh status"
        echo "------------- hadoop103 -----------------"
        ssh hadoop103 "$ZOOKEEPER_HOME/bin/zkServer.sh status"
        echo "------------- hadoop104 -----------------"
        ssh hadoop104 "$ZOOKEEPER_HOME/bin/zkServer.sh status"
;;
*)
    echo "Input Args Error..."
;;
esac

运行脚本

1)启动 zookeeper 集群

./zk.sh start

=========== 启动 zookeeper 集群 ===========
------------- hadoop102 -----------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
------------- hadoop103 -----------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
------------- hadoop104 -----------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

2)查看集群各服务器状态

./zk.sh status

=========== 查看 zookeeper 状态 ===========
------------- hadoop102 -----------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower
------------- hadoop103 -----------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: leader
------------- hadoop104 -----------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower

3)关闭 zookeeper 集群

./zk.sh stop

=========== 关闭 zookeeper 集群 ===========
------------- hadoop102 -----------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.5.7/bin/../conf/zoo.cfg
Stopping zookeeper ... STOPPED
------------- hadoop103 -----------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.5.7/bin/../conf/zoo.cfg
Stopping zookeeper ... STOPPED
------------- hadoop104 -----------------
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.5.7/bin/../conf/zoo.cfg
Stopping zookeeper ... STOPPED

搭建过程中常见错误

Mode: standalone

这通常表示 Zookeeper 配置为单节点模式,而不是集群模式。需要检查 zoo.cfg 文件中的配置,确保包含了所有集群节点的信息。

启动失败

/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.5.7/bin/../conf/zoo.cfg
Starting zookeeper ... FAILED TO START
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Error contacting service. It is probably not running.

首先查看 $ZOOKEEPER_HOME/logs 目录下的 .out 后缀文件中报错内容(在 hadoop 系统中,.log 结尾的日志文件通常用于记录应用程序的日志信息,而 .out 结尾的文件则用于存储标准输出和标准错误信息),出现其他的报错问题都可以去 .out 后缀文件里查看报错信息,根据报错信息能更容易找到问题所在,更方便解决问题。

常见的错误如下:

  • 数据目录和日志目录:写绝对路径,不要写相对路径,也不要直接写 $ZOOKEEPER_HOME/tmp/data,示例

    dataDir=/opt/zookeeper-3.5.7/tmp/data
    
  • 服务器地址问题,如果这里写的 B 写的是用户名,检查 /etc/hosts 是否配置 IP 映射

    server.A=B:C:D
    
  • myid 不匹配: 在每个 Zookeeper 节点的数据目录下的 myid 文件,其中包含一个数字,表示该节点在集群中的唯一标识。如果这个数字与 zoo.cfg 中上述配置 A 不匹配,可能会导致集群故障。

  • 权限问题: 操作系统权限不足可能导致 Zookeeper 无法启动或运行。需要确保 Zookeeper 安装目录具有适当的读写执行 rwx 权限。

  • 进程冲突: 如果在启动 Zookeeper 时出现错误信息

    already running as process XXX 
    

    表示同一台机器上已经有一个 Zookeeper 进程在运行。可能需要停止现有的进程,或者检查是否有残留的进程占用端口,可以通过查看端口占用情况,如使用 netstat -apn | grep 2181 命令,解决端口冲突问题。

  • 防火墙未关闭:防火墙可能会阻止 Zookeeper 集群之间的通信。需要确保防火墙已关闭,或者将 Zookeeper 集群的端口添加到防火墙白名单中。

    例如,如果你使用的是firewalld,关闭防火墙示例代码

    systemctl stop firewalld.service # 停止firewall
    systemctl disable firewalld.service # 禁止firewall开机启动
    

    修改完防火墙配置文件后你需要保存修改并重启防火墙服务,以使更改生效。可以使用以下命令重启防火墙。具体的命令也取决于你使用的防火墙软件

    systemctl restart firewalld
    

    如果你使用的是 iptables 添加白名单示例代码

    iptables -A INPUT -p tcp --dport 2181 -j ACCEPT
    
  • Java 环境问题Java 环境未正确配置或使用的 Java 版本与 Zookeeper 不兼容。

解决这些问题通常需要仔细检查配置文件、日志文件和操作系统设置,并根据具体错误信息进行相应的调整。

  • 24
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值