Zookeeper學習總結及集羣部署記錄

 

ZooKeeper是一個開放源碼的分佈式應用程序協調服務,它包含一個簡單的原語集,分佈式應用程序能夠基於它實現同步服務,配置維護和命名服務等。java

Zookeeper設計目的node

  • 最終一致性:client不論鏈接到那個Server,展現給它的都是同一個視圖。
  • 可靠性:具備簡單、健壯、良好的性能、若是消息m被到一臺服務器接收,那麼消息m將被全部服務器接收。
  • 實時性:Zookeeper保證客戶端將在一個時間間隔範圍內得到服務器的更新信息,或者服務器失效的信息。但因爲網絡延時等緣由,Zookeeper不能保證兩個客戶端能同時獲得剛更新的數據,若是須要最新數據,應該在讀數據以前調用sync()接口。
  • 等待無關(wait-free):慢的或者失效的client不得干預快速的client的請求,使得每一個client都能有效的等待。
  • 原子性:更新只能成功或者失敗,沒有中間狀態。
  • 順序性:包括全局有序和偏序兩種:全局有序是指若是在一臺服務器上消息a在消息b前發佈,則在全部Server上消息a都將在消息b前被髮布;偏序是指若是一個消息b在消息a後被同一個發送者發佈,a必將排在b前面。

Zookeeper工做原理
在zookeeper的集羣中,各個節點共有下面3種角色和4種狀態
角色:leader、follower、observer
狀態:leading、following、observing、lookinglinux

Zookeeper的核心是原子廣播,這個機制保證了各個Server之間的同步。實現這個機制的協議叫作Zab協議(ZooKeeper Atomic Broadcast protocol)。Zab協議有兩種模式,它們分別是恢復模式(Recovery選主)和廣播模式(Broadcast同步)。當服務啓動或者在領導者崩潰後,Zab就進入了恢復模式,當領導者被選舉出來,且大多數Server完成了和leader的狀態同步之後,恢復模式就結束了。狀態同步保證了leader和Server具備相同的系統狀態。
爲了保證事務的順序一致性,zookeeper採用了遞增的事務id號(zxid)來標識事務。全部的提議(proposal)都在被提出的時候加上了zxid。實現中zxid是一個64位的數字,它高32位是epoch用來標識leader關係是否改變,每次一個leader被選出來,它都會有一個新的epoch,標識當前屬於那個leader的統治時期。低32位用於遞增計數。數據庫

每一個Server在工做過程當中有4種狀態:apache

  • LOOKING:當前Server不知道leader是誰,正在搜尋。
  • LEADING:當前Server即爲選舉出來的leader。
  • FOLLOWING:leader已經選舉出來,當前Server與之同步。
  • OBSERVING:observer的行爲在大多數狀況下與follower徹底一致,可是他們不參加選舉和投票,而僅僅接受(observing)選舉和投票的結果。

Zookeeper數據與存儲api

1.  內存數據
Zookeeper的數據模型是樹結構,在內存數據庫中,存儲了整棵樹的內容,包括全部的節點路徑、節點數據、ACL信息,Zookeeper會定時將這個數據存儲到磁盤上。緩存

1) DataTree
DataTree是內存數據存儲的核心,是一個樹結構,表明了內存中一份完整的數據。DataTree不包含任何與網絡、客戶端鏈接及請求處理相關的業務邏輯,是一個獨立的組件。bash

2) DataNode
DataNode是數據存儲的最小單元,其內部除了保存告終點的數據內容、ACL列表、節點狀態以外,還記錄了父節點的引用和子節點列表兩個屬性,其也提供了對子節點列表進行操做的接口。服務器

3) KDatabase
Zookeeper的內存數據庫,管理Zookeeper的全部會話、DataTree存儲和事務日誌。ZKDatabase會定時向磁盤dump快照數據,同時在Zookeeper啓動時,會經過磁盤的事務日誌和快照文件恢復成一個完整的內存數據庫。網絡

2.  事務日誌
1) 文件存儲
在配置Zookeeper集羣時須要配置dataDir目錄,其用來存儲事務日誌文件。也能夠爲事務日誌單獨分配一個文件存儲目錄:dataLogDir。若配置dataLogDir爲/data/zookeeper-3.5.3-beta/logs,那麼Zookeeper在運行過程當中會在該目錄下創建一個名字爲version-2的子目錄,該目錄肯定了當前Zookeeper使用的事務日誌格式版本號,當下次某個Zookeeper版本對事務日誌格式進行變動時,此目錄也會變動,即在version-2子目錄下會生成一系列文件大小一致(64MB)的文件。

