1. 程式人生 > >ZooKeeper配置和學習筆記

ZooKeeper配置和學習筆記

ZooKeeper介紹

  1. Zookeeper 分散式服務框架是 Apache Hadoop 的一個子專案,它主要是用來解決分散式應用中經常遇到的一些資料管理問題,如:統一命名服務、狀態同步服務、叢集管理、分散式應用配置項的管理等。本文將從使用者角度詳細介紹 Zookeeper 的安裝和配置檔案中各個配置項的意義,以及分析 Zookeeper 的典型的應用場景(配置檔案的管理、叢集管理、同步鎖、Leader 選舉、佇列管理等)。
  2. 簡單說下我的理解:

    • ZooKeeper有三種工作模式:

    • Standalone:單點模式,有單點故障問題。
    • 偽分散式
      :在一臺機器同時執行多個ZooKeeper例項,仍然有單點故障問題,當然,其中配置的埠號要錯開的,適合實驗環境模擬叢集使用。
    • 完全分散式:在多臺機器上部署ZooKeeper叢集,適合線上環境使用。
    • ZooKeeper到底是什麼:
    • 三種埠號:這裡先說明三個ZooKeeper配置需要的埠號,因為後面的解釋中會經常引用,就拉到前面講啦
    • 埠X:客戶端連線ZooKeeper叢集使用的監聽埠號
    • 埠Y:leader和follower之間資料同步使用的埠號
    • 埠Z:leader選舉專用的埠號
    • 單點分析
      :在每個ZooKeeper節點當中,ZooKeeper維護了一個類似linux的樹狀檔案系統結構,可以把一些配置資訊,資料等存放到ZooKeeper當中,也可以把ZooKeeper當中的一個目錄節點當做一個鎖的互斥檔案來實現併發安全控制,你看到這就先把ZooKeeper理解為一個在作業系統上執行的一個虛擬檔案系統,只不過他不是像HDFS那樣真的用來存放檔案的,他是利用檔案系統的節點作為底層實現來提供分散式環境很常用的功能,這在後面的實戰使用會具體講解.
    • 叢集分析:ZooKeeper中的每個節點都是上面的單點分析那樣工作的,但是叢集多節點之間到底如何進行協商和通訊呢?
    • 首先,類似mysql讀寫分離那樣,ZooKeeper的每個節點都存放相同的資料,因此訪問ZooKeeper的時候會被分流道各個節點實現高併發,多節點也順便實現了高可用。
    • ZooKeeper的節點之間也有主次關係,叢集啟動完成之後,ZooKeeper會執行選舉程式(埠Z)從叢集中選擇一個leader節點,而其他的節點就是follower節點,對於ZooKeeper的寫操作,會被轉發到leader節點,而follower節點和leader節點的資料同步(埠Y)也在後臺自動實現,讀操作則每個節點都能提供,負載均衡~
    • 容災機制:follower節點掛了比較不要緊,有leader協調,整個叢集還不至於發生致命影響。但是leader節點要是掛了,就群龍無首了,但是其實這個狀態和ZooKeeper叢集啟動前期還沒確定leader節點的時候是一樣的狀態,下面講解這個狀態如何進行leader的 選舉。
      由於每個節點配置檔案中都維護了整個ZooKeeper叢集的所有節點列表,因此在沒確定leader節點或者leader節點掛掉的時候,每個節點向leader的通訊必然是失敗的,follower節點就是這麼發現leader節點掛了的,這個時候他就能啟動選舉程式進行leader競選,和其他的所有follower節點進行通訊,根據某種演算法方案確定leader的節點之後,被選中的節點就啟動leader的程式,化身leader重新領導整個叢集。
    • 客戶端訪問高可用:
    • 讀操作:每個節點都能響應
    • 寫操作:不管向哪個節點請求都會轉發到leader節點執行,再把資料同步到各個follower節點。
    • 訪問follower節點宕機:客戶端會儲存一個地址列表,會自動使用另一個地址進行訪問,實在不行還有leader節點分配地址再次訪問呢,而且一旦客戶端和伺服器的連線被斷開,客戶端就會自動去連線另一個節點的地址進行請求。
    • 訪問leader節點宕機:也是使用這個地址列表,如果是讀操作,則leader選舉出來之前都能訪問,但是如果是寫操作,就要等leader選舉完成之後才能進行操作。
    • 我之前有疑問的地方就是以為客戶端只維護一個節點的地址,這樣的話導致了這個節點宕機之後客戶端就和ZooKeeper叢集斷開了且無法重新連線了,但是後來知道了客戶端是儲存了節點地址列表,那所有問題就很好理解啦。
    • 好了,說了很多廢話你可能有點暈了,但是總說一點,別忘了,現在先把他當成一個樹形檔案系統~

