Zookeeper入門:基本概念、5項配置、啟動

小雷FansUnion發表於2015-12-01
起源


   最早接觸Zookeeper,是在學習Hadoop權威指南這本書的時候,印象中是Hadoop專案的一個子工程。
   
   最近,專案中需要用到“分散式鎖”。
   
   之前,在開發P2P網貸系統的時候,就用到了“分散式鎖”,這個概念聽起來挺高階的,實際就是多臺機器下,同時執行專案下的“鎖”。
 之前是用Redis實現“分散式鎖”,但是週期性地出現了問題。只能是推測,程式異常退出,或者本地開發和測試環境用的一套Redis,
 本地執行緒定時任務,經常被強制關閉,鎖沒有成功釋放。
 
   聽Boss說,Memcache自帶的就是分散式的鎖,目前還沒用過。
   據Boss說,2005年之前,實現分散式鎖主要是用Memcache和Oracle。後來,出現了NoSQL的Redis,Oracle基本被MySQL取代,
“分散式鎖”就成了個問題。至於其他人是怎麼解決的,可能還是用了Memcache做快取,也可能還有其它機智或者解決方案。


   探討技術概念“分散式鎖”,真正的實現,必須是要考慮“業務場景”的。
   單獨的技術,很少有脫離業務場景的。
   
   後來Hadoop出現,有Zookeeper,不知什麼時候起,用Zookeeper實現分散式鎖的人就變多了。
   
   從哪裡可以看出來呢?百度搜尋“Zookeeper”,相關的文章多了,搜尋Zookeeper+分散式鎖的人變多了。
   
   看一個技術火不火,看看有多少人在學習,有多少人在總結相關的文章,就知道了。
   
Zookeeper基本介紹
 
   ZooKeeper是一個分散式的,開放原始碼的分散式應用程式協調服務,是Google的Chubby一個開源的實現,是Hadoop和Hbase的重要元件。
   它是一個為分散式應用提供一致性服務的軟體,提供的功能包括:配置維護、名字服務、分散式同步、組服務等。
ZooKeeper的目標就是封裝好複雜易出錯的關鍵服務,將簡單易用的介面和效能高效、功能穩定的系統提供給使用者。
ZooKeeper包含一個簡單的原語集,[1]  提供Java和C的介面。
   ZooKeeper程式碼版本中,提供了分散式獨享鎖、選舉、佇列的介面,程式碼在zookeeper-3.4.3\src\recipes。其中分佈鎖和佇列有Java和C兩個版本,選舉只有Java版本。


   ZooKeeper是以Fast Paxos演算法為基礎的,paxos演算法存在活鎖的問題,即當有多個proposer交錯提交時,有可能互相排斥導致沒有一個proposer能提交成功,
   而Fast Paxos作了一些優化,通過選舉產生一個leader,只有leader才能提交proposer,具體演算法可見Fast Paxos。因此,要想弄懂ZooKeeper首先得對Fast Paxos有所瞭解。[3] 
ZooKeeper的基本運轉流程:
1、選舉Leader。
2、同步資料。
3、選舉Leader過程中演算法有很多,但要達到的選舉標準是一致的。
4、Leader要具有最高的zxid。
5、叢集中大多數的機器得到響應並follow選出的Leader。


官方網站
   http://zookeeper.apache.org/
   
Zookeeper啟動
   實際專案開發中,用的是Linux版本的。
   #Zookeeper啟動
./zkServer.sh start &
./zkCli.sh -server 127.0.0.1:2181 &
  沒啥大問題


  自己學習,用的是Windows版本的。
  #Zookeeper啟動
  cd /d E:\Mongodb-Redis-Nginx\zookeeper-3.5.1-alpha\bin
  
  zkServer start &
  zkCli -server 127.0.0.1:2181 &


  E:\Mongodb-Redis-Nginx\zookeeper-3.5.1-alpha\bin>zkServer.cmd start
系統找不到指定的路徑。
Error: JAVA_HOME is incorrectly set.


