1. 程式人生 > 實用技巧 >Spark專案實戰從0到1之(20)企業級資料倉庫構建(三):資料採集模組環境搭建(1)

Spark專案實戰從0到1之(20)企業級資料倉庫構建(三):資料採集模組環境搭建(1)

一、資料採集模組

Linux基本配置

【1】Linux環境搭建

1).修改MAC地址
方法1:vim /etc/udev/rules.d/70-persistent-net.rules
刪除eth0,將eth1修改為eth0
方法2:rm -rf /etc/udev/rules.d/70-persistent-net.rules

2).修改IP
vim /etc/sysconfig/network-scripts/ifcfg-eth0
修改以下程式碼:
ONBOOT=yes
BOOTPROTO=static
新增以下程式碼:
IPADDR=192.168.100.100
NETMASK=255.255.255.0
GATEWAY=192.168
.100.2 DNS1=8.8.8.8 3).修改主機名 vim /etc/sysconfig/network 4).配置hosts vim /etc/hosts 192.168.100.100 node01 (根據自己需求配置對映關係) 5).關閉防火牆(CentOS7以下版本) 暫時關閉:service iptables stop 永久關閉:chkconfig iptables off 6).關閉selinux vim /etc/selinux/config 將SELINUX設定為disabled 7).新增使用者 useradd zsy passwd zsy vim /etc/sudoers +92 zsy ALL
=(ALL) NOPASSWD: ALL su - zsy 8).SSH免金鑰 ssh-keygen 然後敲四下回車 ssh-copy-id localhost

【2】Hadoop環境搭建



1)基礎環境建立

[node01]
cd ~
mkdir bin
cd bin
vim xsync
=======================指令碼如下========================
#!/bin/bash
#1 獲取輸入引數個數,如果沒有引數,直接退出
pcount=$#
if((pcount==0)); then
echo no args;
exit;
fi

#2 獲取檔名稱
p1
=$1 fname=`basename $p1` echo fname=$fname #3 獲取上級目錄到絕對路徑 pdir=`cd -P $(dirname $p1); pwd` echo pdir=$pdir #4 獲取當前使用者名稱稱 user=`whoami` #5 迴圈 for((host=101; host<104; host++)); do echo ------------------- hadoop$host -------------- rsync -rvl $pdir/$fname $user@hadoop$host:$pdir done =======================指令碼如上======================== chmod 770 xsync sudo rm -rf /opt/* sudo mkdir /opt/modules sudo mkdir /opt/software sudo mkdir -p /opt/tmp/logs sudo chown zsy:zsy -R /opt xsync /opt/* [node02/node03] sudo chown zsy:zsy -R /opt

2)JDK安裝

注意: 安裝之前,請先刪除系統自帶的JDK

[node01]
tar -zxf /opt/software/jdk-8u144-linux-x64.tar.gz -C /opt/modules
sudo vim /etc/profile.d/java.sh
export JAVA_HOME=/opt/modules/jdk1.8.0_144
export PATH=$PATH:$JAVA_HOME/bin
source /etc/profile
xsync /opt/modules/jdk1.8.0_144
sudo scp /etc/profile.d/java.sh node02:/etc/profile
sudo scp /etc/profile.d/java.sh node03:/etc/profile
[node02/node03]
source /etc/profile

注意:可以看到,我在上面新增的JDK環境變數是在/etc/profile.d目錄下建立了一個以.sh結尾的檔案,那麼為什麼可以這麼做呢?

我們首先說一下環境變數的配置方式有哪些

1)修改/etc/profile檔案:用來設定系統環境引數,比如$PATH,這裡面的環境變數是對系統內所有使用者生效。使用bash命令,需要source /etc/profile一下

2)修改~/.bashrc檔案:針對某一個特定的使用者,環境變數的設定只對該使用者自己有效,使用bash命令,只要以該使用者身份執行命令列就會讀取該檔案,該檔案會去載入/etc/bashrc檔案,該檔案會遍歷/etc/profile.d檔案下的以.sh檔案結尾的檔案,將其中的環境變數新增到/etc/bashrc檔案中,所以我們把配置的環境變數新增到/etc/profile.d目錄下