2) 日誌格式
在配置好日誌文件目錄,啓動Zookeeper後, 會在zoo.cfg文件裏配置的日誌目錄/data/zookeeper-3.5.3-beta/logs/version-2下產生日誌文件, 如:

3) 日誌寫入
FileTxnLog負責維護事務日誌對外的接口,包括事務日誌的寫入和讀取等。Zookeeper的事務日誌寫入過程大致能夠分爲以下6個步驟:

a) 肯定是否有事務日誌可寫。當Zookeeper服務器啓動完成須要進行第一次事務日誌的寫入,或是上一次事務日誌寫滿時,都會處於與事務日誌文件斷開的狀態,即Zookeeper服務器沒有和任意一個日誌文件相關聯。所以在進行事務日誌寫入前,Zookeeper首先會判斷FileTxnLog組件是否已經關聯上一個可寫的事務日誌文件。若沒有,則會使用該事務操做關聯的ZXID做爲後綴建立一個事務日誌文件,同時構建事務日誌的文件頭信息,並當即寫入這個事務日誌文件中去,同時將該文件的文件流放入streamToFlush集合,該集合用來記錄當前須要強制進行數據落盤的文件流。

b) 肯定事務日誌文件是否須要擴容(預分配)。Zookeeper會採用磁盤空間預分配策略。當檢測到當前事務日誌文件剩餘空間不足4096字節時,就會開始進行文件空間擴容,即在現有文件大小上,將文件增長65536KB(64MB),而後使用"0"填充被擴容的文件空間。

c) 事務序列化。對事務頭和事務體的序列化,其中事務體又可分爲會話建立事務、節點建立事務、節點刪除事務、節點數據更新事務等。

d) 生成Checksum。爲保證日誌文件的完整性和數據的準確性,Zookeeper在將事務日誌寫入文件前,會計算生成Checksum。

e) 寫入事務日誌文件流。將序列化後的事務頭、事務體和Checksum寫入文件流中,此時併爲寫入到磁盤上。

f) 事務日誌刷入磁盤。因爲步驟5中的緩存緣由,沒法實時地寫入磁盤文件中,所以須要將緩存數據強制刷入磁盤。

4) 日誌截斷
在Zookeeper運行過程當中,可能出現非Leader記錄的事務ID比Leader上大,這是非法運行狀態。此時,須要保證全部機器必須與該Leader的數據保持同步,即Leader會發送TRUNC命令給該機器,要求進行日誌截斷,Learner收到該命令後,就會刪除全部包含或大於該事務ID的事務日誌文件。

3.  snapshot-數據快照
數據快照是Zookeeper數據存儲中很是核心的運行機制,數據快照用來記錄Zookeeper服務器上某一時刻的全量內存數據內容,並將其寫入指定的磁盤文件中

1) 文件存儲
與事務文件相似,Zookeeper快照文件也能夠指定特定磁盤目錄,經過dataDir屬性來配置。若指定dataDir爲/home/admin/zkData/zk_data,則在運行過程當中會在該目錄下建立version-2的目錄,該目錄肯定了當前Zookeeper使用的快照數據格式版本號。在Zookeeper運行時,會生成一系列文件。例如:

2) 數據快照
FileSnap負責維護快照數據對外的接口,包括快照數據的寫入和讀取等,將內存數據庫寫入快照數據文件實際上是一個序列化過程。針對客戶端的每一次事務操做,Zookeeper都會將他們記錄到事務日誌中,同時也會將數據變動應用到內存數據庫中,Zookeeper在進行若干次事務日誌記錄後,將內存數據庫的全量數據Dump到本地文件中,這就是數據快照。其步驟以下:

a) 肯定是否須要進行數據快照。每進行一次事務日誌記錄以後,Zookeeper都會檢測當前是否須要進行數據快照,考慮到數據快照對於Zookeeper機器的影響,須要儘可能避免Zookeeper集羣中的全部機器在同一時刻進行數據快照。採用過半隨機策略進行數據快照操做。

b) 切換事務日誌文件。表示當前的事務日誌已經寫滿,須要從新建立一個新的事務日誌。

c) 建立數據快照異步線程。建立單獨的異步線程來進行數據快照以免影響Zookeeper主流程。

d) 獲取全量數據和會話信息。從ZKDatabase中獲取到DataTree和會話信息。

e) 生成快照數據文件名。Zookeeper根據當前已經提交的最大ZXID來生成數據快照文件名。

f) 數據序列化。首先序列化文件頭信息,而後再對會話信息和DataTree分別進行序列化,同時生成一個Checksum,一併寫入快照數據文件中去。

4.  初始化
在Zookeeper服務器啓動期間,首先會進行數據初始化工做,用於將存儲在磁盤上的數據文件加載到Zookeeper服務器內存中。

