1. 程式人生 > >ZooKeeper的典型應用場景之名稱空間。

ZooKeeper的典型應用場景之名稱空間。

        命名服務(Name Service)也是分散式系統中比較常見的一類場景,在《Java網路高階程式設計》一書中提到,命名服務是分散式系統最基本的公共服務之一。在分散式系統中,被命名的實體通常可以是叢集中的機器、提供的服務地址或遠端物件等——這些我們都可以統稱他們為名字(Name),其中較為常見的就是一些分散式服務框架(如RPC、RMI)中的服務地址列表,通過使用命名服務,客戶端應用能夠根據指定名字來獲取資源的實體、服務地址和提供者的資訊等。

        Java語言中的JNDI便是一種典型的命名服務。JNDI是Java命名與目錄介面(Java Naming and Directory Interface)的縮寫,是J2EE體系中重要的規範之一,標準的J2EE容器都提供了對JNDI規範的實現。因此,在實際開發中,開發人員常常使用應用伺服器自帶的JNDI實現來完成資料來源的配置與管理——使用JNDI方式後,開發人員可以完全不需要關心與資料庫相關的任何資訊,包括資料庫型別、JDBC驅動型別以及資料庫賬戶等。

         ZooKeeper提供的命名服務功能與JNDI技術有相似的地方,都能夠幫助應用系統通過一個資源引起的方式來實現對資源的定位與使用。另外,廣義上命名服務的資源定位都不是真正意義的實體資源——在分散式環境中,上層應用僅僅需要一個全域性唯一的名字,類似於資料庫中的唯一主鍵。下面我們來看看如何使用ZooKeeper來實現一套分散式全域性唯一ID的分配機制。

        所謂ID,就是一個能夠唯一標識某個物件的識別符號。在我們熟悉的關係型資料庫中,各個表都需要一個主鍵來唯一標識每條資料庫記錄,這個主鍵就是這樣的唯一ID。在過去的單庫單表型系統中,通常可以使用資料庫欄位自帶的auto_increment屬性來自動為每條資料庫記錄生成一個唯一的ID,資料庫會保證生成的這個ID在全域性唯一。但是隨著資料庫資料規模的不斷增大,分庫分表隨之出現,而auto_increment屬性僅能針對單一表中的記錄自動生成ID,因此在這種情況下,就無法再依靠資料庫的auto_increment屬性來唯一標識一條記錄了。於是,我們必須尋求一種能夠在分散式環境下生成全域性唯一ID的方法。

        一說起全域性唯一ID,相信讀者都會聯想到UUID。沒錯,UUID是通用唯一識別碼(Universally Unique Identifier)的簡稱,是一種在分散式系統中廣泛使用的用於唯一標識元素的標準,最典型的實現是GUID(Globally Unique Identifier,全域性唯一識別符號),主流ORM框架Hibernate有對UUID的直接支援。

        確實,UUID是一個非常不錯的全域性唯一ID生成方式,能夠非常簡便的保證分散式環境中的唯一性。一個標準的UUID是一個包含32位字元和4個短線的字串,例如“e79f1357-f260-46ff-a32d-53a086c57ade”。UUID的優勢自然不必多說,我們重點來看看他的缺陷。

  • 長度過長

UUID最大的問題就在於生成的字串過長。顯然,和資料庫中的INT型別相比,儲存一個UUID需要花費更多的空間。

  • 含義不明

上面我們已經看到一個典型的UUID是類似於“e79f1357-f260-46ff-a32d-53a086c57ade”的一個字串。根據這個字串,開發人員從字面上基本看不出任何其表達的含義,這將會大大影響問題排查和開發除錯的效率。

        接下來,我們結合一個分散式任務排程系統來看看如何使用ZooKeeper來實現這類全域性唯一ID的生成。

        通過呼叫ZooKeeper節點建立的API介面可以建立一個順序節點,並且在API返回值中會返回這個節點的完整名字。利用這個特性,我們就可以藉助ZooKeeper來生成全域性唯一的ID了,如下圖所示。

        結合 上圖,我們來講解對於一個任務列表的主鍵,使用ZooKeeper生成唯一ID的基本步驟。

  1. 所有客戶端都會根據自己的任務型別,在指定型別的任務下面通過呼叫create()介面來建立一個順序節點,例如建立“job-”節點。
  2. 節點建立完畢後,create()介面會返回一個完整的節點名,例如“job-0000000003”。
  3. 客戶端拿到這個返回值後,拼接上type型別,例如“type2-job-0000000003”,這就可以作為一個全域性唯一的ID了。
        在ZooKeeper中,每一個數據節點都能夠維護一份子節點的順序順列,當客戶端對其建立一個順序子節點的時候ZooKeeper會自動以後綴的形式在其子節點上新增一個序號,在這個場景中就是利用了ZooKeeper的這個特性。