3)說明:
登入式Shell:採用使用者名稱登入,會自動載入/etc/profile
非登入式Sehll:採用ssh登入,不會自動載入/etc/profile,會自動載入~/.backrc

3)Zookeeper安裝

一、ZooKeeper概述

【1】Zookeeper簡介

  • (1)Zookeeper是一個分散式協調服務的開源框架,主要用來解決分散式叢集中應用系統的一致性問題
  • (2)ZooKeeper本質上是一個分散式的小檔案儲存系統。提供基於類似於檔案系統的目錄樹方式的資料儲存,並且可以對樹中的節點進行有效管理。從而用來維護和監控你儲存的資料的狀態變化。通過監控這些資料狀態的變化,從而可以達到基於資料的叢集管理
  • (3)Zookeeper從設計模式角度來理解:是一個基於觀察者模式設計的分散式服務管理框架,它負責儲存和管理大家都關心的資料,然後接受觀察者的註冊,一旦這些資料的狀態發生變化,Zookeeper就將負責通知已經在Zookeeper上註冊的那些觀察者做出相應的反應,從而實現叢集中類似Master/Slave管理模式
  • (4)Zookeeper = 檔案系統 + 通知機制

【2】Zookeeper特性

  • (1)全域性資料一致:叢集中每個伺服器儲存一份相同的資料副本,client無論連線到哪個伺服器,展示的資料都是一致的,這是最重要的特徵
  • (2)可靠性:如果訊息被其中一臺伺服器接受,那麼將被所有的伺服器接受
  • (3)順序性:包括全域性有序和偏序兩種:全域性有序是指如果在一臺伺服器上訊息a在訊息b前釋出,則在所有Server上訊息a都將在訊息b前被髮布;偏序是指如果一個訊息b在訊息a後被同一個傳送者釋出,a必將排在b前面
  • (4)資料更新原子性:一次資料更新要麼成功(半數以上節點成功),要麼失敗,不存在中間狀態
  • (5)實時性:Zookeeper保證客戶端將在一個時間間隔範圍內獲得伺服器的更新資訊,或者伺服器失效的資訊

【3】Zookeeper叢集角色

Leader:

1.Zookeeper叢集工作的核心
2.事務請求(寫操作)的唯一排程和處理者,保證叢集事務處理的順序性
3.叢集內部各個伺服器的排程者
4.對於create,setData,delete等有寫操作的請求,則需要統一轉發給leader處理,
leader需要決定編號、執行操作,這個過程稱為一個事務

Follower:

1.處理客戶端非事務(讀操作)請求,轉發事務請求給Leader
2.參與叢集Leader選舉投票
3.此外,針對訪問量比較大的zookeeper叢集,還可新增觀察者角色

Observer:

1.觀察者角色,觀察Zookeeper叢集的最新狀態變化並將這些狀態同步過來,其對於非事務請求可以進行獨立處理,
對於事務請求,則會轉發給Leader伺服器進行處理
2.不會參與任何形式的投票只提供非事務服務,通常用於在不影響叢集事務處理能力的前提下提升叢集的非事務處理能力

二、ZooKeeper安裝

安裝zookeeper的注意事項:
    安裝前需要安裝好jdk
    檢測叢集時間是否同步
    檢測防火牆是否關閉
    檢測主機 ip對映有沒有配置
    
##下載安裝包、解壓
下載地址:
CDH版本:http://archive.cloudera.com/cdh5/cdh/5/zookeeper-3.4.5-cdh5.14.0.tar.gz
apache版本:https://archive.apache.org/dist/zookeeper/

【1】解壓tar包

tar -zxf zookeeper-3.4.5-cdh5.14.0.tar.gz ../servers/

【2】配置環境變數

vim /etc/profile.d/zookeeper.sh

export ZOOKEEPER_HOME=/export/servers/zookeeper
export PATH=$PATH:$ZOOKEEPER_HOME/bin

source /etc/profile

【3】修改配置檔案

cd $ZOOKEEPER_HOME/conf
mv zoo_sample.cfg  zoo.cfg
vim zoo.cfg

【4】新增myid

建立在 zoo.cfg 中指定的 dataDir 目錄
mkdir /export/servers/zookeeper/zkdata

