文中包含的幾個部分的圖片沒法顯示,能夠到:http://note.youdao.com/share/?id=3651565d31662d82cd6e2d5abbd99749&type=note 查看全文,html
文中的各個部分都給出了引用連接,也能夠直接查看node
一、分佈式服務框架 Zookeeper -- 管理分佈式環境中的數據web
二、簡單的例子算法
三、ZooKeeper的實現機理數據庫
四、ZooKeeper的應用領域http://blog.csdn.net/y_xianjun/article/details/8190500apache
五、ZooKeeper分佈式鎖
緩存
六、ZooKeeper一致性協議-Zab
安全
七、ZooKeeper選舉和同步
服務器
一些有用的link:
http://www.cnblogs.com/mandela/archive/2011/08/09/2132122.html
http://blog.csdn.net/cnhzgb/article/details/7700026
一、分佈式服務框架 Zookeeper -- 管理分佈式環境中的數據
詳細內容參見 link:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/
分佈式服務框架 Zookeeper -- 管理分佈式環境中的數據
簡介: Zookeeper 分佈式服務框架是 Apache Hadoop 的一個子項目,它主要是用來解決分佈式應用中常常遇到的一些數據管理問題,如:統一命名服務、狀態同步服務、集羣管理、分佈式應用配置項的管理等。本文將從使用者角度詳細介紹 Zookeeper 的安裝和配置文件中各個配置項的意義,以及分析 Zookeeper 的典型的應用場景(配置文件的管理、集羣管理、同步鎖、Leader 選舉、隊列管理等),用 Java 實現它們並給出示例代碼。
二、簡單的例子:
link:http://www.oschina.net/p/zookeeper
假設咱們咱們有個20個搜索引擎的服務器(每一個負責總索引中的一部分的搜索任務)和一個 總服務器(負責向這20個搜索引擎的服務器發出搜索請求併合並結果集),一個備用的總服務器(負責當總服務器宕機時替換總服務器),一個web的 cgi(向總服務器發出搜索請求).搜索引擎的服務器中的15個服務器如今提供搜索服務,5個服務器正在生成索引.這20個搜索引擎的服務器常常要讓正在 提供搜索服務的服務器中止提供服務開始生成索引,或生成索引的服務器已經把索引生成完成能夠提供搜索服務了.使用Zookeeper能夠保證總服務器自動 感知有多少提供搜索引擎的服務器並向這些服務器發出搜索請求,備用的總服務器宕機時自動啓用備用的總服務器,web的cgi可以自動地獲知總服務器的網絡 地址變化.這些又如何作到呢?
- 提供搜索引擎的服務器都在Zookeeper中建立znode,zk.create("/search/nodes/node1",
"hostname".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateFlags.EPHEMERAL); - 總服務器能夠從Zookeeper中獲取一個znode的子節點的列表,zk.getChildren("/search/nodes", true);
- 總服務器遍歷這些子節點,並獲取子節點的數據生成提供搜索引擎的服務器列表.
- 當總服務器接收到子節點改變的事件信息,從新返回第二步.
- 總服務器在Zookeeper中建立節點,zk.create("/search/master", "hostname".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateFlags.EPHEMERAL);
- 備用的總服務器監控Zookeeper中的"/search/master"節點.當這個znode的節點數據改變時,把本身啓動變成總服務器,並把本身的網絡地址數據放進這個節點.
- web的cgi從Zookeeper中"/search/master"節點獲取總服務器的網絡地址數據並向其發送搜索請求.
- web的cgi監控Zookeeper中的"/search/master"節點,當這個znode的節點數據改變時,從這個節點獲取總服務器的網絡地址數據,並改變當前的總服務器的網絡地址.
三、ZooKeeper的實現機理
link:http://bbs.zoomla.cn/archiver/showtopic-15086.aspx
ZooKeeper的實現機理是我看過的開源框架中最複雜的,它的解決是分佈式環境中的一致性問題,這個場景也決定了其實現的複雜性。看了兩三天的源碼仍是有些摸不着頭腦,有些超出了個人能力,不過經過看文檔和其餘高人寫的文章大體清楚它的原理和基本結構。
1)ZooKeeper的基本原理
ZooKeeper是以Fast Paxos算法爲基礎的(不是zab?),在前一篇blog中大體介紹了一下paxos,而沒有提到的是paxos存在活鎖的問題,也就是當有多個proposer交錯提交時,有可能互相排斥導致沒有一個proposer能提交成功,而Fast Paxos做了一些優化,經過選舉產生一個leader,只有leader才能提交propose,具體算法可見Fast Paxos。所以,要想弄得ZooKeeper首先得對Fast Paxos有所瞭解。
2)ZooKeeper的基本運轉流程
ZooKeeper主要存在如下兩個流程:
選舉Leader
同步數據
選舉Leader過程當中算法有不少,但要達到的選舉標準是一致的:
Leader要具備最高的zxid
集羣中大多數的機器獲得響應並follow選出的Leader
同步數據這個流程是ZooKeeper的精髓所在,而且就是Fast Paxos算法的具體實現。一個牛人畫了一個ZooKeeper數據流動圖,比較直觀地描述了ZooKeeper是如何同步數據的。
以上兩個核心流程我暫時還不能悟透其中的精髓,這也和我尚未徹底理解Fast Paxos算法有關,有待後續深刻學習
四、ZooKeeper的應用領域
Tim在blog中提到了Paxos所能應用的幾個主要場景,包括database replication、naming service、config配置管理、access control list等等,這也是ZooKeeper能夠應用的幾個主要場景。此外,ZooKeeper官方文檔中提到了幾個更爲基礎的分佈式應用,這也算是ZooKeeper的妙用吧
1)分佈式Barrier
Barrier是一種控制和協調多個任務觸發次序的機制,簡單說來就是搞個閘門把欲執行的任務給攔住,等全部任務都處於能夠執行的狀態時,才放開閘門。它的機理能夠見下圖所示
:
在單機上JDK提供了CyclicBarrier這個類來實現這個機制,但在分佈式環境中JDK就無能爲力了。在分佈式裏實現Barrer須要高一致性作保障,所以ZooKeeper能夠派上用場,所採取的方案就是用一個Node做爲Barrer的實體,須要被Barrer的任務經過調用exists()檢測這個Node的存在,當須要打開Barrier的時候,刪掉這個Node,ZooKeeper的watch機制會通知到各個任務能夠開始執行。
2)分佈式Queue
與Barrier相似分佈式環境中實現Queue也須要高一致性作保障,ZooKeeper提供了一個種簡單的方式,ZooKeeper經過一個Node來維護Queue的實體,用其children來存儲Queue的內容,而且ZooKeeper的create方法中提供了順序遞增的模式,會自動地在name後面加上一個遞增的數字來插入新元素。能夠用其children來構建一個queue的數據結構,offer的時候使用create,take的時候按照children的順序刪除第一個便可。ZooKeeper保障了各個server上數據是一致的,所以也就實現了一個分佈式Queue。take和offer的實例代碼以下所示
:
3)分佈式lock
利用ZooKeeper實現分佈式lock,主要是經過一個Node來表明一個Lock,當一個client去拿鎖的時候,會在這個Node下建立一個自增序列的child,而後經過getChildren()方式來check建立的child是否是最靠前的,若是是則拿到鎖,不然就調用exist()來check第二靠前的child,並加上watch來監視。當拿到鎖的child執行完後歸還鎖,歸還鎖僅僅須要刪除本身建立的child,這時watch機制會通知到全部沒有拿到鎖的client,這些child就會根據前面所講的拿鎖規則來競爭鎖。
五、ZooKeeper分佈式鎖
(a)基於zookeeper實現的分佈式鎖
zookeeper是hadoop下面的一個子項目, 用來協調跟hadoop相關的一些分佈式的框架, 如hadoop, hive, pig等, 其實他們都是動物, 因此叫zookeeper(本人歪歪).
zookeeper實際上是集羣中每一個節點都維護着一棵相同的樹, 樹的結構跟linux的目錄結構的概念差很少, 以/爲跟節點, 下邊能夠擴展任意的節點和葉子節點, 每一個節點均可以寫入數據. 基於zookeeper的分佈式鎖的實現, 實際上是得益於zookeeper同步文件的強大性, 咱們相信每時每刻咱們訪問zookeeper的樹時, 相同節點返回的數據都是一致的. 這要靠zookeeper內部的一些算法來實現. 特別是leader的選舉算法, 這裏就不說了, 感興趣的話能夠去搜索一下看看.
咱們知道了zookeeper集羣的每一個節點的數據都是一致的, 那麼咱們能夠經過這些節點來做爲鎖的標誌.
首先給鎖設置一下API, 至少要包含, lock(鎖住), unlock(解鎖), isLocked(是否鎖住)三個方法
而後咱們能夠建立一個工廠(LockFactory), 用來專門生產鎖.
鎖的建立過程以下描述:
前提:每一個鎖都須要一個路徑來指定(如:/jiacheo/lock)
1.根據指定的路徑, 查找zookeeper集羣下的這個節點是否存在.(說明已經有鎖了)
2. 若是存在, 根據查詢者的一些特徵數據(如ip地址/hostname), 當前的鎖是否是查詢者的
3. 若是不是查詢者的鎖, 則返回null, 說明建立鎖失敗
4. 若是是查詢者的鎖, 則把這個鎖返回給查詢者
5. 若是這個節點不存在, 說明當前沒有鎖, 那麼建立一個臨時節點, 並將查詢者的特徵信息寫入這個節點的數據中, 而後返回這個鎖.
根據以上5部, 一個分佈式的鎖就能夠建立了.
建立的鎖有三種狀態:
1. 建立失敗(null), 說明該鎖被其餘查詢者使用了.’
2. 建立成功, 但當前沒有鎖住(unlocked), 可使用
3. 建立成功, 但當前已經鎖住(locked)了, 不能繼續加鎖.
如圖, 若是咱們getLock(「/jiacheo/lock1″,」192.168.0.100″), 想要獲取/jiacheo/lock1這個鎖的話, 咱們先判斷這個節點是否存在, 存在的話獲取他的數據(data), 而後經過解析data, 咱們能夠知道這個節點是否是咱們查詢者建立的(經過ip地址寫入節點數據中), 而後就能夠返回一個鎖了.
正確實現一個分佈式鎖是一件很是棘手的事情,由於很難對全部類型的故障進行正確的處理,ZooKeeper帶有一個Java語言編寫的生產級別的鎖實現,名爲WriteLock,客戶端能夠方便的使用它。
(b)zookeeper分佈式鎖
link:http://www.searchtb.com/2011/01/zookeeper-research.html
擁有了zookeeper如此強大的分佈式協做系統後,咱們能夠很容易的實現大量的分佈式應用,包括了分佈式鎖,分佈式隊列,分佈式Barrier,雙階段提交等等. 這些應用能夠幫咱們改進不少複雜系統的協做方式,將這些系統的實現變得更加優雅而高效.鑑於篇幅,本文僅介紹分佈式鎖的實現.
利用了前文提到的sequence nodes能夠很是容易的實現分佈式鎖. 實現分佈式鎖的基本步驟以下(這些步驟須要在全部須要鎖的客戶端執行):
分佈式鎖在zookeeper的源代碼中已經有實現,能夠參考org.apache.zookeeper.recipes.lock
六、ZooKeeper一致性協議-Zab
link:http://blog.csdn.net/chen77716/article/details/7309915
Zookeeper使用了一種稱爲Zab(Zookeeper Atomic Broadcast)的協議做爲其一致性複製的核心,據其做者說這是一種新發算法,其特色是充分考慮了Yahoo的具體狀況:高吞吐量、低延遲、健壯、簡單,但不過度要求其擴展性。下面將展現一些該協議的核心內容:
另,本文僅討論Zookeeper使用的一致性協議而非討論其源碼實現
Zookeeper的實現是有Client、Server構成,Server端提供了一個一致性複製、存儲服務,Client端會提供一些具體的語義,好比分佈式鎖、選舉算法、分佈式互斥等。從存儲內容來講,Server端更多的是存儲一些數據的狀態,而非數據內容自己,所以Zookeeper能夠做爲一個小文件系統使用。數據狀態的存儲量相對不大,徹底能夠所有加載到內存中,從而極大地消除了通訊延遲。
Server能夠Crash後重啓,考慮到容錯性,Server必須「記住」以前的數據狀態,所以數據須要持久化,但吞吐量很高時,磁盤的IO便成爲系統瓶頸,其解決辦法是使用緩存,把隨機寫變爲連續寫。
考慮到Zookeeper主要操做數據的狀態,爲了保證狀態的一致性,Zookeeper提出了兩個安全屬性(Safety Property)
- 全序(Total order):若是消息a在消息b以前發送,則全部Server應該看到相同的結果
- 因果順序(Causal order):若是消息a在消息b以前發生(a致使了b),並被一塊兒發送,則a始終在b以前被執行。
- 由於只有一個Leader,Leader提交到Follower的請求必定會被接受(沒有其餘Leader干擾)
- 不須要全部的Follower都響應成功,只要一個多數派便可
2. Leader Election
- 老Leader在COMMIT前Crash(已經提交到本地)
- 老Leader在COMMIT後Crash,但有部分Follower接收到了Commit請求
3. Zab與Paxos
Because multiple leaders can propose a value for a given instance two problems arise. First, proposals can conflict. Paxos uses ballots to detect and resolve conflicting proposals. Second, it is not enough to know that a given instance number has been committed, processes must also be able to figure out which value has been committed.
- 以前的Phase2
- Learn
4.結束
- A simple totally ordered broadcast protocol
- paxos
七、ZooKeeper選舉和同步
http://stblog.baidu-tech.com/?p=1164
用於分佈式下一致性相關問題的解決方案。能夠理解爲由集羣組成的可靠的單master。可將傳統方案中的master使用zookeeper代替,且不用擔憂單點問題。
應用場景:樹狀結構的命名服務、節點數據變動的消息通知、分佈式共享鎖、配置數據的集中存放、集羣中節點機器的狀態管理及狀態變動通知
zookeeper實現分佈式鎖:經過zookeeper的節點狀態進行條件判斷,若是不知足,則在客戶端本地加鎖等待Object.wait()。利用zookeeper的實時通知機制,當zookeeper的節點知足條件狀態時,客戶端會同步得到通知,而後在本地解鎖Object.notifyAll()。從而實現了分佈式加鎖、阻塞、解鎖。
三類角色: leader(處理寫請求,單點)、follower(處理客戶端請求,參與投票)、observer(不投票,只處理客戶端請求)
恢復模式:服務重啓或者leader宕機後,經過paxos算法,從follower中從新選出leader,並以leader爲準,進行數據同步。此時服務不可用。
paxos選舉算法:
一、每次選舉,都是針對某個txid(transaction id)進行。
二、每一個follower首先廣播詢問,獲取其它全部server的txid、提議value,txid必須相同,value存儲到提議列表中
三、follower從提議列表中獲取value,若是這個value被大於一半的follower支持,則直接使用此value,不然,繼續發出廣播詢問。而且將此value做爲回答其它follower輪訓的提議。
四、循環執行3,直到收斂
paxos的精髓:解決了集羣中,非全聯通狀況下的一致性問題。對於正常全聯通狀況,每臺機器只須要廣播獲取其它各臺機器的數據,而後比較獲取最大值便可。這樣各個節點獲得的結論應該是同樣的。問題在於,某些節點之間是不聯通的。因而某個節點沒法獲知全局數據,只能經過paxos中循環投票,收斂至全局最優解。
同步流程:選舉完成後,各個follower向leader發送同步請求,帶上本身的最大zxid。leader經過zxid肯定同步點,將這以後的commit log交給follower進行同步。全部節點都保存一份系統狀態數據,非強一致(getData不保證最新數據,能夠先sync一下保證數據的同步狀態),有同步延時。
多節點可讀可寫,部分節點延時同步,最終一致性。follower和observer負責監聽客戶請求和處理讀請求。對於全部寫請求,都一概轉發至leader進行選舉和數據同步。observer不參與投票,只作數據同步,提升寫請求的效率。