E:\Mongodb-Redis-Nginx\zookeeper-3.5.1-alpha\bin>call  "-Dzookeeper.log.dir=E:\M
ongodb-Redis-Nginx\zookeeper-3.5.1-alpha\bin\..\logs" "-Dzookeeper.root.logger=I
NFO,CONSOLE" "-Dzookeeper.log.file=zookeeper-Administrator-server-XIAOLEI.log" "
-XX:+HeapDumpOnOutOfMemoryError" "-XX:OnOutOfMemoryError=cmd /c taskkill /pid %%
p /t /f" -cp "E:\Mongodb-Redis-Nginx\zookeeper-3.5.1-alpha\bin\..\build\classes;
E:\Mongodb-Redis-Nginx\zookeeper-3.5.1-alpha\bin\..\build\lib\*;E:\Mongodb-Redis
-Nginx\zookeeper-3.5.1-alpha\bin\..\*;E:\Mongodb-Redis-Nginx\zookeeper-3.5.1-alp
ha\bin\..\lib\*;E:\Mongodb-Redis-Nginx\zookeeper-3.5.1-alpha\bin\..\conf" org.ap
ache.zookeeper.server.quorum.QuorumPeerMain "E:\Mongodb-Redis-Nginx\zookeeper-3.
5.1-alpha\bin\..\conf\zoo.cfg" start
檔名、目錄名或卷標語法不正確。


E:\Mongodb-Redis-Nginx\zookeeper-3.5.1-alpha\bin>endlocal


#列印Java_HOME,明明已經配置好了,所以排除JAVA_HOME的原因
E:\Mongodb-Redis-Nginx\zookeeper-3.5.1-alpha\bin>echo %JAVA_HOME%
C:\Program Files\Java\jdk1.7.0_17;
就算是把JAVA_HOME改為"C:\Program Files\Java\jdk1.7.0_17"還是不行。




網上搜了下,可能是JDK版本的問題,我用的是JDK1.7。
因此,我判斷很可能是JDK和Zookeeper的版本匹配問題。


重新下載3.4.6版本的Zookeeper
  cd /d E:\Mongodb-Redis-Nginx\zookeeper-3.4.6\bin
  zkServer start &
  
  E:\Mongodb-Redis-Nginx\zookeeper-3.4.6\bin>zkServer.cmd start


E:\Mongodb-Redis-Nginx\zookeeper-3.4.6\bin>java "-Dzookeeper.log.dir=E:\Mongodb-
Redis-Nginx\zookeeper-3.4.6\bin\.." "-Dzookeeper.root.logger=INFO,CONSOLE" -cp "
E:\Mongodb-Redis-Nginx\zookeeper-3.4.6\bin\..\build\classes;E:\Mongodb-Redis-Ngi
nx\zookeeper-3.4.6\bin\..\build\lib\*;E:\Mongodb-Redis-Nginx\zookeeper-3.4.6\bin
\..\*;E:\Mongodb-Redis-Nginx\zookeeper-3.4.6\bin\..\lib\*;E:\Mongodb-Redis-Nginx
\zookeeper-3.4.6\bin\..\conf" org.apache.zookeeper.server.quorum.QuorumPeerMain
"E:\Mongodb-Redis-Nginx\zookeeper-3.4.6\bin\..\conf\zoo.cfg" start
錯誤: 找不到或無法載入主類 org.apache.zookeeper.server.quorum.QuorumPeerMain


E:\Mongodb-Redis-Nginx\zookeeper-3.4.6\bin>endlocal


配置zoo.cfg檔案
在conf目錄,複製zoo_sample.cfg,重名為zoo.cfg,重新啟動


又報錯了
E:\Mongodb-Redis-Nginx\zookeeper-3.4.6\bin>zkServer.cmd start


E:\Mongodb-Redis-Nginx\zookeeper-3.4.6\bin>java "-Dzookeeper.log.dir=E:\Mongodb-
Redis-Nginx\zookeeper-3.4.6\bin\.." "-Dzookeeper.root.logger=INFO,CONSOLE" -cp "
E:\Mongodb-Redis-Nginx\zookeeper-3.4.6\bin\..\build\classes;E:\Mongodb-Redis-Ngi
nx\zookeeper-3.4.6\bin\..\build\lib\*;E:\Mongodb-Redis-Nginx\zookeeper-3.4.6\bin
\..\*;E:\Mongodb-Redis-Nginx\zookeeper-3.4.6\bin\..\lib\*;E:\Mongodb-Redis-Nginx
\zookeeper-3.4.6\bin\..\conf" org.apache.zookeeper.server.quorum.QuorumPeerMain
"E:\Mongodb-Redis-Nginx\zookeeper-3.4.6\bin\..\conf\zoo.cfg" start
2015-12-01 10:14:27,347 [myid:] - INFO  [main:DatadirCleanupManager@78] - autopu
rge.snapRetainCount set to 3
2015-12-01 10:14:27,350 [myid:] - INFO  [main:DatadirCleanupManager@79] - autopu
rge.purgeInterval set to 0
2015-12-01 10:14:27,351 [myid:] - INFO  [main:DatadirCleanupManager@101] - Purge
 task is not scheduled.