1) 初始化流程
Zookeeper的初始化過程以下圖所示:

數據的初始化工做是從磁盤上加載數據的過程,主要包括了從快照文件中加載快照數據和根據實物日誌進行數據修正兩個過程。

初始化FileTxnSnapLog: FileTxnSnapLog是Zookeeper事務日誌和快照數據訪問層,用於銜接上層業務和底層數據存儲,底層數據包含了事務日誌和快照數據兩部分。FileTxnSnapLog中對應FileTxnLog和FileSnap。

初始化ZKDatabase: 首先構建DataTree,同時將FileTxnSnapLog交付ZKDatabase,以便內存數據庫可以對事務日誌和快照數據進行訪問。在ZKDatabase初始化時,DataTree也會進行相應的初始化工做,如建立一些默認結點,如/、/zookeeper、/zookeeper/quota三個節點。

建立PlayBackListener: 其主要用來接收事務應用過程當中的回調,在Zookeeper數據恢復後期,會有事務修正過程,此過程會回調PlayBackListener來進行對應的數據修正。

處理快照文件: 此時能夠從磁盤中恢復數據了,首先從快照文件開始加載。

獲取最新的100個快照文件: 更新時間最晚的快照文件包含了最新的全量數據。

解析快照文件: 逐個解析快照文件,此時須要進行反序列化,生成DataTree和sessionsWithTimeouts,同時還會校驗Checksum及快照文件的正確性。對於100個快找文件,若是正確性校驗經過時,一般只會解析最新的那個快照文件。只有最新快照文件不可用時,纔會逐個進行解析,直至100個快照文件所有解析完。若將100個快照文件解析完後仍是沒法成功恢復一個完整的DataTree和sessionWithTimeouts,此時服務器啓動失敗。

獲取最新的ZXID: 此時根據快照文件的文件名便可解析出最新的ZXID:zxid_for_snap。該ZXID表明了Zookeeper開始進行數據快照的時刻。

處理事務日誌: 此時服務器內存中已經有了一份近似全量的數據,如今開始經過事務日誌來更新增量數據。

獲取全部zxid_for_snap以後提交的事務: 此時,已經能夠獲取快照數據的最新ZXID。只須要從事務日誌中獲取全部ZXID比步驟7獲得的ZXID大的事務操做。

事務應用: 獲取大於zxid_for_snap的事務後,將其逐個應用到以前基於快照數據文件恢復出來的DataTree和sessionsWithTimeouts。每當有一個事務被應用到內存數據庫中後,Zookeeper同時會回調PlayBackListener,將這事務操做記錄轉換成Proposal,並保存到ZKDatabase的committedLog中,以便Follower進行快速同步。

獲取最新的ZXID: 待全部的事務都被完整地應用到內存數據庫中後,也就基本上完成了數據的初始化過程,此時再次獲取ZXID,用來標識上次服務器正常運行時提交的最大事務ID。

校驗epoch: epoch標識了當前Leader週期,集羣機器相互通訊時,會帶上這個epoch以確保彼此在同一個Leader週期中。完成數據加載後,Zookeeper會從步驟11中肯定ZXID中解析出事務處理的Leader週期:epochOfZxid。同時也會從磁盤的currentEpoch和acceptedEpoch文件中讀取上次記錄的最新的epoch值,進行校驗。

5.  數據同步
整個集羣完成Leader選舉後,Learner會向Leader進行註冊,當Learner向Leader完成註冊後,就進入數據同步環節,同步過程就是Leader將那些沒有在Learner服務器上提交過的事務請求同步給Learner服務器,大致過程以下:

獲取Learner狀態: 在註冊Learner的最後階段,Learner服務器會發送給Leader服務器一個ACKEPOCH數據包,Leader會從這個數據包中解析出該Learner的currentEpoch和lastZxid。

數據同步初始化: 首先從Zookeeper內存數據庫中提取出事務請求對應的提議緩存隊列proposals,同時完成peerLastZxid(該Learner最後處理的ZXID)、minCommittedLog(Leader提議緩存隊列commitedLog中最小的ZXID)、maxCommittedLog(Leader提議緩存隊列commitedLog中的最大ZXID)三個ZXID值的初始化。

對於集羣數據同步而言,一般分爲四類: 直接差別化同步(DIFF同步)先回滾再差別化同步(TRUNC+DIFF同步)僅回滾同步(TRUNC同步)全量同步(SNAP同步)在初始化階段,Leader會優先以全量同步方式來同步數據。同時,會根據Leader和Learner之間的數據差別狀況來決定最終的數據同步方式。

