AmosCloud

Library

Have a Question?

If you have any question you can ask below or enter what you are looking for!

Zookeeper

Zookeeper

是什么?

zookeeper是Hadoop生态的一个分布式集群协调服务。
zookeeper的主要使用场景:

  1. 管理集群节点在线状态
  2. 管理配置文件
  3. 管理集群节点之间的选举
  4. 分布式锁

集群搭建

  1. 下载解压改名
    http://archive.apache.org/dist/zookeeper/zookeeper-3.4.14/

  2. 修改配置文件

    • cd到conf目录下

      # 将zoo_sample.cfg复制并改名为  zoo.cfg
      cp zoo_sample.cfg zoo.cfg
    • 修改zoo.cfg

      # 修改zk保存数据的目录
      dataDir=/opt/zookeeper-3.4.14/data
      # 集群配置
      # server.A=B:C:D
      # A:是每个zk节点的唯一个标识id,是一个整数一般从,0开始
      # B:主机名或者IP地址
      # C:集群之间选举使用的通信端口
      # D:集群之间数据同步使用的通信端口
      server.1=node01:2888:3888
      server.2=node02:2888:3888
      server.3=node03:2888:3888
    • 配置myid文件

# 创建data目录
mkdir -p /opt/zookeeper-3.4.14/data
# cd到data目录
cd /opt/zookeeper-3.4.14/data
# 创建一个文件  文件名叫 myid 文件内容是当前机器对应的id号
echo 1 > myid
  1. 分发安装包

    • 分发之后需要为每台机器修改自己的myid文件
  2. 设置环境变量

echo 'export ZK_HOME=/opt/zookeeper-3.4.14' >> /etc/profile
echo 'export PATH=.:$ZK_HOME/bin:$PATH' >> /etc/profile
source /etc/profile
  1. 启动
# 启动zk服务
zkServer.sh start
# 查看状态
zkServer.sh status
# 关闭zk服务
zkServer.sh stop

核心概念

  • 集群特点

    1. 选举机制
      zk集群每一个节点在搭建时不用明确指定主从关系
      而是在集群启动后,自动选举出一个节点作为leader其他节点作为follower
    • 3.4.x版本中集群的选举机制如下
    • 半数以上取id最大作为leader
    1. 比如zk集群有5台机器 myid分别为1 2 3 4 5
    2. 如果myid为1的节点先启动,会使用2888端口与其他节点进行交互,1如果没有找到任何其他节点,他会不断使用2888端口发送一个信息,信息包含当前myid为1的机器将自己投票为leader,但是由于集群中已经启动的节点不到集群节点的半数,所以集群不能正常服务
    3. 如果myid为2的节点第二个启动,会使用2888端口与其他节点进行交互,发现1已经在线,这时1和2都会投票给当前id号较大的2号选举为leader,但是由于集群中已经启动的节点不到集群节点的半数,所以集群不能正常服务
    4. 如果myid为3的节点第二个启动,会使用2888端口与其他节点进行交互,发现1已经在线,这时1、2和3都会投票给当前id号较大的3号选举为leader,此时已经上线的机器已经超过集群节点半数,所以3选举成为leader,1、2成为follower
    5. 4、5上线时发现集群已经有leader产生,所以自动以follower身份加入集群
  1. 数据一致性

    zk集群中所有节点数据完全一致

file

  • zk中的每一步操作都会记录和更新逻辑时钟
  • Zxid是一个单调递增的id号,用来记录每一次的操作
# 执行get操作时除了可以查看到znode的数据
# 还可以看到znode的一些属性信息
[zk: node02(CONNECTED) 12] get /a
# znode的数据
aaa
# 属性
# c是craete
cZxid = 0x600000004
# 当前znode的创建时间
ctime = Mon May 24 09:20:15 CST 2021
# m是modifier
mZxid = 0x600000004
# 修改时间
mtime = Mon May 24 09:20:15 CST 2021
# p是parent
pZxid = 0x600000005
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 1
  1. znode类型

    • 生命周期
      1. 临时 EPHEMERAL
        临时znode,客户端断开连接时,自动消亡(删除)
    1. 永久 PERSISTENT
    • 是否有序号
      1. 有序号 SEQUENTIAL
        在创建节点时如果选择带有需要的节点,那么zk会自动在znode名称后带一个单调递增的序号
    1. 无序号
create [-s] [-e] path data
# -s 是否开始序号
# -e 是否设置为临时节点
# 默认创建无序号的永久节点

zk客户端shell操作

  • 客户端连接

    # 客户端连接方式
    zkCli.sh -server hostname:port
    # 端口默认为2181,如果没改可以省略不写
    zkCli.sh -server hostname
    # 默认服务器为localhost如果本机有zk服务可以省略不写
    zkCli.sh
  • 客户端操作

    # 查看某个路径下包含哪些子路径
    ls path
    # create [-s] [-e] path data acl
    # 创建一个路径并且添加一些数据
    create path data
    # 给某个路径设置数据
    set path data
    # 读取某个路径中的数据
    get path
    # 删除某个路径
    rmr path
    # 退出
    quit

zk客户端javaApi

  • maven依赖

    <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.14</version>
    </dependency>
  • 入口类

    • zookeeper的Java客户端使用Zookeeper对象
public class ZKTest {
    public static void main(String[] args) throws Exception {
        ZooKeeper zooKeeper = new ZooKeeper(
                "node01:2181,node02:2181,node03:2181",
                5000,
                new Watcher() {
                    @Override
                    public void process(WatchedEvent event) {
                        Event.EventType type = event.getType();
                    }
                });

        List<String> children = zooKeeper.getChildren("/", true);
        for (String child : children) {
            System.out.println(child);
        }

    }
}