ZooKeeper環境部署和和簡單測試

  1. 安裝準備:
    • JDK
    • hosts
    • 防火牆
    • SELinux
    • ssh免密碼登入
    • 等等這些基本配置前面的Hadoop教程說過了,不再贅述,這些問題我相信都是很容易解決的。
    • 安裝步驟總結:

    (1) 建立快取目錄;
    (2) 配置zookeeper配置檔案zoo.cfg,設定快取目錄、監聽客戶端埠號、server列表配置等
    (3) bin目錄下的zkServer.sh啟動即可,還能檢視叢集中的leader、follower之間的關係

  2. 單機模式:

    • 建立快取目錄;
    • 解壓ZooKeeper安裝包,在conf目錄下的zoo_sample.cfg檔案複製一個副本zoo.cfg,在裡面進行ZooKeeper整體配置:
tickTime=2000
dataDir=/opt/zookeeper1
clientPort=2181

tickTime:這個時間是作為 Zookeeper 伺服器之間或客戶端與伺服器之間維持心跳的時間間隔,也就是每個 tickTime 時間就會發送一個心跳。
dataDir:顧名思義就是 Zookeeper 儲存資料的目錄,預設情況下,Zookeeper 將寫資料的日誌檔案也儲存在這個目錄裡。
clientPort:這個埠就是客戶端連線 Zookeeper 伺服器的埠,Zookeeper 會監聽這個埠,接受客戶端的訪問請求。
* bin目錄下的zkServer.sh執行即可啟動:

bin/zkServer.sh start
  • 可以檢視ZooKeeper的執行狀態:
bin/zkServer.sh status
  1. 叢集模式:
    • 建立快取目錄;
    • 解壓ZooKeeper安裝包,在conf目錄下的zoo_sample.cfg檔案複製一個副本zoo.cfg,在裡面進行ZooKeeper整體配置:

tickTime=2000
dataDir=/opt/zookeeper1
clientPort=2181
initLimit=5
syncLimit=2
server.1=192.168.211.1:2888:3888
server.2=192.168.211.2:2888:3888

上面前三個的配置和單機模式一樣,不多贅述了。
initLimit:這個配置項是用來配置 Zookeeper 接受客戶端(這裡所說的客戶端不是使用者連線 Zookeeper 伺服器的客戶端,而是 Zookeeper 伺服器叢集中連線到 Leader 的 Follower 伺服器)初始化連線時最長能忍受多少個心跳時間間隔數。當已經超過 10 個心跳的時間(也就是 tickTime)長度後 Zookeeper 伺服器還沒有收到客戶端的返回資訊,那麼表明這個客戶端連線失敗。總的時間長度就是 5*2000=10 秒
syncLimit:這個配置項標識 Leader 與 Follower 之間傳送訊息,請求和應答時間長度,最長不能超過多少個 tickTime 的時間長度,總的時間長度就是 2*2000=4 秒
server.A=B:C:D:其中 A 是一個數字,表示這個是第幾號伺服器;B 是這個伺服器的 ip 地址;C 表示的是這個伺服器與叢集中的 Leader 伺服器交換資訊的埠(上面的埠Y);D 表示的是萬一叢集中的 Leader 伺服器掛了,需要一個埠來重新進行選舉,選出一個新的 Leader,而這個埠就是用來執行選舉時伺服器相互通訊的埠(上面的埠Z)。如果是偽叢集的配置方式,由於 B 都是一樣,所以不同的 Zookeeper 例項通訊埠號不能一樣,所以要給它們分配不同的埠號。
* 在上面配置的dataDir目錄下建立myid檔案,填寫這個節點上的id號,就是server.A=B:C:D配置的A那個號碼
“`bash
[[email protected]_68_145_centos zookeeper]# cat /opt/zookeeper1/myid
1
[[email protected]_68_145_centos zookeeper]# cat /opt/zookeeper2/myid
2
[[email protected]_68_145_centos zookeeper]# cat /opt/zookeeper3/myid
3
[[email protected]_68_145_centos zookeeper]# cat /opt/zookeeper4/myid
4

>* 將配置好的整個安裝包複製到每個節點機器上,scp命令複製過去,我這裡是採用偽分散式,直接使用cp命令即可。
>* 到每個節點上zookeeper/bin目錄下的zkServer.sh執行即可啟動:
```bash
bin/zkServer.sh start