->  直接差別化同步(DIFF同步:  peerLastZxid介於minCommittedLog和maxCommittedLog之間)。Leader首先向這個Learner發送一個DIFF指令,用於通知Learner進入差別化數據同步階段,Leader即將把一些Proposal同步給本身,針對每一個Proposal,Leader都會經過發送PROPOSAL內容數據包和COMMIT指令數據包來完成,

-> 先回滾再差別化同步(TRUNC+DIFF同步:  Leader已經將事務記錄到本地事務日誌中,可是沒有成功發起Proposal流程)。當Leader發現某個Learner包含了一條本身沒有的事務記錄,那麼就須要該Learner進行事務回滾,回滾到Leader服務器上存在的,同時也是最接近於peerLastZxid的ZXID。

->  僅回滾同步(TRUNC同步:  peerLastZxid大於maxCommittedLog)。Leader要求Learner回滾到ZXID值爲maxCommittedLog對應的事務操做。

->  全量同步(SNAP同步:  peerLastZxid小於minCommittedLog或peerLastZxid不等於lastProcessedZxid)。Leader沒法直接使用提議緩存隊列和Learner進行同步,所以只能進行全量同步。Leader將本機的全量內存數據同步給Learner。Leader首先向Learner發送一個SNAP指令,通知Learner即將進行全量同步,隨後,Leader會從內存數據庫中獲取到全量的數據節點和會話超時時間記錄器,將他們序列化後傳輸給Learner。Learner接收到該全量數據後,會對其反序列化後載入到內存數據庫中。

Zookeeper集羣節點

  • Zookeeper節點部署越多,服務的可靠性越高,建議部署奇數個節點,由於zookeeper集羣是以宕機個數過半纔會讓整個集羣宕機的。
  • 須要給每一個zookeeper 1G左右的內存,若是可能的話,最好有獨立的磁盤,由於獨立磁盤能夠確保zookeeper是高性能的。若是你的集羣負載很重,不要把zookeeper和RegionServer運行在同一臺機器上面,就像DataNodes和TaskTrackers同樣。

ZooKeeper經常使用命令
Zookeeper服務端命令
啓動ZK服務:    sh bin/zkServer.sh start
查看ZK服務狀態:   sh bin/zkServer.sh status
中止ZK服務:   sh bin/zkServer.sh stop
重啓ZK服務:   sh bin/zkServer.sh restart

Zookeeper客戶端命令
客戶端登陸Zookeeper:   sh bin/zkCli.sh -server 127.0.0.1:2181
顯示根目錄下、文件:    ls /      #使用 ls 命令來查看當前ZooKeeper中所包含的內容。即查看Zookeeper當前註冊了哪些服務?
顯示根目錄下、文件: ls2 /       #查看當前節點數據並能看到更新次數等數據
建立文件,並設置初始內容: create /zk "test"       #建立一個新的znode節點"zk"以及與它關聯的字符串
獲取文件內容:     get /zk               #確認znode是否包含咱們所建立的字符串
修改文件內容:    set /zk "zkbak"    #對zk所關聯的字符串進行設置
刪除文件:     delete /zk                #將剛纔建立的znode刪除
退出客戶端:    quit
幫助命令:     help

ZooKeeper的"watch"機制說明 
zookeeper做爲一款成熟的分佈式協調框架,訂閱-發佈功能是很重要的一個。所謂訂閱發佈功能,其實說白了就是觀察者模式。觀察者會訂閱一些感興趣的主題,而後這些主題一旦變化了,就會自動通知到這些觀察者。

1)  zookeeper的watch機制原理
zookeeper的訂閱發佈也就是watch機制,是一個輕量級的設計,由於它採用了一種推拉結合的模式。一旦服務端感知主題變了,那麼只會發送一個事件類型和節點信息給關注的客戶端,而不會包括具體的變動內容,因此事件自己是輕量級的,這就是所謂的"推"部分,而後收到變動通知的客戶端須要本身去拉變動的數據,這就是"拉"部分。znode以某種方式發生變化時,"觀察"(watch)機制可讓客戶端獲得通知.能夠針對ZooKeeper服務的「操做」來設置觀察,該服務的其餘 操做能夠觸發觀察。

訂閱-發佈在zookeeper中是經過事件註冊和回調機制實現的,整個註冊回調過程分爲三個大的部分:客戶端註冊,服務端發回事件,客戶端回調。

2)  zookeeper的watch架構
watch的總體流程以下圖所示,客戶端先向zookeeper服務端成功註冊想要監聽的節點狀態,同時客戶端本地會存儲該監聽器相關的信息在WatchManager中,當zookeeper服務端監聽的數據狀態發生變化時,zookeeper就會主動通知發送相應事件信息給相關會話客戶端,客戶端就會在本地響應式的回調相關watcher的Handler。

