Zookeeper是架構模式是主從結構,用來存儲一些數據,也可以做分佈式協調服務,它的主節點叫leader,從節點叫follower。zookeeper允許一半的節點宕機。它的集羣模式一般是奇數臺服務器。
zookeeper的功能:
1、存儲數據:配置信息,元信息
2、選舉功能
3、數據同步(ZAB協議)
4、分佈式鎖
5、監聽機制,監聽節點的數據變化
單節點的安裝
zookeeper的安裝其實特別簡單。
第一步減壓
tar -zxvf zookeeper-3.4.10.tar.gz -C ~/training/
第二步 配置環境變量
vim ~/.bash_profile
ZOOKEEPER_HOME=/root/training/zookeeper-3.4.10
export ZOOKEEPER_HOME
PATH=$ZOOKEEPER_HOME/bin:$PATH
export PATH
使用戶的環境變量配置文件生效
source ~/.bash_profile
第三步配置配置文件
它的配置文件需要把conf 目錄下的示例配置文件拷貝一份
cp zoo_sample.cfg zoo.cfg
因爲啓動zookeeper的時候默認使用的conf目錄下的zoo.cfg配置文件
配置
dataDir=/root/training/zookeeper-3.4.10/tmp 數據存儲的路徑
server.1=bigdata111:2888:3888 2888是通信端口,3888是選舉端口
數據存儲路徑要事先創建好
在/root/training/zookeeper-3.4.10/tmp創建一個文件:myid
輸入 1
啓動:zkServer.sh start
zkServer.sh status
這樣一個單機版zookeeper就安裝成功了
然後同過命令行客戶端測試一下:
zkClli.sh
ZooKeeper節點的類型:兩個維度(永久還是臨時、有序還是無序)
(1)持久化節點
(2)持久化排序節點
臨時節點:當客戶端會話如果退出,該臨時節點就自動刪除。
(3)臨時節點
(4)臨時的有序節點
使用代碼操作Zookeeper:
apache提供了一套api接口專門操作zookeeper叫curator
搭建一個簡單maven工程把它引入進去
pom依賴
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>16.0.1</version>
</dependency>
</dependencies>
創永久無序節點
package com.kanxyz.demo;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
public class CreateZKNode
{
public static void main(String[] args) throws Exception {
//如果Zookeeper斷掉,設置連接策略 每隔1秒連接一次 最多連接十次
RetryPolicy retryPolicy=new ExponentialBackoffRetry(1000, 10);
CuratorFramework client=CuratorFrameworkFactory.builder()
.connectString("192.168.112.111:2181")
.retryPolicy(retryPolicy)
.build();
client.start();
//創建永久無序節點
client.create().forPath("/mypath");
client.close();
}
}
代碼創建節點可以沒有數據,但是命令行創建節點是創建不上的
創建永久有序節點
package com.kanxyz.demo;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.schema.SchemaSet;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
public class CreateZKNode
{
public static void main(String[] args) throws Exception {
//如果Zookeeper斷掉,設置連接策略 每隔1秒連接一次 最多連接十次
RetryPolicy retryPolicy=new ExponentialBackoffRetry(1000, 10);
CuratorFramework client=CuratorFrameworkFactory.builder()
.connectString("192.168.112.111:2181")
.retryPolicy(retryPolicy)
.build();
client.start();
//創建永久無序節點
// client.create().forPath("/mypath");
//創建永久有序節點
client.create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/node-");
client.create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/node-");
client.create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/node-");
client.create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/node-");
//創建臨時無序節點
//創建臨時有序節點
client.close();
}
}
創建臨時無序節點和臨時有序節點
package com.kanxyz.demo;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
public class CreateZKNode
{
public static void main(String[] args) throws Exception {
//如果Zookeeper斷掉,設置連接策略 每隔1秒連接一次 最多連接十次
RetryPolicy retryPolicy=new ExponentialBackoffRetry(1000, 10);
CuratorFramework client=CuratorFrameworkFactory.builder()
.connectString("192.168.112.111:2181")
.retryPolicy(retryPolicy)
.build();
client.start();
//創建永久無序節點
// client.create().forPath("/mypath");
//創建永久有序節點
/*client.create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/node-");
client.create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/node-");
client.create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/node-");
client.create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/node-");*/
//創建臨時無序節點
/*client.create().withMode(CreateMode.EPHEMERAL).forPath("/mytempnode");
Thread.sleep(2000);*/
//創建臨時有序節點
client.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/tmpnode-");
client.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/tmpnode-");
client.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/tmpnode-");
client.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/tmpnode-");
client.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/tmpnode-");
Thread.sleep(5000);
client.close();
}
}
節點監聽
package com.kanxyz.demo;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
public class ListenerZKDemo
{
public static void main(String[] args) throws Exception{
RetryPolicy retryPolicy=new ExponentialBackoffRetry(1000, 10);
CuratorFramework client=CuratorFrameworkFactory.builder()
.connectString("192.168.112.111:2181")
.retryPolicy(retryPolicy)
.build();
client.start();
//監聽節點mypath操作
PathChildrenCache children = new PathChildrenCache(client, "/mypath", true);
children.getListenable().addListener(new PathChildrenCacheListener()
{
public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
System.out.println("監控節點的操作:"+event.getType());
// public static final Type CHILD_ADDED; 子節點添加的類型
// public static final Type CHILD_UPDATED; 子節點更新的類型
// public static final Type CHILD_REMOVED; 子節點移除的類型
switch (event.getType())
{
case CHILD_ADDED:
System.out.println("節點添加");
break;
case CHILD_UPDATED:
System.out.println("節點更新");
break;
case CHILD_REMOVED:
System.out.println("節點移除");
break;
default :
System.out.println("執行了其他的操作");
break;
}
}
});
children.start();
Thread.sleep(100000);
client.close();
System.out.println("監聽結束--------------");
}
}
分佈式鎖功能
package com.kanxyz.demo;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;
public class ZKDistributeLock
{
//秒殺總分數
private static int NUMBER=10;
//定義秒殺邏輯
private static void getNumber(){
System.out.println("秒殺開始");
System.out.println("我搶第"+NUMBER+"商品");
NUMBER--;
try
{
Thread.sleep(1000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("秒殺結束");
}
public static void main(String[] args) {
//創建鏈接策略
RetryPolicy retryPolicy=new ExponentialBackoffRetry(1000, 10);
//創建客戶端
CuratorFramework client=CuratorFrameworkFactory.builder()
.connectString("192.168.112.111:2181")
.retryPolicy(retryPolicy)
.build();
client.start();
//創建這把鎖
final InterProcessMutex lock = new InterProcessMutex(client, "/aaaa");
for (int i = 0; i < 10; i++)
{
new Thread(new Runnable()
{
public void run() {
try
{
//請求得到鎖
lock.acquire();
getNumber();
} catch (Exception e)
{
e.printStackTrace();
}finally {
try
{
//完成本次操作要釋放鎖
lock.release();
} catch (Exception e)
{
e.printStackTrace();
}
}
}
}).start();
}
//因爲是上邊是線程不能提前關閉鏈接客戶端
//client.close();
}
}