<div class="se-preview-section-delimiter"></div>

其他指令碼介紹:

zkServer.sh     : ZooKeeper伺服器的啟動、停止和重啟指令碼;
zkCli.sh        : ZooKeeper的簡易客戶端;
zkEnv.sh        : 設定ZooKeeper的環境變數;
zkCleanup.sh    : 清理ZooKeeper歷史資料,包括事務日誌檔案和快照資料檔案。




<div class="se-preview-section-delimiter"></div>
  • 可以檢視ZooKeeper的執行狀態:
zookeeper/bin/zkServer.sh status




<div class="se-preview-section-delimiter"></div>

  • 簡單說明這樣的配置ZooKeeper叢集是怎麼工作的:

  • 首先,每個節點上zoo.cfg配置檔案中都有整個叢集的列表,所以每個節點之間的通訊都是可行的。
  • 然後是dataDir目錄下的myid標記了這個機器上的這個節點是zoo.cfg上的叢集列表的哪個記錄,從這個就能知道當前的這個節點所處的位置,也能知道當前機器的節點是不是leader,以便於執行leader該執行的程式。
  • 關於配置的三個埠號:
  • 埠X:監聽客戶端連線的,沒什麼可說的
  • 埠Y:follower和leader進行資料同步通訊用的,這個是長連線隨時同步資料,健康情況下正常執行,leader宕機就無法正常執行,此時觸發選舉程式選擇新的leader。
  • 埠Z:選舉時各個follower節點之間兩兩可以相互通訊的,以便於成功選擇出leader。
  • 踩坑記錄:我剛開始以為埠X和埠Y是同一個,導致了我就設定了同一個埠號,所以顯然是無法啟動成功的,後來知道這兩個埠號完成的是不同的功能,所以改正完成就能啟動成功了。
  1. 可以建立一個啟動指令碼一次性啟動整個叢集,比如我搭建的偽分散式的啟動指令碼:




<div class="se-preview-section-delimiter"></div>

#! /bin/sh
/usr/java/zookeeper/zookeeper1/bin/zkServer.sh start
/usr/java/zookeeper/zookeeper2/bin/zkServer.sh start
/usr/java/zookeeper/zookeeper3/bin/zkServer.sh start
/usr/java/zookeeper/zookeeper4/bin/zkServer.sh start
/usr/java/zookeeper/zookeeper1/bin/zkServer.sh status
/usr/java/zookeeper/zookeeper2/bin/zkServer.sh status
/usr/java/zookeeper/zookeeper3/bin/zkServer.sh status
/usr/java/zookeeper/zookeeper4/bin/zkServer.sh status
echo 'you can use zookeeper client connect to 119.29.153.56 on follow ports:'
echo '2181'
echo '2182'
echo '2183'
echo '2184'




<div class="se-preview-section-delimiter"></div>

各個節點的啟動狀態:

[[email protected]_68_145_centos zookeeper]# /usr/java/zookeeper/zookeeper1/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/java/zookeeper/zookeeper1/bin/../conf/zoo.cfg
Mode: follower
[[email protected]_68_145_centos zookeeper]# /usr/java/zookeeper/zookeeper2/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/java/zookeeper/zookeeper2/bin/../conf/zoo.cfg
Mode: follower
[[email protected]_68_145_centos zookeeper]# /usr/java/zookeeper/zookeeper3/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/java/zookeeper/zookeeper3/bin/../conf/zoo.cfg
Mode: leader
[[email protected]_68_145_centos zookeeper]# /usr/java/zookeeper/zookeeper4/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/java/zookeeper/zookeeper4/bin/../conf/zoo.cfg
Mode: follower




