第五十三章:Zookeeper分散式應用程式協調服務
ZooKeeper 到底是個什麼東西?
ZooKeeper 作為 Dubbo 的註冊中心
Zookeeper 是 Hadoop 生態系統的一員。
構建 Zookeeper 叢集的時候,使用的伺服器最好是奇數臺。
ZooKeeper的基本運轉流程:
1、選舉Leader。
2、同步資料。
3、選舉Leader過程中演算法有很多,但要達到的選舉標準是一致的。
4、Leader要具有最高的執行ID,類似root許可權。
5、叢集中大多數的機器得到響應並接受選出的Leader。
Zookeeper的作用
樹形目錄結構
非同步通知機制
Zookeeper安裝
確認JDK
[[email protected] ~]# java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
Zookeeper解壓
第一步:上傳zookeeper-3.4.9.tar.gz到/opt目錄
第二步:解壓
tar -zxvf /opt/zookeeper-3.4.9.tar.gz
第三步:進入解壓目錄下的conf目錄
cd /opt/zookeeper-3.4.9/conf
第四步:複製得到配置檔案
cp zoo_sample.cfg zoo.cfg
第五步:建立資料目錄
mkdir /opt/zookeeper-3.4.9/data
第六步:修改zoo.cfg配置檔案
dataDir=/opt/zookeeper-3.4.9/data
常用四字命令(運維人員常用)
Are your ok? I
ruok:測試服務是否處於正確狀態。如果確實如此,那麼服務返回“imok ”,否則不做任何響應
stat:輸出關於效能和連線的客戶端的列表
conf:輸出相關服務配置的詳細資訊
cons:列出所有連線到伺服器的客戶端的完全的連線 /會話的詳細資訊。包括“接受 / 傳送”的包數量、會話id 、操作延遲、最後的操作執行等等資訊
dump:列出未經處理的會話和臨時節點
envi:輸出關於服務環境的詳細資訊(區別於conf命令)
reqs:列出未經處理的請求
wchs:列出伺服器watch的詳細資訊
wchc:通過session列出伺服器watch的詳細資訊,它的輸出是一個與watch相關的會話的列表
wchp:通過路徑列出伺服器 watch的詳細資訊。它輸出一個與 session相關的路徑
節點狀態
czxid:引起這個znode建立的zxid,建立節點的事務的czxid(create ZooKeeper Transaction Id)
ctime:znode被建立的毫秒數(從1970年開始)
mzxid:znode最後更新的zxid
mtime:znode最後修改的毫秒數(從1970年開始)
pZxid:znode最後更新的子節點zxid
cversion:znode子節點變化號,znode子節點修改次數
dataversion:znode資料變化號,也就是版本號
aclVersion:znode訪問控制列表的變化號
ephemeralOwner:如果是臨時節點,這個是znode擁有者的session id。如果不是臨時節點則是0。
dataLength:znode的資料長度
numChildren:znode子節點數量
版本號的作用
Zookeeper裡面的版本號和我們理解的版本號不同,它表示的是對資料節點的內容、子節點列表或者ACL資訊的修改次數。節點建立時dataversion、aclversion,cversion都為0,每次修改響應內容其對應的版本號加1。
這個版本號的用途就和分散式場景的一個鎖概念有關。比如演出售票中的一個座位,顯然每個場次中的每個座位都只有一個,不可能賣出2次。如果A下單的時候顯示可售,他想買,那麼為了保證他可以下單成功,此時別人就不能買。這時候就需要有一種機制來保證同一時刻只能有一個人去修改該座位的庫存。這就用到了鎖。鎖有悲觀鎖和樂觀鎖。
-
悲觀鎖:它會假定所有不同事務的處理一定會出現干擾,資料庫中最嚴格的併發控制策略,如果一個事務A正在對資料處理,那麼在整個事務過程中,其他事務都無法對這個資料進行更新操作,直到A事務釋放了這個鎖。
-
樂觀鎖:它假定所有不同事務的處理不一定會出現干擾,所以在大部分操作裡不許加鎖,但是既然是併發就有出現干擾的可能,如何解決衝突就是一個問題。在樂觀鎖中當你在提交更新請求之前,你要先去檢查你讀取這個資料之後該資料是否發生了變化,如果有那麼你此次的提交就要放棄,如果沒有就可以提交。
Zookeeper中的版本號就是樂觀鎖,你修改節點資料之前會讀取這個資料並記錄該資料版本號,當你需要更新時會攜帶這個版本號去提交,如果你此時攜帶的版本號(就是你上次讀取出來的)和當前節點的版本號相同則說明該資料沒有被修改過,那麼你的提交就會成功,如果提交失敗說明該資料在你讀取之後和提交之前這段時間內被修改了。
這裡通過set命令並攜帶版本號提交更新,版本號相同更新就會成功。
Zookeeper伺服器客戶端操作
啟動伺服器
/opt/zookeeper-3.4.9/bin/zkServer.sh start
檢視伺服器狀態
[[email protected] bin]# /opt/zookeeper-3.4.9/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.4.9/bin/../conf/zoo.cfg
Mode: standalone
日誌檔案
zookeeper.out
停止伺服器
/opt/zookeeper-3.4.9/bin/zkServer.sh stop
使用客戶端登入伺服器,登入之前要啟動伺服器
/opt/zookeeper-3.4.9/bin/zkCli.sh -server 192.168.200.100:2181
如果是本機和預設2181埠號-server後面部分可以省略
Zookeeper常用命令
ZooKeeper伺服器與客戶端
在/opt/zookeeper-3.4.9/bin目錄下
啟動伺服器:./zkServer.sh start
停止伺服器:./zkServer.sh stop
在/opt/zookeeper-3.4.9/bin目錄下
啟動客戶端:./zkCli.sh
退出客戶端:[zk: localhost:2181(CONNECTED) 6] quit
檢視節點的子節點:ls /zookeeper/quota
獲取指定節點的值:get /zookeeper
設定指定節點的值:set /zookeeper hello
建立節點:create /fruit water
刪除節點:delete /fruit/apple只能刪除空節點
刪除節點rmr /fruit空節點和非空節點都可以刪除
-s:含有序列
建立有序列的節點:create -s /fruit/apple red
apple後面的0000000000就是序列
-e:臨時(重啟或者超時消失)
建立臨時節點:create -e /fruit/orange yellow在重啟後再檢視就沒有這個節點了
通過-e和-s可以把節點分為四個象限,四個情況的節點
Zookeeper叢集搭建
叢集中伺服器間通訊時用到3種埠號
- 客戶端訪問埠號
- 叢集中伺服器間資料同步埠號
- 叢集中follower伺服器選舉leader伺服器埠號
叢集中伺服器編號
編號形式:1、2、3、……
指定編號:資料目錄/myid檔案中寫入編號
編號和埠號在配置檔案中的配置方式
客戶端埠號
clientPort
編號和埠號
在配置檔案末尾指定如下格式:
server.編號=IP地址:資料同步埠號:選舉埠號
server.1=127.0.0.1:6001:6002
server.2=127.0.0.1:7001:7002
server.3=127.0.0.1:8001:8002
zkone步驟
建立目錄
mkdir /opt/cluster_zk
重新解壓Zookeeper
tar -zxvf /opt/zookeeper-3.4.9.tar.gz -C /opt/cluster_zk/
進入叢集目錄
cd /opt/cluster_zk
複製解壓目錄
cp -r zookeeper-3.4.9/ zkone
在zkone中建立data目錄
mkdir /opt/cluster_zk/zkone/data
建立myid檔案
vim /opt/cluster_zk/zkone/data/myid
進入zkone的conf目錄
cd /opt/cluster_zk/zkone/conf/
複製得到zoo.cfg
cp zoo_sample.cfg zoo.cfg
編輯zoo.cfg
dataDir=/opt/cluster_zk/zkone/data/
clientPort=6000
server.1=127.0.0.1:6001:6002
server.2=127.0.0.1:7001:7002
server.3=127.0.0.1:8001:8002
zktwo步驟
複製zkone
cp -r /opt/cluster_zk/zkone/ /opt/cluster_zk/zktwo
將myid改成2
vim /opt/cluster_zk/zktwo/data/myid
修改配置檔案
vim /opt/cluster_zk/zktwo/conf/zoo.cfg
dataDir=/opt/cluster_zk/zktwo/data/
clientPort=7000
三個客戶端登入三個伺服器
/opt/cluster_zk/zkone/bin/zkCli.sh -server 127.0.0.1:6000
/opt/cluster_zk/zktwo/bin/zkCli.sh -server 127.0.0.1:7000
/opt/cluster_zk/zkthree/bin/zkCli.sh -server 127.0.0.1:8000
可以看到現在zktwo是leader,zkone和zkthree是follower
如果leader伺服器不能工作了,並不影響zkone和zkthree,因為zkone和zkthree二個伺服器會選舉出一個leader,三個伺服器任何一個伺服器不能工作,其他伺服器都可以正常執行,並且可以保證資料同步。
叢集數量為什麼是單數?
zookeeper有這樣一個特性:叢集中只要有過半的機器是正常工作的,那麼整個叢集對外就是可用的。也就是說如果有2個zookeeper,那麼只要有1個死了zookeeper就不能用了,因為1沒有過半,所以2個zookeeper的死亡容忍度為0;同理,要是有3個zookeeper,一個死了,還剩下2個正常的,過半了,所以3個zookeeper的容忍度為1;同理你多列舉幾個:2->0;3->1;4->1;5->2;6->2會發現一個規律,2n和2n-1的容忍度是一樣的,都是n-1,所以為了更加高效,何必增加那一個不必要的zookeeper呢。