在大數據和雲計算普遍的今天,越來越多的應用使用了Apache下zookeeper這個利器,舉幾個家喻戶小的,像HBase,Kafka,國內阿里巴巴開源的Dubbo等。
首先來了解下zookeeper,原型是Google的Chubby,數據結構是樹,我個人理解其實zookeeper也是nosql的一種,是一個非關係型數據庫,裏面存儲的是樹結構的數據,包括結點與關係,還有結點上存儲的數據。不過zookeeper的強大之處還不是nosql,他的強大之處在於內部的集羣機制與事件機制,我說的集羣機制是指zookeeper的集羣中的選舉算法,涉及FAST PAXOS和兩段提交算法,相比我看過的hazelcast這個集羣下內存共享的組件的選舉算法要複雜。還的一點就是事件的監聽與處理機制,我在工作中使用到的包括結點的變化事件和結點的子樹變化事件等,前者適用與系統的配置的管理,後者則適用於故障監聽和失效轉移。
用我之前博客裏的圖爲例:
主要是紫色圈起來的部分,集羣中的系統部件以TCP連接到zookeeper上,在一個結點下創建一個臨時的子結點,當連接到zookeeper的部件發生故障與zookeeper之間的socket斷開後,zookeeper中的父結點會產生一個子樹發生變化的事件,這樣對於訂閱了這個父結點子樹變化的系統會收會通知。這個功能特別適用於Service的消費方與提供方之間進行可靠的選擇。
還以蘋果消息通知推送系統爲例,服務消息方先訂閱事件,並做事件變化的處理:
zkClient.subscribeChildChanges(apnsnode, new IZkChildListener() {
@Override
public void handleChildChange(String parentPath,
List<String> currentChilds) throws Exception {
MQUtil.getInstance().setQueues(currentChilds);
for (String queue : currentChilds) {
amqpAdmin.declareQueue(new Queue(PRD_PRIX + queue, true,
false, false));
amqpAdmin.declareBinding(new Binding(PRD_PRIX + queue,
DestinationType.QUEUE, PRD_PRIX + exchange, queue,
null));
amqpAdmin.declareQueue(new Queue(DEV_PRIX + queue, true,
false, false));
amqpAdmin.declareBinding(new Binding(DEV_PRIX + queue,
DestinationType.QUEUE, DEV_PRIX + exchange, queue,
null));
}
}
});
而服務的提供方要做的就是將自己註冊到結點上:
public void init() {
// 創建連接
zkClient = new ZkClient(address);
// 如果根結點不存在則創建根結點
if (!zkClient.exists(apnsnode)) {
zkClient.createPersistent(apnsnode);
}
String prefix = "";
try {
// 以IP地址爲前輟
prefix = Inet4Address.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
}
// 創建CPU核心個數隊列
int number = Runtime.getRuntime().availableProcessors();
for (int i = 0; i < number; i++) {
// 隊列名
String node = prefix + "." + i;
// 子結點名
String path = apnsnode + "/" + node;
if (!zkClient.exists(path)) {
// 創建臨時結點
zkClient.createEphemeral(path);
}
queues.add(node);
}
}
這個功能也是zookeeper被廣泛應用的主要原理,當然,zookeeper還有很多值得研究和學習的地方,推薦大家好好的研究和使用一下zookeeper,我在工作中已經在很多場景中使用,有一個是用zookeeper做的一個系統功能的開關,也就是用他做配置管理。
相信在大數據和雲計算下zookeeper一定會被應用越來越廣,性能也會越來越好。