進入到目錄
cd /export/servers/zookeeper/zkdata

給當前節點新增 myid
echo 1 > myid

【5】分發zookeeper

scp -r zookeeper node02:`pwd`

分發完後根據需求修改 myid 檔案中的值大小

【6】啟動zookeeper

每臺節點使用命令 zkServer.sh start 進行啟動
然後使用命令 zkServer.sh status 進行檢視狀態




zoo.cfg檔案中的 配置引數解讀

    • 1)tickTime:通訊心跳數,Zookeeper伺服器心跳時間,單位毫秒
      Zookeeper使用的基本時間,伺服器之間或客戶端與伺服器之間維持心跳的時間間隔,也就是每個tickTime時間就會發送一個心跳,時間單位為毫秒
      它用於心跳機制,並且設定最小的session超時時間為兩倍心跳時間
      (session的最小超時時間是2 * tickTime)
    • 2)initLimit:LF初始通訊時限
      叢集中的follower跟隨者伺服器(F)與leader領導者伺服器(L)之間初始連線時能容忍的最多心跳數(tickTime的數量),用它來限定叢集中的Zookeeper伺服器連線到Leader的時限
      投票選舉新leader的初始化時間
      Follower在啟動過程中,會從Leader同步所有最新資料,然後確定自己能夠對外服務的起始狀態
      Leader允許F在initLimit時間內完成這個工作
    • 3)syncLimit:LF同步通訊時限
      叢集中Leader與Follower之間的最大響應時間單位,假如響應超過syncLimit * tickTime,
      Leader認為Follwer死掉,從伺服器列表中刪除Follwer
      在執行過程中,Leader負責與ZK叢集中所有機器進行通訊,例如通過一些心跳檢測機制,來檢測機器的存活狀態
      如果L發出心跳包在syncLimit之後,還沒有從F那收到響應,那麼就認為這個F已經不線上了
    • 4)dataDir:資料檔案目錄+資料持久化路徑
      儲存記憶體資料庫快照資訊的位置,如果沒有其他說明,更新的事務日誌也儲存到資料庫
    • 5)clientPort:客戶端連線埠,監聽客戶端連線的埠

三、ZooKeeper Shell

【1】客戶端連線

執行 zkCli.sh 或 zkCli.sh –server ip   進入命令列工具
輸入help,輸出zk shell提示:

【2】shell基本操作

(1)建立節點
語法:create [-s] [-e] path data acl

其中,-s 指定為序列化節點 、 -e 指定為臨時節點 ; 若不指定,則表示永久非序列化節點,acl用來進行許可權控制

(2)讀取節點
與讀取相關的命令有 ls 命令 和 get 命令
1.ls 命令可以列出Zookeeper指定節點下的所有子節點,只能檢視指定節點下的第一級的所有子節點
2.get 命令可以獲取Zookeeper指定節點的資料內容和屬性資訊

語法:
ls path [watch]
get path [watch]
ls2 path [watch]

(3)更新節點
語法:set path data [version]
    data就是要更新的新內容,version表示資料版本


現在dataVersion已經變為2了,表示進行了2次更新

(4)刪除節點
語法:delete path [version]
    若刪除節點存在子節點,那麼無法刪除該節點,必須先刪除子節點,再刪除父節點
語法:Rmr path
    遞迴刪除節點


(5)其他節點相關命令
語法:setquota -n|-b val path  
    對節點增加限制
        n:表示子節點的最大個數
        b:表示資料值的最大長度
        val:子節點最大個數或資料值的最大長度
        path:節點路徑

語法:listquota path  
    列出指定節點的quota

語法:delquota [-n|-b] path  
    刪除quota

語法:history  
    列出命令歷史

語法:redo 編號
該命令可以重新執行指定命令編號的歷史命令,命令編號可以通過history檢視

四、ZooKeeper 資料模型