<div class="se-preview-section-delimiter"></div>

啟動完成之後順便查看了每個節點充當的是leader還是follower,並把叢集的所有客戶端連線埠號輸出出來,從上面的執行結果可知,zookeeper3的這個例項是leader,其他例項是follower。


  1. ZooKeeper簡單操作測試:
  • 命令列方式操縱ZooKeeper:
    “`bash

  • 進入本地的ZooKeeper:

/usr/java/zookeeper/zookeeper1/bin/zkCli.sh

進入遠端的ZooKeeper:

/usr/java/zookeeper/zookeeper1/bin/zkCli.sh -server {ip}:{port}

> 這樣就進入了ZooKeeper的命令列客戶端,就能訪問指定的ZooKeeper叢集中的資料,支援以下的操作(在命令列下輸入錯誤命令就能看到提示了。。。):
>```bash
stat path [watch]
    set path data [version]
    ls path [watch]
    delquota [-n|-b] path
    ls2 path [watch]
    setAcl path acl
    setquota -n|-b val path
    history
    redo cmdno
    printwatches on|off
    delete path [version]
    sync path
    listquota path
    rmr path
    get path [watch]
    create [-s] [-e] path data acl
    addauth scheme auth
    quit
    getAcl path
    close
    connect host:port




<div class="se-preview-section-delimiter"></div>
  • 操作示例:
    “`bash

建立節點/testInput,節點中的數值為inputData

create /testInput “inputData”

查詢剛才插入的節點

get /testInput

執行結果

inputData
cZxid = 0x300000006
ctime = Sun Dec 18 21:47:21 CST 2016
mZxid = 0x300000006
mtime = Sun Dec 18 21:47:21 CST 2016
pZxid = 0x300000006
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 9
numChildren = 0

> 所以整個操縱的過程就和平時操作linux檔案的感覺差不多,下面的Java程式操縱其實也只是對這些命令列的封裝,下面也給出一些示例。

9. Java客戶端操縱ZooKeeper:
>* 這裡也只簡單示例一些基本操作:
>```java
public class ZooKeeperClient {
    //同步互斥變數,用來阻塞等待ZooKeeper連線完成之後再進行ZooKeeper的操作命令
    private static CountDownLatch connectedSemaphore = new CountDownLatch( 1 );
    public static void main(String[] args) throws Exception {
        // 建立一個與伺服器的連線
        ZooKeeper zk = new ZooKeeper("119.29.153.56:2181",3000, new Watcher() {//這個是伺服器連線完成回撥的監聽器
            // 監控所有被觸發的事件
            public void process(WatchedEvent event) {
                System.out.println("已經觸發了" + event.getType() + "事件!");
                if ( Event.KeeperState.SyncConnected == event.getState() ) {
                    //連線完成的同步事件,互斥變數取消,下面的阻塞停止,程式繼續執行
                    connectedSemaphore.countDown();
                }
            }
        });
        //如果和ZooKeeper伺服器的TCP連線還沒完全建立,就阻塞等待
        connectedSemaphore.await();
        // 建立一個目錄節點
        zk.create("/testRootPath", "testRootData".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
                CreateMode.PERSISTENT);
        // 建立一個子目錄節點
        zk.create("/testRootPath/testChildPathOne", "testChildDataOne".getBytes(),
                ZooDefs.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(),
                ZooDefs.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();
    }
}




<div class="se-preview-section-delimiter"></div>

輸出結果:

已經觸發了None事件!
testRootData
[testChildPathOne]
目錄節點狀態:[17179869200,17179869200,1482114759242,1482114759242,0,1,0,0,12,1,17179869201
]
已經觸發了NodeChildrenChanged事件!
testChildDataTwo
已經觸發了NodeDeleted事件!
已經觸發了NodeDeleted事件!




<div class="se-preview-section-delimiter"></div>

解釋
第一個新增節點/testRootPath,觸發None事件,之後再獲取這個節點資料、其子節點列表、節點狀態
接下來建立第二個子節點/testRootPath/testChildPathTwo,觸發NodeChildrenChanged事件
然後刪除兩個子節點,觸發兩次NodeDeleted事件
* 常用介面介紹