3)  zookeeper的watch特性
watch是一次性的,每次都須要從新註冊,而且客戶端在會話異常結束時不會收到任何通知,而快速重鏈接時仍不影響接收通知。watch的回調執行都是順序執行的,而且客戶端在沒有收到關注數據的變化事件通知以前是不會看到最新的數據,另外須要注意不要在Watch回調邏輯中阻塞整個客戶端的watch回調。watch是輕量級的,WatchEvent是最小的通訊單元,結構上只包含通知狀態、事件類型和節點路徑。ZooKeeper服務端只會通知客戶端發生了什麼,並不會告訴具體內容。

Zookeeper集羣部署記錄

1)服務器信息
主機名                        系統                    IP地址
sign-zk01.wangshibo.cn    CentOS release 6.8    172.16.51.198
sign-zk02.wangshibo.cn    CentOS release 6.8    172.16.51.199
sign-zk03.wangshibo.cn    CentOS release 6.8    172.16.51.200

2)安裝過程
先記錄sign-zk01.wangshibo.cn節點機的部署過程(其餘兩個節點的部署過程基本一致)

安裝jdk
能夠yum安裝自帶的jdk
[root@sign-zk01 ~]# yum -y install java-1.7.0-openjdk*
[root@sign-zk01 ~]# java -version
java version "1.7.0_151"
OpenJDK Runtime Environment (rhel-2.6.11.0.el6_9-x86_64 u151-b00)
OpenJDK 64-Bit Server VM (build 24.151-b00, mixed mode)

不過建議卸載掉自帶的jdk,安裝Java OpenJDK
[root@sign-zk01 ~]# yum -y remove java-1.7.0-openjdk*
[root@sign-zk01 ~]# yum -y remove tzdata-java.noarch
[root@sign-zk01 ~]# java -version
-bash: java: command not found

[root@sign-zk01 ~]# rpm -ivh jdk-7u79-linux-x64.rpm --force
[root@sign-zk01 ~]# java -version
java version "1.7.0_79"
Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)

安裝並部署zookeeper集羣
[app@sign-zk01 ~]$ cd /usr/local/src/
[app@sign-zk01 src]$ wget http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.11/zookeeper-3.4.11.tar.gz
[app@sign-zk01 src]$ tar -zvxf zookeeper-3.4.11.tar.gz
[app@sign-zk01 src]$ mv zookeeper-3.4.11.tar.gz /data/
[app@sign-zk01 src]$ cd /data/zookeeper-3.4.11/conf/
[app@sign-zk01 conf]$ cp zoo_sample.cfg zoo.cfg 
[app@sign-zk01 conf]$ cat zoo.cfg |grep -v "#"
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data/zookeeper-3.4.11/data
dataLogDir=/data/zookeeper-3.4.11/logs
clientPort=2181
server.1=sign-zk01.wangshibo.cn:2888:3888
server.2=sign-zk02.wangshibo.cn:2888:3888
server.3=sign-zk03.wangshibo.cn:2888:3888

參數說明:
tickTime這個時間是做爲zookeeper服務器之間或客戶端與服務器之間維持心跳的時間間隔,也就是說每一個tickTime時間就會發送一個心跳。

initLimit這個配置項是用來配置zookeeper接受客戶端(這裏所說的客戶端不是用戶鏈接zookeeper服務器的客戶端,而是zookeeper服務器集羣中鏈接到leader的follower 服務器)初始化鏈接時最長能忍受多少個心跳時間間隔數。
當已經超過10個心跳的時間(也就是tickTime)長度後 zookeeper 服務器尚未收到客戶端的返回信息,那麼代表這個客戶端鏈接失敗。總的時間長度就是 10*2000=20秒。

syncLimit這個配置項標識leader與follower之間發送消息,請求和應答時間長度,最長不能超過多少個tickTime的時間長度,總的時間長度就是5*2000=10秒。

dataDir顧名思義就是zookeeper保存數據的目錄,默認狀況下zookeeper將寫數據的日誌文件也保存在這個目錄裏;

clientPort這個端口就是客戶端鏈接Zookeeper服務器的端口,Zookeeper會監聽這個端口接受客戶端的訪問請求;

server.A=B:C:D中的A是一個數字,表示這個是第幾號服務器,B是這個服務器的IP地址,C第一個端口用來集羣成員的信息交換,表示這個服務器與集羣中的leader服務器交換信息的端口,D是在leader掛掉時專門用來進行選舉leader所用的端口。


