ZooKeeper概述

1. ZooKeeper入門

1.1 概述

Zookeeper是一個開源的,爲分佈式應用提供協調服務的Apache項目.
ZooKeeper工作機制
ZooKeeper從設計模式角度來理解,是一個基於觀察者模式設計的,分佈式服務管理框架.它負責存儲和管理大家都關心的數據,然後接受觀察者的註冊,一旦這些數據發生變化,ZooKeeper就將負責通知已註冊的觀察者做出相應的反應.

1.2 特點

在這裏插入圖片描述

  1. ZooKeeper由一個leader和多個follower組成.
  2. 集羣中只要有半數以上的節點存活,ZooKeeper就能正常服務.
  3. 全局一直:每個server保存一份相同的數據副本,Client無論連接到哪個server,數據都是一致的.
  4. 更新請求順序執行:來自同一個Client的更新請求,按發送的事件順序執行.
  5. 數據更新原子性,一次數據更新要麼成功,要麼失敗.
  6. 實時性,在一定時間範圍內,Client能讀到最新的數據.

1.3 數據結構

在這裏插入圖片描述
ZooKeeper數據模型的結構與Unix文件系統類似,整體上可以看成一棵樹, 每一個節點都成爲ZNode,每個ZNode默認能夠儲存1M的數據,每個ZNode都可以通過路徑作爲唯一的標識.

2. 本地模式

(1)事前準備:

  1. 下載,解壓ZooKeeper
    下載地址:https://archive.apache.org/dist/zookeeper/
sudo tar xzvf zookeeper-3.4.14/ -C /opt/softwares/
修改目錄及子目錄權限
sudo chown -R USER:GROUP /opt/softwares/zookeeper-3.4.14
# 習慣性的創建符號鏈接,可忽略,看個人
sudo ln -s zookeeper-3.4.14 zkeeper
  1. jdk的配置.
# 1. 解壓縮
sudo tar xzvf /opt/download/jdk-8u202-linux-x64.tar.gz -C /opt/softwares/
# 2. 創建符號鏈接
sudo ln -s jdk1.8.0_202/ jdk
# 3. 配置環境變量
vi ~/.bash_profile
####在文件中添加相應信息
export JAVA_HOME=/opt/softwares/jdk
PATH=......:$JAVA_HOME/bin:$JAVA_HOME/sbin
#### 重讀配置文件
source ~/.bash_profile
#### 驗證配置是否成功
java -version

在這裏插入圖片描述
(2)配置修改:

  1. 將zookeeper目錄conf/zoo_sample.cfg文件複製/修改爲zoo.cfg
cp conf/zoo_sample.cfg zoo.cfg
  1. 修改zoo.cfg中dataDir屬性
dataDir=/opt/softwares/zkeeper/zkData

(3)ZooKeeper操作:

  1. 啓動zkServer
bin/zkServer.sh start
  1. 查看進程是否啓動成功
    在這裏插入圖片描述
  2. 查看狀態:
bin/zkServer.sh status

在這裏插入圖片描述

  1. 啓動客戶端
bin/zkCli.sh
  1. 退出客戶端
quit

在這裏插入圖片描述

  1. 停止ZooKeeper
bin/zkServer.sh stop

3. 配置參數解讀

ZooKeeper中的配置文件zoo.cfg中參數含義解讀:

  1. tickTime=2000
    通信心跳時間,ZooKeeper服務器與客戶端的心跳時間,單位:毫秒.
  2. initLimit=10
    初始通信時限,集羣中的Follower服務器與Leader服務器之間初始連接時能容忍的最多心跳次數,這裏的設置是超過10次,即20秒,則判斷連接失敗.
  3. syncLimit=5
    同步通信時限,集羣中Leader與Follower之間的最大響應時限,加入超過syncLimit * tickTime,則Leader會判定Follower掛掉,會將Follower從服務器列表中刪除.
  4. dataDir
    數據文件路徑+數據持久化路徑.用於保存ZooKeeper的數據.
  5. clientPort = 2181
    客戶端連接端口.

4. 分佈式安裝部署

(1) 集羣規劃
這裏用的還是之前基於Docker搭建的Hadoop集羣,三個節點分別爲:
在這裏插入圖片描述

172.18.0.2 cluster-hdfs-master
172.18.0.3 cluster-hdfs-slave1
172.18.0.4 cluster-hdfs-slave2

(2)在cluster-hdfs-master容器中進行配置

  1. 解壓安裝ZooKeeper
sudo tar xzvf zookeeper-3.4.14.tar.gz -C /opt/softwares/
# 爲了避免權限問題修改owner:group
sudo chown -R hadoop:hadoop /opt/softwares/zookeeper-3.4.14
  1. 進入ZooKeeper的目錄,在目錄中創建目錄,用於存放數據.
cd /opt/softwares/zookeeper-3.4.14 && mkdir zkData
  1. 在zkData目錄中創建名爲myid的文件
touch myid
  1. 在myid中添加與server對應的編號
    注:編號爲數字
    這裏我們按照下面的對應進行填寫,由於是在cluster-hdfs-master容器中,所以這裏填寫1,稍後再去修改另外2個容器中的內容
cluster-hdfs-master 1
cluster-hdfs-slave1 2
cluster-hdfs-slave2 3
  1. 配置zoo.cfg文件
    ①在ZooKeeper的conf目錄下,將名爲zoo_sample.cfg的文件重命名或複製爲zoo.cfg
 cp zoo_sample.cfg zoo.cfg