ZooKeeper的資料模型,在結構上和標準檔案系統的非常相似,擁有一個層次的名稱空間,都是採用樹形層次結構,ZooKeeper樹中的每個節點被稱為Znode。和檔案系統的目錄樹一樣,ZooKeeper樹中的每個節點可以擁有子節點。但也有不同之處:

  • (1)Znode兼具檔案和目錄兩種特點。既像檔案一樣維護著資料、元資訊、ACL、時間戳等資料結構,又像目錄一樣可以作為路徑標識的一部分,並可以具有子Znode。使用者對Znode具有增、刪、改、查等操作(許可權允許的情況下)
  • (2)Znode具有原子性操作,讀操作將獲取與節點相關的所有資料,寫操作也將替換掉節點的所有資料。另外,每一個節點都擁有自己的ACL(訪問控制列表),這個列表規定了使用者的許可權,即限定了特定使用者對目標節點可以執行的操作
  • (3)Znode儲存資料大小有限制。ZooKeeper雖然可以關聯一些資料,但並沒有被設計為常規的資料庫或者大資料儲存,相反的是,它用來管理排程資料,比如分散式應用中的配置檔案資訊、狀態資訊、彙集位置等等。這些資料的共同特性就是它們都是很小的資料,通常以KB為大小單位。ZooKeeper的伺服器和客戶端都被設計為嚴格檢查並限制每個Znode的資料大小至多1M,當時常規使用中應該遠小於此值
  • (4)Znode通過路徑引用,如同Unix中的檔案路徑。路徑必須是絕對的,因此他們必須由斜槓字元來開頭。除此以外,他們必須是唯一的,也就是說每一個路徑只有一個表示,因此這些路徑不能改變。在ZooKeeper中,路徑由Unicode字串組成,並且有一些限制。字串"/zookeeper"用以儲存管理資訊,比如關鍵配額資訊

【4.1】 資料結構圖

  • 圖中的每個節點稱為一個Znode。 每個Znode由3部分組成:
    • ① stat:此為狀態資訊, 描述該Znode的版本, 許可權等資訊
    • ② data:與該Znode關聯的資料
    • ③ children:該Znode下的子節點

【4.2】 節點型別

  • Znode有兩種,分別為臨時節點永久節點
  • 節點的型別建立時即被確定,並且不能改變
  • 臨時節點:該節點的生命週期依賴於建立它們的會話,一旦會話結束臨時節點將被自動刪除,當然可以也可以手動刪除;臨時節點不允許擁有子節點
  • 永久節點:該節點的生命週期不依賴於會話,並且只有在客戶端顯示執行刪除操作的時候,他們才能被刪除
  • Znode還有一個序列化的特性,如果建立的時候指定的話,該Znode的名字後面會自動追加一個不斷增加的序列號。序列號對於此節點的父節點來說是唯一的,這樣便會記錄每個子節點建立的先後順序。它的格式為“%10d”(10位數字,沒有數值的數位用0補充,例如“0000000001”)
  • 這樣便會存在四種類型的Znode節點,分別對應:
    • PERSISTENT:永久節點
    • EPHEMERAL:臨時節點
    • PERSISTENT_SEQUENTIAL:永久節點、序列化
    • EPHEMERAL_SEQUENTIAL:臨時節點、序列化

【4.3】 節點屬性

每個znode都包含了一系列的屬性,通過命令get,可以獲得節點的屬性

  • dataVersion:資料版本號,每次對節點進行set操作,dataVersion的值都會增加1(即使設定的是相同的資料),可有效避免了資料更新時出現的先後順序問題
  • cversion:子節點的版本號。當znode的子節點有變化時,cversion 的值就會增加1
  • cZxid:Znode建立的事務id
  • mZxid:Znode被修改的事務id,即每次對znode的修改都會更新mZxid
  • 對於zk來說,每次的變化都會產生一個唯一的事務idzxid(ZooKeeper Transaction Id)。通過zxid,可以確定更新操作的先後順序。例如,如果zxid1小於zxid2,說明zxid1操作先於zxid2發生,zxid對於整個zk都是唯一的,即使操作的是不同的znode
  • ctime:節點建立時的時間戳
  • mtime:節點最新一次更新發生時的時間戳
  • ephemeralOwner:如果該節點為臨時節點, ephemeralOwner值表示與該節點繫結的session id. 如果不是, ephemeralOwner值為0
  • 在client和server通訊之前,首先需要建立連線,該連線稱為session。連線建立後,如果發生連線超時、授權失敗,或者顯式關閉連線,連線便處於CLOSED狀態, 此時session結束

