一、什么是zookeeper
ZooKeeper是一個分布式的,開放源碼的分布式應用程序協調服務,是Google的Chubby一個開源的實現,是Hadoop和Hbase的重要組件。它是一個為分布式應用提供一致性服務的軟件,提供的功能包括:配置維護、域名服務、分布式同步、組服務等。
簡單來說,zookeeper = 文件系統 + 監聽通知機制
二、文件系統
zookeeper有着與linux類似的文件系統,區別是,linux的目錄就是目錄,文件就是文件。而zookeeper中只有一個znode概念,本身可以做為“文件”存儲一定的數據,又可以做為“目錄”存在。
/* +---+ |/ | +-+-+ | | +------+ +--|config| | +--+---+ | | +-----+ | +-----|ip | | | +-----+ | | +-----+ | +-----|port | | +-----+ | | +------+ +--|apps | +--+---+ | +-----+ +-----|app1 | | +-----+ | +-----+ +-----|app2 | +-----+ */
znode共分為四種:
1、PERSISTENT-持久化目錄節點
此節點在客戶端與zookeeper斷開連接之后,依然存在,需要主動刪除。
2、PERSISTENT_SEQUENTIAL-持久化順序編號目錄節點
同樣地,此類節點也是需要主動刪除,不會隨着客戶端的斷開連接而刪除。與PERSISTENT不同的是,zookeeper會給此類節點進行編號。如:app0000003362。0000003362為zookeeper給的編號,自動遞增。由於此編號是一個有符號整形(4字節),當它超過2147483647時,將會溢出。
3、EPHEMERAL-臨時目錄節點
與PERSISTENT不同的是,此類節點會在客戶端與zookeeper斷開連接之后被刪除。由於其生命周期與連接有關,所以其不可以有子節點。
4、EPHEMERAL_SEQUENTIAL-臨時順序編號目錄節點
與PERSISTENT_SEQUENTIAL類似擁有zookeeper的自動編號,區別是會在客戶端與zookeeper斷開連接之后被刪除,且不可以有子節點。
值得注意的是,同路徑下,同名znode只能被創建一次。且每個znode最多只可以存儲1M數據。
三、監聽通知機制
客戶端注冊監聽它關心的目錄節點,當目錄節點發生變化(數據改變、被刪除、子目錄節點增加刪除)時,zookeeper會通知客戶端。
四、 實際應用
基於文件系統與監聽通知機制,zookeeper有諸多應用場景。
1、命名服務(基於文件系統)
名稱在所有計算機系統中起着重要的作用,它們用來共享資源,唯一標識實體,指向位置等。命名的對象可以有多種類型,而且可被一些不同的服務來訪問。命名服務器可根據給定的名字來進行資源或對象的地址定位,並獲取有關的屬性信息。(百度百科)
簡單來說,就是通過名字來獲取對應資源/服務地址。利用znode的唯一性,可以創建一個全局節點,將對應的信息記錄在znode中。需要使用對應資源的服務直接獲取此節點的信息即可。
2、配置管理(基於文件系統與監聽通知機制)
服務有自己的配置,而同一個服務可多點部署。如果采用配置文件的形式,在修改配置的時候,需要同步文件至所有機器,再通知程度動態加載,或者直接重啟。若存在這種情況,整個后台存在一份共享配置(路由信息等),而在一次修改中,只需要同步到某個服務(擴容、增加下游節點等)。長久之后,會出現不同服務的配置不同的情況(雖然對於他們自己所使用的部門是最新的)。此時可以通過配置中心來解決此類問題,所有配置都從配置中心中讀取,統一管理。
自己實現配置中心畢竟是有代價。而利用zookeeper,完全可以實現配置中心的功能。將對應信息存儲到對應的znode中,服務只需要監聽自己關心的配置(znode)。一旦znode發生變化,利用watcher通知所有監聽此znode的客戶端(對於zookeeper而言,服務是他的客戶端),從而更新配置。
3、集群管理(基於文件系統與監聽通知機制)
當一個服務部署成集群的時候,就會有兩個問題:機器的加入與退出,master的選舉。可以在zookeeper里創建一個持久化znode A,然后讓本集群所有的服務在A下創建臨時znode B,需要知道此集群的服務監聽A。當新機器加入時,創建新的B,舊機器離開(宕機、縮容等)時,自動刪除B。不管是創建,還是刪除,A都發生了變化,利用watcher通知所有監聽者。於是大家都知道本集群的情況了。
對於master選舉,同樣也可以在zookeeper里創建一個持久化znode C,而后所有服務在C里創建臨時順序編號目錄節點。每次選擇編號最大或者最小的做為master。由於臨時順序編號目錄節點的編號是自增的,若選擇最大的做為master,當有新機器加入時,新機器就會成為master。而選擇最小編號做為master,只要其不退出(znode沒刪),就不會產生切換master的情況,對數據來說是最安全的。
4、分布式鎖(基於文件系統與監聽通知機制)
有一個程序,有兩個線程,都對相同變量進行100w次++操作。未加鎖的情況下,得到的結果並不是200w。同樣,在一個集群中,如果同時修改相同資源,也會出現相互覆蓋的情況。此時,需要使用到分布式鎖來處理此類問題。要開始修改此資源之前,先獲取鎖。獲取成功之后才可以進行修改操作。由於zookeeper中,znode的唯一性,可以利用它來實現分布式鎖服務。需要獲取鎖時,在指定路徑下創建znode(非自動編號),需要釋放時,刪除此znode。若創建失敗,則認為當前已有其它服務搶到了鎖。
若創建的是非自動編號的znode,會有一個問題。每次都是集群中所有服務競爭同一把鎖,會出現一個服務搶到多次,而其它服務一次都不成功的情況。此時可以將其修改為自動編號的znode,並監聽對應父znode。每次需要鎖時,創建一個自動編號的znode。若自己創建的znode在所有znode中編號最小,則認為自己搶到了鎖。解鎖(刪除znode)之后,又會通知整個集群。這樣不僅實現了分布式鎖,而且人人有份,有序進行。
五、參考鏈接
https://blog.csdn.net/u010963948/article/details/83381757
https://www.cnblogs.com/lfs2640666960/p/11104838.html
https://blog.csdn.net/java_66666/article/details/81015302
https://blog.csdn.net/chunqiu3351/article/details/100762270
https://www.jianshu.com/p/d4fb16fafc2e
http://zookeeper.apache.org/doc/r3.3.3/zookeeperProgrammers.html