[app@sign-zk01 conf]$ mkdir /data/zookeeper-3.4.11/data
[app@sign-zk01 conf]$ mkdir /data/zookeeper-3.4.11/logs

建立ServerID標識(這是三個節點機器惟一配置不同的地方,三個節點的myid文件配置的ServerID不能重複,建議分別配置成一、二、3)
除了修改zoo.cfg配置文件外,zookeeper集羣模式下還要配置一個myid文件,這個文件須要放在dataDir目錄下。
這個文件裏面有一個數據就是A的值(該A就是zoo.cfg文件中server.A=B:C:D中的A),在zoo.cfg文件中配置的dataDir路徑中建立myid文件。

[app@sign-zk01 ~]$ echo "1" > /data/zookeeper-3.4.11/data/myid
[app@sign-zk02 ~]$ echo "2" > /data/zookeeper-3.4.11/data/myid
[app@sign-zk03 ~]$ echo "3" > /data/zookeeper-3.4.11/data/myid

而後分別重啓三個節點機器的zookeeper(stop/start/restart)
[app@sign-zk01 ~]$ /data/zookeeper-3.4.11/bin/zkServer.sh start
[app@sign-zk02 ~]$ /data/zookeeper-3.4.11/bin/zkServer.sh start
[app@sign-zk03 ~]$ /data/zookeeper-3.4.11/bin/zkServer.sh start

[app@sign-zk01 ~]$ lsof -i:2181
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
java    7071  app   20u  IPv6  30989      0t0  TCP *:eforward (LISTEN)

查看zookeeper集羣狀態
[app@sign-zk01 ~]$ /data/zookeeper-3.4.11/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /data/zookeeper-3.4.11/bin/../conf/zoo.cfg
Mode: follower

[app@sign-zk02 ~]$ /data/zookeeper-3.4.11/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /data/zookeeper-3.4.11/bin/../conf/zoo.cfg
Mode: leader

[app@sign-zk03 ~]$ /data/zookeeper-3.4.11/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /data/zookeeper-3.4.11/bin/../conf/zoo.cfg
Mode: follower

從上面能夠看出,sign-zk01.wangshibo.cn,sign-zk03.wangshibo.cn兩臺服務器zookeeper的狀態是follow模式,
sign-zk02.wangshibo.cn這臺服務器zookeeper的狀態是leader模式。

