??1.zookeeper概念Zookeeper是 Apache Hadoop項(xiàng)目下的一個(gè)子項(xiàng)目,是一個(gè)樹(shù)形目錄服務(wù)。 Zookeeper翻譯過(guò)來(lái)就是動(dòng)物園管理員,他是用來(lái)管Hadoop(大象)、Hive(蜜蜂)、 Pig(小豬)的管理員,簡(jiǎn)稱zk Zookeeper是一個(gè)分布式的、開(kāi)源的應(yīng)用程序的協(xié)調(diào)服務(wù)。 zookeeper提供的主要功能包括:
在多個(gè)應(yīng)用程序(或服務(wù)器)中,假如存在一些相同的配置信息,在對(duì)該配置信息進(jìn)行修改時(shí),我們需要一個(gè)一個(gè)進(jìn)行修改,這樣會(huì)大大增加維護(hù)的成本,不方便管理。這時(shí)如果使用一個(gè)專門放配置中心的組件,將相同的配置信息放在配置中心,需要的時(shí)候直接拉取,這樣可以大大節(jié)約維護(hù)的成本, 而zookeeper即可實(shí)現(xiàn)配置中心的功能。
在多個(gè)用戶訪問(wèn)同一臺(tái)主機(jī)上的應(yīng)用程序數(shù)據(jù)時(shí),我們可以通過(guò)加鎖解決并發(fā)操作的問(wèn)題,但是如果有多臺(tái)主機(jī)相同的應(yīng)用程序要訪問(wèn)同一數(shù)據(jù)時(shí),這個(gè)時(shí)候我們?cè)谝慌_(tái)主機(jī)上加鎖是不能解決另一臺(tái)主機(jī)的并發(fā)問(wèn)題的,換句話說(shuō)自己的鎖只對(duì)自己有效并不影響別的,這個(gè)時(shí)候就需要分布式鎖解決這類問(wèn)題,我個(gè)人理解分布式鎖像是從所有主機(jī)中抽取出來(lái)的一把鎖,或者是有一把總鎖對(duì)所有主機(jī)都有效。zookeeper可以實(shí)現(xiàn)分布式鎖的功能
zookeeper作為注冊(cè)中心,管理服務(wù)提供方的ip地址端口號(hào)url信息,并在服務(wù)消費(fèi)方請(qǐng)求需要時(shí)發(fā)送給服務(wù)消費(fèi)方 ??2.zookeeper的安裝??2.1環(huán)境準(zhǔn)備:zookeeper服務(wù)器是用Java創(chuàng)建的,運(yùn)行在JVM之上。需要安裝JDK7以上版本(最好JDK8或以上) ??2.2下載官網(wǎng)下載地址: Apache ZooKeeper ??2.3上傳并安裝下載在本地之后可以把安裝包上傳到服務(wù)器或者虛擬機(jī)中,我使用的是服務(wù)器并遠(yuǎn)程shell連接 1.使用xshell 遠(yuǎn)程連接服務(wù)器,在opt目錄下新建一個(gè)zookeeper目錄 2.使用xftp將剛才下載的安裝包上傳到zookeeper目錄下 3.進(jìn)入zookeeper目錄下解壓 tar -zxvf apache-zookeeper-3.8.0-bin.tar.gz 4. 安裝成功! ' title=''> ??2.4配置進(jìn)入conf配置目錄 zoo_sample.cfg就是配置文件,但是此文件不能生效,需要名稱為zoo.cfg的文件才能生效 改名復(fù)制一份配置文件 編輯配置文件zoo.cfg/tmp/zookeeper這個(gè)目錄是zookeeper用于存儲(chǔ)持久化的數(shù)據(jù)到本地的,但是服務(wù)器默認(rèn)是沒(méi)有的 進(jìn)入opt/zookeeper目錄下,新建一個(gè)目錄zkdata(目錄名隨意?。┯糜诖娣舲ookeeper的持久化數(shù)據(jù) 復(fù)制此目錄/opt/zookeeper/zkdata,將zoo.cfg配置文件中的dataDir修改為/opt/zookeeper/zkdata ' title=''> 保存退出! ??2.5啟動(dòng)zookeeper
??3.zookeeper內(nèi)存模型??3.1模型??3.2模型的特點(diǎn):
數(shù)據(jù)
知設(shè)置監(jiān)控的客戶端** ??3.3節(jié)點(diǎn)的分類:1.持久節(jié)點(diǎn)(默認(rèn))2.持久順序節(jié)點(diǎn)3.臨時(shí)節(jié)點(diǎn)4.臨時(shí)順序節(jié)點(diǎn) 1.create 節(jié)點(diǎn)path data 創(chuàng)建一個(gè)節(jié)點(diǎn)。并給節(jié)點(diǎn)綁定數(shù)據(jù)(默認(rèn)是持久性節(jié)點(diǎn)) 2.create -s 節(jié)點(diǎn)path data 創(chuàng)建持久性順序節(jié)點(diǎn) 3.create -e 節(jié)點(diǎn)path data 創(chuàng)建臨時(shí)性節(jié)點(diǎn) 4.create -e -s 節(jié)點(diǎn)path data 創(chuàng)建臨時(shí)順序節(jié)點(diǎn) (注意:臨時(shí)節(jié)點(diǎn)不能含有任何子節(jié)點(diǎn)) ??4.zookeeper配置文件詳解??5.zookeeper客戶端常用命令連接ZooKeeper服務(wù)端 斷開(kāi)連接 quit CRUD 1.設(shè)置(修改)節(jié)點(diǎn)值 set 節(jié)點(diǎn)path value 2.查看命令幫助 3.刪除單個(gè)節(jié)點(diǎn) delete 節(jié)點(diǎn)path 4.顯示指定目錄下節(jié)點(diǎn) ls 目錄名 5.刪除帶有子節(jié)點(diǎn)的節(jié)點(diǎn) deleteall 節(jié)點(diǎn)path 6.創(chuàng)建節(jié)點(diǎn) create 節(jié)點(diǎn)path value 7.獲取節(jié)點(diǎn)值 get 節(jié)點(diǎn)path 8.查看路徑下節(jié)點(diǎn)信息及子節(jié)點(diǎn) 9.查看節(jié)點(diǎn)狀態(tài) 節(jié)點(diǎn)監(jiān)聽(tīng)機(jī)制watch 客戶端可以監(jiān)測(cè)znode節(jié)點(diǎn)的變化。Zonode節(jié)點(diǎn)的變化觸發(fā)相應(yīng)的事件,然后清除對(duì)該節(jié)點(diǎn)的監(jiān) 測(cè)。當(dāng)監(jiān)測(cè)一個(gè)znode節(jié)點(diǎn)時(shí)候,Zookeeper會(huì)發(fā)送通知給監(jiān)測(cè)節(jié)點(diǎn)。在shell終端一個(gè)Watch事件是一個(gè)一次性 的觸發(fā)器,當(dāng)被設(shè)置了Watch的數(shù)據(jù)或者目錄發(fā)生了改變的時(shí)候,則服務(wù)器將這個(gè)改變發(fā)送給設(shè)置了 Watch的客戶端以便通知它們。 1.ls -w 節(jié)點(diǎn)path 監(jiān)聽(tīng)節(jié)點(diǎn)目錄的變化 ??新建一個(gè)會(huì)話連接 對(duì)/app1的目錄進(jìn)行修改,增加一個(gè)子節(jié)點(diǎn) 然后監(jiān)聽(tīng)就失效了,因?yàn)槭且淮涡缘?/strong> 2.get -w 節(jié)點(diǎn)path 監(jiān)聽(tīng)節(jié)點(diǎn)數(shù)據(jù)的變化 ??修改節(jié)點(diǎn)信息 觸發(fā)監(jiān)聽(tīng),并且之后監(jiān)聽(tīng)就失效了 ??6.Java客戶端操作導(dǎo)入zookeeper的依賴包和junit的測(cè)試包 <dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>provided</scope></dependency><dependency><groupId>com.101tec</groupId><artifactId>zkclient</artifactId><version>0.10</version></dependency> ??6.1連接zk server服務(wù)端@Beforepublic void before() {//參數(shù)1 --> zk server 服務(wù)ip地址:端口號(hào)//參數(shù)2 --> 會(huì)話超時(shí)時(shí)間//參數(shù)3 --> 連接超時(shí)時(shí)間//參數(shù)4 --> 序列化方式 zkClient = new ZkClient('ip:端口號(hào)', 60000 * 30, 60000, new SerializableSerializer());
}private ZkClient zkClient;
@Testpublic void test01(){
System.out.println(zkClient);
} @After
public void after() {
zkClient.close();
} 打印出結(jié)果,成功連接! ??6.2創(chuàng)建節(jié)點(diǎn)@Testpublic void test() { //創(chuàng)建持久節(jié)點(diǎn) zkClient.create('/app2', 'xue', CreateMode.PERSISTENT); //創(chuàng)建持久順序節(jié)點(diǎn) zkClient.create('/app3','yue', CreateMode.PERSISTENT_SEQUENTIAL); //創(chuàng)建臨時(shí)節(jié)點(diǎn) zkClient.create('/app4','qing', CreateMode.EPHEMERAL); //創(chuàng)建臨時(shí)順序節(jié)點(diǎn) zkClient.create('/app5','haha',CreateMode.EPHEMERAL_SEQUENTIAL); } ??6.3查看某個(gè)節(jié)點(diǎn)信息@Testpublic void test2(){//查看某個(gè)節(jié)點(diǎn)數(shù)據(jù),需要保證創(chuàng)建和獲取的數(shù)據(jù)序列化方式相同,如果是在linux上創(chuàng)建的節(jié)點(diǎn)那么在Java上獲取就會(huì)出現(xiàn)序列化不匹配的異常Object o = zkClient.readData('/app2');
System.out.println(o);//查看節(jié)點(diǎn)狀態(tài)
Stat stat = new Stat();
System.out.println(o);//查看節(jié)點(diǎn)創(chuàng)建時(shí)間System.out.println(stat.getCtime());//查看版本System.out.println(stat.getCversion());//查看idSystem.out.println(stat.getCzxid());
} ??6.4修改節(jié)點(diǎn)信息zkClient.writeData('/app2','xueyueqing'); ??6.5查看當(dāng)前節(jié)點(diǎn)所有子節(jié)點(diǎn)@Testpublic void test4(){
List<String> children = zkClient.getChildren('/');for(String c : children ){
System.out.println(c);
}
} ??6.6監(jiān)聽(tīng)@Testpublic void test5() throws IOException { zkClient.subscribeDataChanges('/app1', new IZkDataListener() { //當(dāng)前節(jié)點(diǎn)數(shù)據(jù)變化時(shí)觸發(fā) @Override public void handleDataChange(String dataPath, Object o) throws Exception { System.out.println('當(dāng)前節(jié)點(diǎn)路徑' dataPath); System.out.println('當(dāng)前節(jié)點(diǎn)信息' o); } //當(dāng)前節(jié)點(diǎn)刪除時(shí)觸發(fā) @Override public void handleDataDeleted(String dataPath) throws Exception { System.out.println('當(dāng)前節(jié)點(diǎn)路徑' dataPath); } }); //阻塞當(dāng)前監(jiān)聽(tīng) System.in.read(); } 注意:在shell終端修改,Java是監(jiān)聽(tīng)不了的,必須使用Java代碼修改 ??通過(guò)Java代碼進(jìn)行修改 ' title=''> 監(jiān)聽(tīng)成功!并發(fā)現(xiàn)Java代碼進(jìn)行監(jiān)聽(tīng)是永久的,不是一次性的 @Test
public void test6() throws IOException {//監(jiān)聽(tīng)節(jié)點(diǎn)目錄變化 zkClient.subscribeChildChanges('/app1', new IZkChildListener() { @Override public void handleChildChange(String s, List<String> list) throws Exception {
System.out.println('父節(jié)點(diǎn)名稱:' s);
System.out.println('發(fā)生變化后孩子節(jié)點(diǎn)名稱:'); for(String child : list){
System.out.println(child);
}
}
}); //阻塞當(dāng)前監(jiān)聽(tīng) System.in.read();
} 在/app1目錄下創(chuàng)建節(jié)點(diǎn)name 監(jiān)聽(tīng)成功! |
|
來(lái)自: 修行的嘟嘟 > 《軟件開(kāi)發(fā)》