②修改數據存儲路徑爲我們創建的zkData路徑

dataDir=/opt/softwares/zookeeper-3.4.14/zkData

③添加集羣服務信息

################cluster info####################
server.1=cluster-hdfs-master:2888:3888
server.2=cluster-hdfs-slave1:2888:3888
server.3=cluster-hdfs-slave2:2888:3888
  1. 將zookeeper-3.4.14目錄分發到集羣中其他節點
    ①準備一個分發腳本這裏起名爲container-sync
#!/bin/bash
#    Program:
#        use rsync to copy the file or folder to the nodes among the cluster
#    2020/01/20    Shuu    First release

cnt=$#
if [ $cnt -lt 1 ]; then
    echo "Usage:`basename $0` argument"
    exit 1
fi
filename=`basename $1`
# -P選項的作用是,如果目標爲符號鏈接,則追蹤到真實路徑
DIR=`cd $(dirname $1);pwd -P`

for line in `cat /home/hadoop/scripts/hosts.info`
do
    HOST=`echo $line | cut -f2`
    echo ==============$HOST===============
    # -r 遞歸
    # -u 文件存在的話如果有內容更新,則更新,否則不做操作
    # -l 文件爲符號鏈接,則按照符號鏈接進行拷貝
    rsync -ruvl $DIR/$filename $HOST:$DIR
done

爲了方便操作我們將container-sync移動到/usr/bin/目錄中.

# 給user賦予執行權限
sudo chmod u+x container-sync
# 移動到/usr/bin目錄
sudo mv container-sync /usr/bin/

②分發ZooKeeper目錄
/opt/softwares/目錄需要進行相應的權限設置,比如sudo chmod 777 /opt/softwares

container-sync /opt/softwares/zookeeper-3.4.14
  1. 分別修改另外2個容器中myid文件中的內容
sudo docker exec slave1 /bin/bash -c "su - hadoop -c 'echo 2 > /opt/softwares/zookeeper-3.4.14/zkData/myid'"
sudo docker exec slave2 /bin/bash -c "su - hadoop -c 'echo 2 > /opt/softwares/zookeeper-3.4.14/zkData/myid'"

(3)配置解讀
server.A=B:C:D
A:
是一個數字,表示這是第幾號服務器;
集羣模式下,在conf下的zoo.cfg文件中所配置的dataDir目錄下,需要配置一個名爲myid的文件,文件中存放着當前節點的號碼,ZooKeeper啓動時,會讀取此文件,然後與zoo.cfg文件中集羣信息進行比對,即A,從而判斷當前爲哪個Server.
B:
服務器地址
C:
集羣中Follower與Leader通信端口
D:
ZooKeeper集羣選舉時使用的端口
(4)啓動集羣
分別在集羣中的每個節點啓動ZooKeeper服務端.(這裏只是演示,後期建議寫成自啓腳本)

# 在ZooKeeper目錄下
bin/zkServer.sh start

在這裏插入圖片描述

# 查看ZooKeeper Server狀態
bin/zkServer.sh status

在這裏插入圖片描述

5. 客戶端常見命令

  1. 啓動客戶端
bin/zkCli.sh
命令 描述
help 顯示左右操作命令
ls path [watch] 使用ls命令來查看當前znode中所包含的內容
ls2 path [path] 查看path節點數據,並能查看到更豐富的內容信息
create 創建znode
-s Sequence Znode序列節點
-e Ephemeral Znode 臨時節點,重啓後消失
get path [watch] 獲得path節點的數據
set 設置節點的值
stat 查看節點狀態
delte 刪除節點
rmr 遞歸刪除節點

6. IDE操作ZooKeeper

這裏使Idea爲例演示.
pom.xml中添加相應的信息

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.8.2</version>
    </dependency>    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.4.14</version>
    </dependency>
</dependencies>

添加客戶端連接方法,並進行節點的創建,查詢子節點,刪除節點的操作.
雲服務器玩家需要在安全組,開放相應的端口

package conn;

import org.apache.zookeeper.*;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.List;

public class ZkpCli {
    // 用的docker搭的,所以端口分別被我映射爲不同的端口
    // 如果用的是多臺主機/虛擬機,則可以使用2181端口
    private static final String HOSTS = "master:2181,slave1:2182,slave2:2183";
    private static final int TIMEOUT = 2000;
    private ZooKeeper zkClient = null;
    @Before
    public void conn() throws IOException {
        zkClient = new ZooKeeper(HOSTS, TIMEOUT, new Watcher() {
            public void process(WatchedEvent e) {
                System.out.println(e.getState().toString());
            }
        });
    }

    @Test
    public void create() throws KeeperException, InterruptedException {
        for (int i = 0; i < 3; i++) {
            String str = zkClient.create("/testCli" + i, "Test API".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            System.out.println(str);
        }
    }

    @Test
    public void getChildren() throws KeeperException, InterruptedException {
        List<String> list = zkClient.getChildren("/", false);
        for (String s : list) {
            System.out.println(s);
        }
    }

    @Test
    public void deleteNode() throws KeeperException, InterruptedException {
        for (int i = 0; i < 3; i++) {
            zkClient.delete("/testCli" + i, 0);
        }
    }
}
發佈了73 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章