2015-12-01 10:14:27,351 [myid:] - WARN  [main:QuorumPeerMain@113] - Either no co
nfig or no quorum defined in config, running  in standalone mode
2015-12-01 10:14:27,411 [myid:] - ERROR [main:ZooKeeperServerMain@54] - Invalid
arguments, exiting abnormally
java.lang.NumberFormatException: For input string: "E:\Mongodb-Redis-Nginx\zooke
eper-3.4.6\bin\..\conf\zoo.cfg"
        at java.lang.NumberFormatException.forInputString(Unknown Source)
        at java.lang.Integer.parseInt(Unknown Source)
        at java.lang.Integer.parseInt(Unknown Source)
        at org.apache.zookeeper.server.ServerConfig.parse(ServerConfig.java:60)
        at org.apache.zookeeper.server.ZooKeeperServerMain.initializeAndRun(ZooK
eeperServerMain.java:83)
        at org.apache.zookeeper.server.ZooKeeperServerMain.main(ZooKeeperServerM
ain.java:52)
        at org.apache.zookeeper.server.quorum.QuorumPeerMain.initializeAndRun(Qu
orumPeerMain.java:116)
        at org.apache.zookeeper.server.quorum.QuorumPeerMain.main(QuorumPeerMain
.java:78)
2015-12-01 10:14:27,415 [myid:] - INFO  [main:ZooKeeperServerMain@55] - Usage: Z
ooKeeperServerMain configfile | port datadir [ticktime] [maxcnxns]
Usage: ZooKeeperServerMain configfile | port datadir [ticktime] [maxcnxns]


媽蛋啊,網上找了很多資料,沒啥可用的。
後來,還是根據錯誤資訊“windows zookeeper啟動 java.lang.NumberFormatException”找到了1個答案。
zkServer.cmd 不要後面的“start”就正常啟動了。


cd /d E:\Mongodb-Redis-Nginx\zookeeper-3.4.6\bin
zkCli.cmd -server 127.0.0.1:2181
通過艱難的幾步,就正常啟動了。


Zookeeper啟動總結
1.實際專案用的是Linux,問題不大,本地開發學習用Windows,問題多多。
2.Zookeeper3.5.1-alpha,和本地JDK1.7,有衝突,無法正常啟動。
3.Zookeeper啟動,需要配置conf目錄下的zoo.cfg。複製-貼上-重新命名一次就可以了。
4.Windows下啟動,不需要帶“start”引數,直接zkServer.cmd,真是夠坑的。


zoo.cfg
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
dataDir=C:/zookeeper
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1




dataDir和clientPort應該是必須的。

一點感想:逃避or面對
在Windows下遇到問題的時候,其實我非常想立即轉到Linux下,就沒有這麼多屁事了。
但是,我一直意識到“人”比較喜歡逃避問題,就硬是忍著去正面解決了問題。
另外,是想把遇到的每一個問題都解決了,自己解決問題的能力,肯定是大幅度提高了。




參考資料
Zookeeper百度百科
http://baike.baidu.com/link?url=MsOQSGlqQA1BKF8v9OlB7k_jRi6lZm4fU9JeyP_pwA8yFa8mJopj3B7INfVVLRCIKkkEo2osXfBqnnSvuTq0p_


Zookeeper異常ConnectionLossException解決
http://www.sjsjw.com/kf_cloud/article/022572ABA018042.asp
E:\Mongodb-Redis-Nginx\zookeeper-3.5.1-alpha\bin


啟動Zookeeper時丟擲“Invalid arguments, exiting abnormally”錯誤資訊
http://www.bug315.com/article/156.htm

相關文章