Zookeeper集羣鏈接
Zookeeper集羣搭建完畢以後,能夠經過客戶端腳本鏈接到zookeeper集羣上面,對客戶端來講,zookeeper集羣是一個總體,鏈接到zookeeper集羣實際上感受在獨享整個集羣的服務。
[app@sign-zk01 ~]$ /data/zookeeper-3.4.11/bin/zkCli.sh -server sign-zk02.wangshibo.cn:2181
Connecting to sign-zk02.wangshibo.cn:2181
2017-11-22 15:22:55,110 [myid:] - INFO  [main:Environment@100] - Client environment:zookeeper.version=3.4.11-37e277162d567b55a07d1755f0b31c32e93c01a0, built on 11/01/2017 18:06 GMT
2017-11-22 15:22:55,113 [myid:] - INFO  [main:Environment@100] - Client environment:host.name=sign-zk01.wangshibo.cn
2017-11-22 15:22:55,113 [myid:] - INFO  [main:Environment@100] - Client environment:java.version=1.7.0_79
2017-11-22 15:22:55,114 [myid:] - INFO  [main:Environment@100] - Client environment:java.vendor=Oracle Corporation
2017-11-22 15:22:55,114 [myid:] - INFO  [main:Environment@100] - Client environment:java.home=/usr/java/jdk1.7.0_79/jre
2017-11-22 15:22:55,114 [myid:] - INFO  [main:Environment@100] - Client environment:java.class.path=/data/zookeeper-3.4.11/bin/../build/classes:/data/zookeeper-3.4.11/bin/../build/lib/*.jar:/data/zookeeper-3.4.11/bin/../lib/slf4j-log4j12-1.6.1.jar:/data/zookeeper-3.4.11/bin/../lib/slf4j-api-1.6.1.jar:/data/zookeeper-3.4.11/bin/../lib/netty-3.10.5.Final.jar:/data/zookeeper-3.4.11/bin/../lib/log4j-1.2.16.jar:/data/zookeeper-3.4.11/bin/../lib/jline-0.9.94.jar:/data/zookeeper-3.4.11/bin/../lib/audience-annotations-0.5.0.jar:/data/zookeeper-3.4.11/bin/../zookeeper-3.4.11.jar:/data/zookeeper-3.4.11/bin/../src/java/lib/*.jar:/data/zookeeper-3.4.11/bin/../conf:
2017-11-22 15:22:55,115 [myid:] - INFO  [main:Environment@100] - Client environment:java.library.path=/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
2017-11-22 15:22:55,115 [myid:] - INFO  [main:Environment@100] - Client environment:java.io.tmpdir=/tmp
2017-11-22 15:22:55,115 [myid:] - INFO  [main:Environment@100] - Client environment:java.compiler=<NA>
2017-11-22 15:22:55,115 [myid:] - INFO  [main:Environment@100] - Client environment:os.name=Linux
2017-11-22 15:22:55,115 [myid:] - INFO  [main:Environment@100] - Client environment:os.arch=amd64
2017-11-22 15:22:55,115 [myid:] - INFO  [main:Environment@100] - Client environment:os.version=2.6.32-696.13.2.el6.x86_64
2017-11-22 15:22:55,115 [myid:] - INFO  [main:Environment@100] - Client environment:user.name=app
2017-11-22 15:22:55,115 [myid:] - INFO  [main:Environment@100] - Client environment:user.home=/home/app
2017-11-22 15:22:55,115 [myid:] - INFO  [main:Environment@100] - Client environment:user.dir=/home/app
2017-11-22 15:22:55,116 [myid:] - INFO  [main:ZooKeeper@441] - Initiating client connection, connectString=sign-zk02.wangshibo.cn:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@594b7042
Welcome to ZooKeeper!
2017-11-22 15:22:55,136 [myid:] - INFO  [main-SendThread(sign-zk02.wangshibo.cn:2181):ClientCnxn$SendThread@1035] - Opening socket connection to server sign-zk02.wangshibo.cn/172.16.51.199:2181. Will not attempt to authenticate using SASL (unknown error)
2017-11-22 15:22:55,140 [myid:] - INFO  [main-SendThread(sign-zk02.wangshibo.cn:2181):ClientCnxn$SendThread@877] - Socket connection established to sign-zk02.wangshibo.cn/172.16.51.199:2181, initiating session
JLine support is enabled
[zk: sign-zk02.wangshibo.cn:2181(CONNECTING) 0] 2017-11-22 15:22:55,287 [myid:] - INFO  [main-SendThread(sign-zk02.wangshibo.cn:2181):ClientCnxn$SendThread@1302] - Session establishment complete on server sign-zk02.wangshibo.cn/172.16.51.199:2181, sessionid = 0x2000495ce4f0000, negotiated timeout = 30000

WATCHER::

WatchedEvent state:SyncConnected type:None path:null            
                                                                    //這一步按Enter
[zk: sign-zk02.wangshibo.cn:2181(CONNECTED) 0] ls /
[zookeeper]
[zk: sign-zk02.wangshibo.cn:2181(CONNECTED) 1] quit
Quitting...
2017-11-22 15:23:39,255 [myid:] - INFO  [main:ZooKeeper@687] - Session: 0x2000495ce4f0000 closed
2017-11-22 15:23:39,257 [myid:] - INFO  [main-EventThread:ClientCnxn$EventThread@520] - EventThread shut down for session: 0x2000495ce4f0000

經過上圖能夠看出整個zookeeper集羣已經搭建並測試完成。

                                                                                       問題記錄                                                                           
客戶端鏈接zookeeper,發生重連,拒絕鏈接,以下截圖(172.16.50.86/87/88是zk集羣的三個節點):

官網解釋:

解決辦法:

修改三個節點的zookeeper裏conf的zoo.cfg.dynamic.*文件
[app@uatsign-zk01 ~]$ cat /data/zookeeper-3.5.3-beta/conf/zoo.cfg.dynamic.800000000 
server.1=172.16.50.86:2888:3888:participant;
server.2=172.16.50.87:2888:3888:participant;
server.3=172.16.50.88:2888:3888:participant;

修改成
[app@uatsign-zk01 ~]$ cat /data/zookeeper-3.5.3-beta/conf/zoo.cfg.dynamic.800000000 
server.1=172.16.50.86:2888:3888:participant;172.16.50.86:2181
server.2=172.16.50.87:2888:3888:participant;172.16.50.87:2181
server.3=172.16.50.88:2888:3888:participant;172.16.50.88:2181

而後重啓每一個節點的zookeeper服務便可

注意:
上面修改中的172.16.50.86/87/88:2181不能配置成0.0.0.0:2181,得加具體的客戶端ip(即具體的每一個zk節點的ip),若是加全0,重連的時候就會用全0的ip,可能會出錯。

                                                              Zookeeper日誌清理機制 (清理zookeeper的歷史數據)                                        

問題記錄:
在服務器上部署了zookeeper集羣(三個節點), 在一次斷電重啓後發現, zookeeper服務在啓動後不就就自動關閉.
後面發現是集羣中的三個zk節點的數據盤使用率100%致使的! 發現是zoo.cfg文件裏配置的dataDir目錄 (即/data/zookeeper-3.5.3-beta/data) 佔用了數據盤很大空間!

解決辦法: 清理Zookeeper的歷史數據

1) 使用zookeeper自帶的清理腳本zkCleanup.sh, 手動清理zookeeper歷史數據

[app@uatsign-zk03 ~]$ /data/zookeeper-3.5.3-beta/bin/zkCleanup.sh  -n 5
.......................
Removing file: Jul 17, 2018 3:07:46 PM  /data/zookeeper-3.5.3-beta/data/version-2/snapshot.b0022de4e
2019-04-01 15:45:22,943 [myid:] - INFO  [main:PurgeTxnLog@154] - Removing file: Oct 7, 2018 7:20:30 AM  /data/zookeeper-3.5.3-beta/data/version-2/snapshot.c0022e577
Removing file: Oct 7, 2018 7:20:30 AM   /data/zookeeper-3.5.3-beta/data/version-2/snapshot.c0022e577
2019-04-01 15:45:22,944 [myid:] - INFO  [main:PurgeTxnLog@154] - Removing file: Mar 13, 2019 11:55:47 AM        /data/zookeeper-3.5.3-beta/data/version-2/snapshot.23000cc8ff
Removing file: Mar 13, 2019 11:55:47 AM /data/zookeeper-3.5.3-beta/data/version-2/snapshot.23000cc8ff
2019-04-01 15:45:22,948 [myid:] - INFO  [main:PurgeTxnLog@154] - Removing file: Mar 12, 2019 6:50:44 PM /data/zookeeper-3.5.3-beta/data/version-2/snapshot.2300056f0c
Removing file: Mar 12, 2019 6:50:44 PM  /data/zookeeper-3.5.3-beta/data/version-2/snapshot.2300056f0c
2019-04-01 15:45:22,951 [myid:] - INFO  [main:PurgeTxnLog@154] - Removing file: Nov 24, 2017 9:41:31 AM /data/zookeeper-3.5.3-beta/data/version-2/snapshot.0
...........................

[app@uatsign-zk03 ~]$ ll /data/zookeeper-3.5.3-beta/data/version-2/
total 2914360
-rw-rw-r-- 1 app  app          2 Apr  1 15:46 acceptedEpoch
-rw-rw-r-- 1 app  app          2 Apr  1 15:46 currentEpoch
-rw-rw-r-- 1 app  app  334514719 Apr  1 11:45 snapshot.2c00013653
-rw-rw-r-- 1 app  app   94838784 Apr  1 11:55 snapshot.2c00022aea
-rw-rw-r-- 1 app  app  186249216 Apr  1 14:36 snapshot.2d0001116d
-rw-r--r-- 1 root root 338225939 Apr  1 15:31 snapshot.2e00001294
-rw-r--r-- 1 root root 338224028 Apr  1 15:41 snapshot.2e000148d5

其中: -n 5  表示清理後保留5份最新的歷史數據

手動清理zookeeper歷史數據的命令總結

# /data/zookeeper-3.5.3-beta/bin/zkCleanup.sh  -n 5

以前版本, 須要在清理命令中添加zookeeper的數據目錄
# /data/zookeeper-3.5.3-beta/bin/zkCleanup.sh /data/zookeeper-3.5.3-beta/data -n 5

2) 設置zookeeper歷史數據的自動清理
修改zoo.cfg配置文件中的 autopurge.snapRetainCount 和 autopurge.purgeInterval 兩個參數實現定時清理

依次修改zookeeper集羣節點的zoo.cfg文件, 添加下面兩行內容:
[app@uatsign-zk03 ~]$ cat /data/zookeeper-3.5.3-beta/conf/zoo.cfg
.............
autopurge.snapRetainCount=10
autopurge.purgeInterval=1

而後依次重啓集羣節點的zookeeper服務便可
[app@uatsign-zk03 ~]$ ps -ef|grep zookeeper|awk '{print $2}'|xargs kill -9
[app@uatsign-zk03 ~]$ /data/zookeeper-3.5.3-beta/bin/zkServer.sh start

autopurge.purgeInterval:   這個參數指定了清理頻率,單位是小時,須要填寫一個1或更大的整數,默認是0,表示不開啓自動清理功能。

autopurge.snapRetainCount:  這個參數和上面的參數搭配使用,這個參數指定了須要保留的快照文件數目,默認是保留3個。

相關文章
相關標籤/搜索