  • IBM教程這邊已經有部分介面的說明,可以拿來當做初步認識,在比較下面,往下翻哦~。
  • 幾個可能的疑問:
    ACL:這個是ZooKeeper本身提供的簡單的許可權控制模型,有一些簡單的許可權控制策略,可以稍做了解。
    OP:面向物件的思想嘛,一個ZooKeeper的操作命令也抽象為一個操作物件,不過它只是個抽象類,具體的實現有Delete、Check等子類才是實際的具體操作物件。
    CreateMode:建立節點的模式列舉,四個成員分別是:PERSISTENT(持久化)、PERSISTENT_SEQUENTIAL(持久化並序號自增)、EPHEMERAL(臨時,當前session有效)、EPHEMERAL_SEQUENTIAL(臨時,當前session有效,序號自增)
    ZooDefs.Ids:提供了上面ACL的常用的許可權策略常量列表。
    Event.KeeperState:ZooKeeper的事件型別狀態常量列表。
  • #### 特別注意:ZooKeeper是支援Watcher監聽的,你可以用它監聽某個節點的值是否存在、是否改變、是否被刪除等之類的動作,當他觸發了相關的動作就會進行回撥的,有點是非同步程式設計,也是特別棒的東西。
    到這裡入門就告一段落了,接下來就是實際應用場景的分析啦~

實戰使用


  1. 統一命名服務(Name Service):在ZooKeeper的樹形結構下你可以建立一個統一的不重複的命名,比如create建立一個節點即可,再建立一個相同名稱的節點是不允許的。
  2. 配置管理(Configuration Management):意思就是分散式應用的配置可以交給ZooKeeper來管理,不然一旦修改配置,就得每臺機器上的配置都做相應的修改,如果交給ZooKeeper管理的話,只需要修改ZooKeeper上的節點值即可。
  3. 叢集管理(Group Membership)
  • Zookeeper 不僅能夠幫你維護當前的叢集中機器的服務狀態,而且能夠幫你選出一個“總管”,讓這個總管來管理叢集,這就是 Zookeeper 的另一個功能 Leader Election。
  • 它們的實現方式都是在 Zookeeper上建立一個 EPHEMERAL 型別的目錄節點,然後每個 Server 在它們建立目錄節點的父目錄節點上呼叫 getChildren(String path, boolean watch) 方法並設定 watch 為 true,由於是 EPHEMERAL 目錄節點,當建立它的 Server 死去,這個目錄節點也隨之被刪除,所以 Children 將會變化,這時 getChildren上的 Watch 將會被呼叫,所以其它 Server 就知道已經有某臺 Server 死去了。新增 Server 也是同樣的原理。
  • Zookeeper 如何實現 Leader Election,也就是選出一個 Master Server。和前面的一樣每臺 Server 建立一個 EPHEMERAL 目錄節點,不同的是它還是一個 SEQUENTIAL 目錄節點,所以它是個 EPHEMERAL_SEQUENTIAL 目錄節點。之所以它是 EPHEMERAL_SEQUENTIAL 目錄節點,是因為我們可以給每臺 Server 編號,我們可以選擇當前是最小編號的 Server 為 Master,假如這個最小編號的 Server 死去,由於是 EPHEMERAL 節點,死去的 Server 對應的節點也被刪除,所以當前的節點列表中又出現一個最小編號的節點,我們就選擇這個節點為當前 Master。這樣就實現了動態選擇 Master,避免了傳統意義上單 Master 容易出現單點故障的問題。
  • 共享鎖(Locks):共享鎖在同一個程序中很容易實現,但是在跨程序或者在不同 Server 之間就不好實現了。Zookeeper 卻很容易實現這個功能,實現方式也是需要獲得鎖的 Server 建立一個 EPHEMERAL_SEQUENTIAL 目錄節點,然後呼叫 getChildren方法獲取當前的目錄節點列表中最小的目錄節點是不是就是自己建立的目錄節點,如果正是自己建立的,那麼它就獲得了這個鎖,如果不是那麼它就呼叫 exists(String path, boolean watch) 方法並監控 Zookeeper 上目錄節點列表的變化,一直到自己建立的節點是列表中最小編號的目錄節點,從而獲得鎖,釋放鎖很簡單,只要刪除前面它自己所建立的目錄節點就行了。
  • 佇列管理
  • 同步佇列
    當一個佇列的成員都聚齊時,這個佇列才可用,否則一直等待所有成員到達,這種是同步佇列。
    佇列按照 FIFO 方式進行入隊和出隊操作,例如實現生產者和消費者模型。
    同步佇列用 Zookeeper 實現的實現思路如下:
    建立一個父目錄 /synchronizing,每個成員都監控標誌(Set Watch)位目錄 /synchronizing/start 是否存在,然後每個成員都加入這個佇列,加入佇列的方式就是建立 /synchronizing/member_i 的臨時目錄節點,然後每個成員獲取 / synchronizing 目錄的所有目錄節點,也就是 member_i。判斷 i 的值是否已經是成員的個數,如果小於成員個數等待 /synchronizing/start 的出現,如果已經相等就建立 /synchronizing/start。
  • FIFO佇列
    實現的思路也非常簡單,就是在特定的目錄下建立 SEQUENTIAL 型別的子目錄 /queue_i,這樣就能保證所有成員加入佇列時都是有編號的,出佇列時通過 getChildren( ) 方法可以返回當前所有的佇列中的元素,然後消費其中最小的一個,這樣就能保證 FIFO。