五、ZooKeeper Watcher(監聽機制)

簡介
  • ZooKeeper提供了分散式資料釋出/訂閱功能,一個典型的釋出/訂閱模型系統定義了一種一對多的訂閱關係,能讓多個訂閱者同時監聽某一個主題物件,當這個主題物件自身狀態變化時,會通知所有訂閱者,使他們能夠做出相應的處理
  • ZooKeeper中,引入了Watcher機制來實現這種分散式的通知功能。ZooKeeper允許客戶端向服務端註冊一個Watcher監聽,當服務端的一些事件觸發了這個Watcher,那麼就會向指定客戶端傳送一個事件通知來實現分散式的通知功能
  • 觸發事件種類很多,如:節點建立節點刪除節點改變子節點改變
    總的來說可以概括Watcher為以下三個過程客戶端向服務端註冊Watcher服務端事件發生觸發Watcher客戶端回撥Watcher得到觸發事件情況

【5.1】 Watch機制特點

一次性觸發

事件發生觸發監聽,一個watcher event就會被髮送到設定監聽的客戶端,這種效果是一次性的,後續再次發生同樣的事件,不會再次觸發

事件封裝

ZooKeeper使用WatchedEvent物件來封裝服務端事件並傳遞
WatchedEvent包含了每一個事件的三個基本屬性
通知狀態(keeperState)事件型別(EventType)節點路徑(path)

event非同步傳送

watcher的通知事件從服務端傳送到客戶端是非同步的

先註冊再觸發

Zookeeper中的watch機制,必須客戶端先去服務端註冊監聽,這樣事件傳送才會觸發監聽,通知給客戶端

【5.2】 通知狀態和事件型別

同一個事件型別在不同的通知狀態中代表的含義有所不同,下表列舉了常見的通知狀態和事件型別

其中連線狀態事件(type=None, path=null)不需要客戶端註冊,客戶端只要有需要直接處理就行了

【5.3】 Shell 客戶端設定watcher

設定節點資料變動監聽:

通過另一個客戶端更改節點資料:

此時設定監聽的節點收到通知:

六、ZooKeeper Java API

簡介
org.apache.zookeeper.Zookeeper
Zookeeper 是在Java中客戶端主類,負責建立與zookeeper叢集的會話,並提供方法進行操作
org.apache.zookeeper.Watcher
Watcher介面表示一個標準的事件處理器,其定義了事件通知相關的邏輯,包含KeeperState和EventType兩個列舉類,
分別代表了通知狀態和事件型別,同時定義了事件的回撥方法:process(WatchedEvent event)
process方法是Watcher介面中的一個回撥方法,當ZooKeeper向客戶端傳送一個Watcher事件通知時,
客戶端就會對相應的process方法進行回撥,從而實現對事件的處理
基本使用

建立Java maven專案,引入maven pom座標

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.9</version>
</dependency>

示例1

public static void main(String[] args) throws Exception {
        // 初始化 ZooKeeper例項(zk地址、會話超時時間,與系統預設一致、watcher)
        ZooKeeper zk = new ZooKeeper("node01:2181,node02:2181", 30000, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                System.out.println("事件型別為:" + event.getType());
                System.out.println("事件發生的路徑:" + event.getPath());
                System.out.println("通知狀態為:" +event.getState());
            }
        });
    zk.create("/tmp", "HelloWorld".getBytes("UTF-8"), Ids.OPEN_ACL_UNSAFE,
         CreateMode.PERSISTENT);
    zk.close();
}

示例2

