ZooKeeper系列文章:http://www.javashuo.com/article/p-waqydwdc-bt.htmlhtml
在比較老的ZooKeeper版本中,只有兩種角色:leader和follower。後來引入了一種新角色Observer,Observer角色除了不能投票(以及和投票相關的能力)外,其它和follower功能同樣。node
因此,在ZooKeeper中:數據庫
ZooKeeper集羣中的每一個server都能爲客戶端提供讀、寫服務。bash
對於客戶端的讀請求,server會直接從它本地的內存數據庫中取出數據返回給客戶端,這個過程不涉及其它任何操做,也不會聯繫leader。服務器
對於客戶端的寫請求,由於寫操做會修改znode的數據、狀態,因此必需要在ZooKeeper集羣中進行協調。處理過程以下:性能
下面是ZooKeeper集羣處理寫請求過程的一個簡圖:日誌
當ZooKeeper集羣中follower的數量不少時,投票過程會成爲一個性能瓶頸,爲了解決投票形成的壓力,因而出現了observer角色。code
observer角色不參與投票,它只是投票結果的"聽衆",除此以外,它和follower徹底同樣,例如能接受讀、寫請求。就這一個特色,讓整個ZooKeeper集羣性能大大改善。server
和follower同樣,當observer收到客戶端的讀請求時,會直接從內存數據庫中取出數據返回給客戶端。htm
對於寫請求,當寫請求發送到某server上後,不管這個節點是follower仍是observer,都會將它發送給leader。而後leader組織投票過程,全部server都收到這個proposal(包括observer,由於proposal是廣播出去的),可是leader和follower以及observer經過配置文件,都知道本身是否是observer以及誰是observer。本身是observer的server不參與投票。當leader收集完投票後,將那些observer的server去掉,在剩下的server中計算大多數,若是投票結果達到了大多數,此次寫事務就成功,因而leader通知全部的節點(包括observer),讓它們將事務寫入事務日誌,並提交。
observer角色除了減輕了投票的壓力,還帶來了幾個額外的優勢。
1.提升了伸縮性。
伸縮性指的是經過添加服務器來負載請求,從而提升整個集羣處理請求的能力。也就是"一頭牛拉不動了,找更多牛來拉"。
在出現Observer以前,ZooKeeper集羣的伸縮性由follower來實現。雖然對於讀寫操做來講,follower是"無狀態"的,這使得添加新的follower到集羣(或者從集羣中減小follower)很方便,能提升ZooKeeper集羣負載能力。可是,對於投票來講,follower是有狀態的,增、減follower的數量,都直接影響投票結果,特別是follower的數量越多,投票過程的性能就越差。
而observer不管是讀寫請求仍是投票,都是無狀態的,增、減observer的數量不會影響投票結果。這樣就可讓一部分server做爲follower參與投票,另外一部分做爲observer單純地提供讀寫服務。這使得ZooKeeper的伸縮性大大提升。
2.部署跨地區的ZooKeeper數據中心更方便。
observer能直接從本地內存數據庫中取出數據來響應讀請求,因此提升了讀的吞吐量。對於寫請求,雖然它要發送給leader並接受leader的通知,但相比於投票過程當中傳遞的信息,它的數據量很小,因此即便在廣域網也能有很好的性能。
實際上,不少跨機房、跨地區的數據中心就是經過observer來實現的。
要配置observer,只需稍微修改一下配置文件便可。
首先,在想要成爲observer的配置文件中,加上下面一行:
peerType=observer
這表示這個server以observer角色運行,即不參與投票。
再在全部 server的配置文件中,修改server.X
配置項,在那些observer的節點上加上:observer
後綴。
例如,server.1對應的server要做爲observer:
server.1=IP:2181:3181:observer
這樣配置後,ZooKeeper集羣中的全部服務器節點都知道哪些節點扮演的是observer角色。