  • 可見ZooKeeper本身的樹形目錄結構以及其提供的對目錄節點的監控Watcher,提供了實時資料同步以及可客戶端的及時通知。並且利用節點之間的變化觸發的事件型別可以很方便地設計很多實際應用場景的演算法需求。具體的很多說明和演算法示例程式碼在IBM教程中有詳細的講解。
  • 常用分散式服務框架和ZooKeeper的依賴講解

  • 之前的Hadoop 2.x高可用配置使用了ZooKeeper,但是我根本不知道這個外部新增的ZooKeeper工具是怎麼被Hadoop呼叫的,當時只是知道按照教程一步步下來就能成功執行,不過現在好好把ZooKeeper研究完了,就該來好好回顧一下這個問題了。

  • 具體的過程就不在這裡重複說明了,只挑要點講解:
    1. Hadoop 2.x啟動前要求先把ZooKeeper配置好並啟動起來,這個時候ZooKeeper還是獨立執行的。
    2. Hadoop 2.x配置完成之後在啟動步驟中有一步:
      hdfs zkfc -formatZK

這步幹嘛的?這個時候Hadoop中的多個NameNode節點都已經配置好了,這個步驟就是把NameNode的資訊註冊到ZooKeeper當中,包括哪個是Active,有哪些Standby,都在ZooKeeper當中進行註冊記錄,並且有一個ZKFC程序負責觀察NameNode的狀態,如果有NameNode宕機了,就馬上通知ZooKeeper進行相應的記錄修改,也就是說,ZooKeeper當中實時存放著NameNode的節點列表以及哪個是Active。(這部分的實時記錄和更新程式碼存在ZKFC當中,是Hadoop本身就已經實現的程式碼,不需要我們自己編寫,配置好就行)。
3. Hadoop怎麼知道ZooKeeper的存在?hdfs-site.xml中不是配置了dfs.nameservices這個屬性嗎,這個屬性就是告訴Hadoop ZooKeeper的地址,Hadoop通過這個地址連線到ZooKeeper註冊NameNode的命名資訊,這個動作由hdfs zkfc -formatZK這個命令觸發初始化執行。
4. 到這步就已經知道了,Hadoop中的NameNode的資訊ZooKeeper都知道了,那我們是怎麼訪問HDFS的呢?教程中很清楚說明了,我們訪問的是hdfs-site.xml中配置的dfs.nameservices來訪問HDFS的,這個地址剛才說了,就是ZooKeeper的地址,所以在訪問HDFS的時候就是先訪問了ZooKeeper得到當前的Active NameNode,然後再用得到的Active NameNode地址再去訪問HDFS。
5. Hadoop的Active NameNode宕機呢?ZKFC時刻檢測著NameNode,當NameNode宕機的時候,通知ZooKeeper,ZooKeeper儲存了所有的NameNode的地址列表,他去通知所有的Standby NameNode進行搶鎖競選,誰搶到不重要,結果是會有一個Standby NameNode搶到鎖並切換為Active NameNode,並通知ZooKeeper,這個時候ZooKeeper中的資料依然是實時最新的,很完美~
6. 這不實現了高可用和主備自動切換嗎~ 簡單粗暴~

參考文件

參考文件

相關推薦

ZooKeeper配置學習筆記

ZooKeeper介紹 Zookeeper 分散式服務框架是 Apache Hadoop 的一個子專案,它主要是用來解決分散式應用中經常遇到的一些資料管理問題,如:統一命名服務、狀態同步服務、叢集管理、分散式應用配置項的管理等。本文將從使用者角度詳細介紹

1. PostgreSQL-安裝基本配置學習筆記

安裝和配置 日常使用 buffer java、 note 安裝完成 for ora har 1 PostgreSQL簡介1.1 概述??PostgreSQL數據庫是目前功能最強大的開源數據庫,支持豐富的數據類型(如JSON和JSONB類型,數組類型)和自定義類型。而且它提供

IP、Apache虛擬主機配置部分學習筆記

當前 環境變量 httpd 無法 php nbsp 轉換 配置系統 語法 IP地址 IP地址就是計算機的一個“編號”,該編號是唯一的。相當於我們的身份證號碼一樣。 IP地址格式:a.b.c.d ,每一段的取值範圍0-255。 本機的IP地址:127.0.0.1

Java過濾器Filter的原理及配置_學習筆記

ava .cn -1 求和 pattern 資源 分享 java過濾器 服務器 Filter中文意思為過濾器。顧名思義,過濾器可在瀏覽器以及目標資源之間起到一個過濾的作用。例如:水凈化器,可以看成是生活中的一個過濾器,他可以將汙水中的雜質過濾,從而使進入的汙水變成凈水。 對

nginx配置詳細-學習筆記

nginx配置詳細-學習筆記定義Nginx運行的用戶和用戶組 user www www; nginx進程數,建議設置為等於CPU總核心數。 worker_processes 8; #全局錯誤日誌定義類型,[ debug | info | notice | warn | error | crit ]error_

F28335 ePWM計數模組(CC)與 動作模組(AC)及其暫存器配置 ————TMS320F28335學習筆記(六)

1 計數比較模組 1.1 計數比較模組作用 計數比較模組是以時基計數器的值作為輸入,與比較暫存器CMPA和CMPB不斷進行比較的,當時基計數器的值等於其中之一時,就會產生相應的事件。 F28335就是通過對比這些值,來產生事件,與動作模組AC相配合來調節PWM的佔空比以及頻率。 補充:採

F28335 ePWM時基模組(TB)及其 暫存器配置————TMS320F28335學習筆記(五)

1 時基模組 TB 組成及工作原理簡介 每個PWM模組都有自己的時基單元,這決定了每個PWM模組的時序,時基模組的作用: 確定PWM的週期或頻率 管理當前ePWM模組和其他ePWM模組的相位,以此保持各個ePWM模組的同步性 設定時基計數器的計數方式,是增計數(up)

Zookeeper核心概念學習筆記

一言以蔽之:分散式系統的協調者 兩個核心功能 1.管理和儲存資料結點 2.提供對結點的監聽服務 三種角色 分別是Leader、Follower、OBSERVER,沒有leader的時候,所有zk伺服器都處於LOOKING狀態,不處於任何角色。一旦leader選舉成功,各個角色才各

簡單配置umiJS學習筆記

最近跟著Antd-Pro官方教程學習umi,這裡給大家推薦一下這個教程,特別適合初學者學習,教程涉及了AntD,AntD-Pro,umiJS,dvaJS等框架知識。 學習過程中跟著教程做了個Demo,

MATLAB使用學習筆記01:Cell陣列

關於cell陣列 元胞陣列最有用的地方在於,它可以在一個數組中的每個元胞裡,儲存不同的資料型別。就像人的身體裡可以有神經元細胞,血紅細胞等等,他們型別不同,但是統稱細胞並共存在人體中。 元胞陣列對於讀取,處理和寫入格式複雜的資料檔案非常有用。 1. Cell的

redis-cluster的配置學習

概述操作在/opt/clusters中分別建立6379 6380 6381 6382 6383 6384目錄,用於存放對應的資料檔案將redis.conf配置檔案複製到建立好的目錄中,並進行修改6379修改一下引數:bind 192.168.1.200 port 6379 d

攜程 Apollo 配置中心 | 學習筆記(七) | 如何將配置檔案敏感資訊加密?

以上為相關係列文章通過上述文章,相信我們的環境基本搭建完成!下面,我們將瞭解如何對存放在apollo配置中心的檔案進行脫敏處理。一、需求   當我們把我們專案中的所有配置資訊,都放入到apollo配置中心時,可能存在一些敏感配置資訊,不方便讓其他人檢視到。這時候我們就需要對我

攜程 Apollo 配置中心 | 學習筆記(十一)| 如何引入Apollo配置中心改造老Web專案?

本章將介紹如何從Apollo配置中心獲取配置。專欄目錄:歡迎關注個人公眾號:  Coder程式設計歡迎關注個人網站:www.52melrin.com需求:將老Web專案接入Apollo配置中心。(主要為非Maven專案)思路:這裡主要是針對客戶端client進行修改。一、修改

基於appium自動化測試案例12--使用yaml 進行資料配置學習筆記

在編寫appium自動化測試指令碼中,經常需要配置裝置及app的引數,如:desired_caps={} #裝置平臺名稱 desired_caps['platformName']='Android' #裝置名稱 desired_caps['deviceName']='127.

Maven配置檔案學習筆記

對於maven的具體配置檔案還不是很瞭解,一直都是似懂非懂的狀態,趁著最近專案不緊張,決定學習一下maven的配置檔案. maven的setting.xml檔案最開始介紹了maven的兩個作用域. 在maven配置檔案的開始部分,介紹了maven的兩個作用域,原文大致意思

CUDA學習日誌:開發環境配置學習資源

接觸CUDA的時間並不長,最開始是在cuda-convnet的程式碼中接觸CUDA程式碼,當時確實看的比較痛苦。最近得空,在圖書館借了本《GPU高效能程式設計 CUDA實戰》來看看,同時也整理一些部落

spring配置檔案學習筆記

<!-- 整篇系列內容都是根據郭峰大大的Spring從入門到精通學習整理的--> SPRING配置檔案詳解 概念、用途: Spring配置檔案是用於指導spring工廠進行bean生產、依賴注入(裝配)及Bean例項分發的”圖紙”。 Spring配置檔案是一個

攜程 Apollo 配置中心 | 學習筆記(六) | 詳細介紹攜程Apollo配置中心部署至Kubernetes叢集中

專欄目錄:歡迎關注個人公眾號:  Coder程式設計歡迎關注個人網站:www.52melrin.com以上為之前寫的攜程Apollo配置中心相關文章,有需要,請自行查閱接下來將介紹攜程Apollo配置中心部署至Kubernetes叢集中注意:這裡需要有一定的Kubernete

攜程 Apollo 配置中心 | 學習筆記(十) 如何從Apollo配置中心獲取實時更新配置資訊(熱釋出)?

本章將介紹Apollo配置中心的熱釋出。其實在第九章就有提到Apollo配置中心提供的熱釋出,及實時獲取最新配置資訊。通過API的方式獲取API 方式     API方式靈活,功能完備,配置值實時更新(熱釋出),支援所有Java環境。TestController4.java@

攜程 Apollo 配置中心 | 學習筆記(十三)| 如何將日誌配置檔案放入到Apollo配置中心並支援熱更新?

本章將介紹如何將日誌配置檔案放入到Apollo配置中心並支援熱更新專欄目錄:歡迎關注個人公眾號:  Coder程式設計歡迎關注個人網站:www.52melrin.com需求     日誌模組是每個專案中必須的,用來記錄程式執行中的相關資訊。一般在開發環境下使用DEBUG級別的