public static void main(String[] args) throws Exception {
        // 初始化 ZooKeeper例項(zk地址、會話超時時間,與系統預設一致、watcher)
        ZooKeeper zk = new ZooKeeper("node01:2181,node02:2181", 30000, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                System.out.println("事件型別為:" + event.getType());
                System.out.println("事件發生的路徑:" + event.getPath());
                System.out.println("通知狀態為:" +event.getState());
            }
        });
 // 建立一個目錄節點
 zk.create("/testRootPath", "testRootData".getBytes(), Ids.OPEN_ACL_UNSAFE,
   CreateMode.PERSISTENT); 
 // 建立一個子目錄節點
 zk.create("/testRootPath/testChildPathOne", "testChildDataOne".getBytes(),
   Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT); 
 System.out.println(new String(zk.getData("/testRootPath",false,null))); 
 // 取出子目錄節點列表
 System.out.println(zk.getChildren("/testRootPath",true)); 
 // 修改子目錄節點資料
 zk.setData("/testRootPath/testChildPathOne","modifyChildDataOne".getBytes(),-1); 
 System.out.println("目錄節點狀態:["+zk.exists("/testRootPath",true)+"]"); 
 // 建立另外一個子目錄節點
 zk.create("/testRootPath/testChildPathTwo", "testChildDataTwo".getBytes(), 
   Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT); 
 System.out.println(new String(zk.getData("/testRootPath/testChildPathTwo",true,null))); 
 // 刪除子目錄節點
 zk.delete("/testRootPath/testChildPathTwo",-1); 
 zk.delete("/testRootPath/testChildPathOne",-1); 
 // 刪除父目錄節點
 zk.delete("/testRootPath",-1);
 zk.close();
}

七、ZooKeeper選舉機制

預設演算法:

Zookeeper預設的演算法是FastLeaderElection,採用投票數大於半數則勝出的邏輯

概念
  • 伺服器ID
    比如有五臺伺服器,編號分別是1,2,3,4,5
    編號越大在選擇演算法中的權重越大
  • 選舉狀態
    LOOKING,競選狀態
    FOLLOWING,隨從狀態,同步leader狀態,參與投票
    OBSERVING,觀察狀態,同步leader狀態,不參與投票
    LEADING,領導者狀態
  • 資料ID
    伺服器中存放的最新資料version
    值越大說明資料越新,在選舉演算法中資料越新權重越大
  • 邏輯時鐘
    也叫投票的次數,同一輪投票過程中的邏輯時鐘值是相同的。每投完一次票這個資料就會增加,然後與接收到的其它伺服器返回的投票資訊中的數值相比,根據不同的值做出不同的判斷
全新叢集選舉

假設目前有5臺伺服器,每臺伺服器均沒有資料,它們的編號分別是1,2,3,4,5,按編號依次啟動,它們的選擇舉過程如下:

  • 伺服器1啟動,給自己投票,然後發投票資訊,由於其它機器還沒有啟動所以它收不到反饋資訊,伺服器1的狀態一直屬於Looking
  • 伺服器2啟動,給自己投票,同時與之前啟動的伺服器1交換結果,由於伺服器2的編號大所以伺服器2勝出,但此時投票數沒有大於半數,所以兩個伺服器的狀態依然是LOOKING
  • 伺服器3啟動,給自己投票,同時與之前啟動的伺服器1,2交換資訊,由於伺服器3的編號最大所以伺服器3勝出,此時投票數正好大於半數,所以伺服器3成為領導者,伺服器1,2成為小弟
  • 伺服器4啟動,給自己投票,同時與之前啟動的伺服器1,2,3交換資訊,儘管伺服器4的編號大,但之前伺服器3已經勝出,所以伺服器4只能成為小弟
  • 伺服器5啟動,後面的邏輯同伺服器4成為小弟
非全新叢集選舉

對於執行正常的zookeeper叢集,中途有機器down掉,需要重新選舉時,選舉過程就需要加入資料ID、伺服器ID和邏輯時鐘

    • 資料ID:資料新的version就大,資料每次更新都會更新version
    • 伺服器ID:就是我們配置的myid中的值,每個機器一個
    • 邏輯時鐘:這個值從0開始遞增,每次選舉對應一個值。 如果在同一次選舉中,這個值是一致的
    • 這樣選舉的標準就變成:
      1、邏輯時鐘小的選舉結果被忽略,重新投票
      2、統一邏輯時鐘後,資料id大的勝出
      3、資料id相同的情況下,伺服器id大的勝出
      根據這個規則選出leader

4)Hadoop安裝

【開篇】HA概述與實現

HDFS 是一個分散式檔案系統,有namenode和datanode,我們都知道,
一旦namenode蕩機,整個叢集就會癱瘓,那麼這個問題怎麼處理?

一般我們都會有兩個namenode,我們知道有一個secondary namenode,但是我們知道這個namenode並不能執行namenode的功能,他只是幫namenode做操作日誌的合併,所以我們需要另一種部署模式,即HA部署模式

HA部署模式,是一種高可用部署模式,也就是一天24小時都在工作,他有兩個namenode。namenode記錄的是元資料,這個元資料放在記憶體中, 在磁碟上有一個映象檔案,這個映象檔案是fsimage+編號,還有大量的操作日誌叫做edits+編號,兩個編號都是對應起來的,而且記憶體裡面的元資料都是齊全的,兩個namenode只有一個是對客戶端服務的,另外一個用來備份,對外服務的狀態成為active,備份的是standby,如果有一天active namenode蕩機了,standby要接管對外服務,但是它還沒有元資料,那麼這個問題怎麼解決的。

如果active namenode蕩機,standby要立馬接管,意味著這兩個的元資料必須要時刻同步,如果是standby namenode經常性的去active拷貝元資料資訊,那麼這樣對active namenode的壓力是很大的,所以首先,一開始格式化的時候,生成一個最初的元資料,先給standby拷貝一份,在執行的過程中,日誌不僅在自己的磁碟上,還放在一個 日誌儲存 系統中,standby定期的去從日誌儲存系統中拿取日誌檔案,並且和最初的元資料fsimage進行合併,生成一個新的映象,如果差下那麼一點日誌沒有合併到,就在這一瞬間,active namenode蕩機了,然後standby namenode會從日誌儲存系統拿取缺少的那一塊日誌,與原來的元資料進行合併,進行更新,這樣狀態就和active namenode的狀態是一致的,這樣就可以很快的接手對外服務。

日誌儲存系統:
這是個很重要的,這個系統是不能掛掉的,這個系統不是一個單節點,這個系統也是一個叢集,裡面有很多臺機器,這個叢集也是基數臺,而且每臺之間會同步日誌,這樣一來,日誌儲存系統的可用性就會很高了,資料同步的演算法和zookeeper是一樣的,即資料在多個節點之間同步,採用的是paxos演算法,多數成立則成立,所以這個日誌儲存系統最多可以掛掉半數以下的機器,這個系統叫做QJournal,底層的功能依賴zookeeper叢集,這兩個叢集在業務上沒關係,只是利用zookeeper,就像hbase依賴zookeeper一樣。

但是現在有一個問題,就是active namenode這臺機器掛掉之後,standby namenode這臺機器是怎麼知道的,active namenode 可以在zookeeper上記載東西,然後standby去監聽,一旦這個active namenode不見了,那麼就說明掛了,這是一種方法。

官方是這麼做的,提供了一個額外的程式,叫做zkfc,就是基於zookeeper實現的failover controller,故障控制器,執行在namenode機器上監控namenode的程序並且把監控資訊記錄在zookeeper中,standby 機器也會執行zkfc,監控自己機器上的程序,也會監聽zookeeper裡面的另一個zkfc寫的東西,一旦發生變化,得到zookeeper的通知,就可以呼叫方法,將自己的狀態從standby切換成active狀態,然後開始對外服務,但是問題沒有那麼簡單,有時候JVM會凍結這個namenode,zkfc以為namenode掛掉了,其實只是清理以及維護,但是這樣的話,zkfc將將狀態提交給zookeeper,然後standby namenode會收到zookeeper的通知,那就切換狀態了,這就完了,就將存在兩個active namenode,這樣系統會錯亂。

這裡還有一個機制,就是當standby namenode收到通知切換狀態的時候,先不著急切換,而是先採取措施確保防止這種系統的紊亂,首先會做兩件事。

1.通過SSH遠端指令,殺掉active namenode 的程序,但是如果不僅僅是namenode掛了,而是整個機器掛了,那傳送的指令
就不會有反應,也不會有反饋資訊,

2.那麼如果SSH沒有響應,則幫使用者呼叫一個使用者所指定的指令碼,指令碼執行成功,則切換狀態
做完這兩件事,狀態就切換成功了,這就是HA高可用叢集執行機制。


一、準備工作

1.在四臺節點上安裝JDK以及Hadoop
2.在node02、node03、node04節點上安裝Zookeeper
3.節點配置分佈如下