1.zookeeper主要功能
1.1 配置管理
分布式專案的配置總管理處

1.2 分布式鎖

對于分布式專案修改共享資料時加入鎖管理(同一時間只能有一個服務對資料進更改)
1.3 集群管理
最常見的功能,作為注冊中心使用.

2.zookeeper命令操作
2.1 zookeeper資料模型
-
Zookeeper是一個樹形目錄服務,其資料模型和Unix的檔案系統目錄樹很類似,擁有一個層次化結構
-
這里面的每一個結點都被稱為ZNode,每個節點都會保存自己的資料和節點資訊
-
節點可以擁有子節點,同時也允許少量(1MB)資料存盤在該節點之下
-
節點可以分為四大類
-
PERSISTENT 持久化節點
-
EPHEMRAL 臨時節點 : -e
-
PERSISTENT_SENQUENTIAL 持久化順序節點 : -s
-
EPHEMRAL_SEQUENTIAL 臨時順序節點 : -es
-

2.2 zookeeper 服務端常用命令
在安裝目錄的bin目錄下
-
啟動Zookeeper服務 : ./zkServer.sh start
-
查看Zookeeper服務狀態 : ./zkServer.sh statu
-
停止Zookeeper服務 : ./zkServer.sh stop
-
重啟Zookeeper服務 : ./zkServer.sh restart
2.3 zookeeper 客戶端常用命令
-
連接ZooKeeper服務端
-
./zkCli.sh -server ip:port
-
-
斷開客戶端連接
-
quit
-
-
設定節點的值
-
set /節點path value
-
-
查看幫助命令
-
help
-
-
洗掉單個節點
-
delete /節點path
-
-
顯示指定目錄下的節點
-
ls 目錄
-
-
洗掉帶有子節點的節點
-
deleteall /節點path
-
-
創建節點
-
create /節點path value
-
-
獲取節點的值
-
get /節點path
-
-
創建臨時節點
-
create -e /節點path value
-
-
創建順序節點
-
create -s /節點path value
-
-
查詢節點詳細資訊
-
ls -s /節點path
-
-
節點詳細資訊
-
czxid : 節點被創建的事務ID
-
dataversion : 資料版本號
-
ctime : 創建時間
-
aclversion : 權限版本號
-
mzxid : 最后一次被更新的事務ID
-
ephemeralOwner : 用于臨時節點 ,代表臨時節點的事務ID,如果為持久節點則為0
-
pzxid : 子節點串列最后一次被更新的事務ID
-
dataLength : 節點存盤的資料長度
-
cversion : 子節點的版本號
-
numChildren : 當前節點的子節點數
-
3.Java API-Cuator
-
Curator是Apache ZooKeeper的Java客戶端庫
4.Java API 常用操作
-
建立連接
-
添加節點
-
洗掉節點
-
修改節點
-
查詢節點
-
Watch時間監聽
-
分布式鎖實作
4.1 建立連接
4.1.1 方式一
/**
* Create a new client
*
* @param connectString list of servers to connect to "127.0.0.1:2181'127.0.0.2:8182"
* @param sessionTimeoutMs session timeout
* @param connectionTimeoutMs connection timeout
* @param retryPolicy retry policy to use
* @return client
*/
//重試策略1 每間隔x一共重試x次 每隔3秒連接一次一共連接10次
RetryPolicy r = new ExponentialBackoffRetry(3000, 10);
//第一種方式
CuratorFramework zookeeperClient = CuratorFrameworkFactory.newClient("116.62.71.234:2181",
60 * 1000,
15 * 1000,
r);
//開啟連接
zookeeperClient.start();
4.1.2 方式二 : 鏈式編程
//第二種連接方式:鏈式編程
CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.234:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
namespace("itheima").build();
//開啟連接
zookeeperClient.start();
-
namespace : 創建根節點itheima(為了方便,不用之后每次進行客戶端操作都寫/根節點path)
4.2 添加節點
4.2.1 基本創建
public static void main(String[] args) throws Exception {
//第二種連接方式:鏈式編程
CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.235:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
namespace("itheima").build();
//開啟連接
zookeeperClient.start();
/**
* 創建節點
* 1.基本創建 create().forPath("")
* 2.創建節點,帶有資料 create.forPath("",data.getBytes())
* 3.設定節點的型別 create.withMode(CreateMode.ENUM).forPath("")
* 4.創建多級節點 create().creatingParentsIfNeeded().forPath("/app4/p1","hehe".getBytes());
*/
/**
* 基本創建
* 如果創建節點,沒有指定資料,則默認將當前客戶端的ip作為資料存盤
*/
String path = zookeeperClient.create().forPath("/app1");
System.out.println(path);
//關閉連接
zookeeperClient.close();
}
4.2.2 創建節點帶有資料
-
如果沒有節點資訊,則資訊默認為客戶端ip
public static void main(String[] args) throws Exception {
//第二種連接方式:鏈式編程
CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.235:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
namespace("itheima").build();
//開啟連接
zookeeperClient.start();
/**
* 創建節點
* 1.基本創建 create().forPath("")
* 2.創建節點,帶有資料 create.forPath("",data.getBytes())
* 3.設定節點的型別 create.withMode(CreateMode.ENUM).forPath("")
* 4.創建多級節點 create().creatingParentsIfNeeded().forPath("/app4/p1","hehe".getBytes());
*/
/**
* 基本創建,帶有資料
* 如果創建節點,沒有指定資料,則默認將當前客戶端的ip作為資料存盤
*/
String path = zookeeperClient.create().forPath("/app2","hehe".getBytes());
System.out.println(path);
//關閉連接
zookeeperClient.close();
}
4.2.3 創建節點,設定節點型別
-
默認為持久化型別
public static void main(String[] args) throws Exception {
//第二種連接方式:鏈式編程
CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.235:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
namespace("itheima").build();
//開啟連接
zookeeperClient.start();
/**
* 創建節點
* 1.基本創建 create().forPath("")
* 2.創建節點,帶有資料 create.forPath("",data.getBytes())
* 3.設定節點的型別 create.withMode(CreateMode.ENUM).forPath("")
* 4.創建多級節點 create().creatingParentsIfNeeded().forPath("/app4/p1","hehe".getBytes());
*/
/**
* 創建節點帶有型別
* 默認型別:持久化
*/
String path = zookeeperClient.create().withMode(CreateMode.EPHEMERAL).forPath("/app3","hehe".getBytes());
System.out.println(path);
//關閉連接 app3就會被釋放
zookeeperClient.close();
}
4.2.4 創建多級節點
-
ZooKeeper如果父節點不存在無法創建子節點
public static void main(String[] args) throws Exception {
//第二種連接方式:鏈式編程
CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.235:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
namespace("itheima").build();
//開啟連接
zookeeperClient.start();
/**
* 創建節點
* 1.基本創建 create().forPath("")
* 2.創建節點,帶有資料 create.forPath("",data.getBytes())
* 3.設定節點的型別 create.withMode(CreateMode.ENUM).forPath("")
* 4.創建多級節點 create().creatingParentsIfNeeded().forPath("/app4/p1","hehe".getBytes());
*/
/**
* 創建多級節點
* 父節點不存在無法直接創建子節點
* creatingParentsIfNeeded
*/
String path = zookeeperClient.create().creatingParentsIfNeeded().forPath("/app4/p1","hehe".getBytes());
System.out.println(path);
//關閉連接 app3就會被釋放
zookeeperClient.close();
}
4.3 查詢節點
4.3.1 查詢節點資料
public static void main(String[] args) throws Exception {
//第二種連接方式:鏈式編程
CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.235:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
namespace("itheima").build();
//開啟連接
zookeeperClient.start();
/**
* 查詢節點
* 1.查詢資料 get : getData().forPath()
* 2.查詢子節點 ls getChildren.forPath();
* 3.查詢節點狀態資訊 ; ls -s getData().storingStatIn(status).forPath("/app1")
*/
byte[] bytes = zookeeperClient.getData().forPath("/app1");
System.out.println(new String(bytes));
//關閉連接
zookeeperClient.close();
}
4.3.2 查詢節點子節點
public static void main(String[] args) throws Exception {
//第二種連接方式:鏈式編程
CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.235:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
namespace("itheima").build();
//開啟連接
zookeeperClient.start();
/**
* 查詢節點
* 1.查詢資料 get : getData().forPath()
* 2.查詢子節點 ls getChildren.forPath();
* 3.查詢節點狀態資訊 ; ls -s getData().storingStatIn(status).forPath("/app1")
*/
List<String> strings = zookeeperClient.getChildren().forPath("/app1");
//關閉連接
zookeeperClient.close();
}
4.3.3 查詢節點詳細資訊 2.3詳見詳細資訊
-
回傳的結果需要封裝到一個JavaBean中
public static void main(String[] args) throws Exception {
//第二種連接方式:鏈式編程
CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.235:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
namespace("itheima").build();
//開啟連接
zookeeperClient.start();
/**
* 查詢節點
* 1.查詢資料 get : getData().forPath()
* 2.查詢子節點 ls getChildren.forPath();
* 3.查詢節點狀態資訊 ; ls -s getData().storingStatIn(status).forPath("/app1")
*/
/**
* Stat是一個Bean將回傳的節點的詳細資訊封裝到bean中
*/
Stat status = new Stat();
zookeeperClient.getData().storingStatIn(status).forPath("/app1");
//關閉連接
zookeeperClient.close();
}
4.4 修改節點資訊
4.4.1 基本修改
public static void main(String[] args) throws Exception {
//第二種連接方式:鏈式編程
CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.235:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
namespace("itheima").build();
//開啟連接
zookeeperClient.start();
/**
* 修改節點資料
* 1.修改資料
* 2.根據版本修改
*/
zookeeperClient.setData().forPath("/app1","itcast".getBytes());
//關閉連接
zookeeperClient.close();
}
4.4.2 根據版本修改節點資訊(推薦)
public static void main(String[] args) throws Exception {
//第二種連接方式:鏈式編程
CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.234:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
namespace("itheima").build();
//開啟連接
zookeeperClient.start();
/**
* 修改節點資料
* 1.修改資料
* 2.根據版本修改
*/
/**
* 根據版本修改前需要先查出版本,查詢出的版本和傳入的版本號需要一致才能修改成功,目的就是讓其他客戶端或者其他執行緒不干擾我.
*/
Stat status = new Stat();
zookeeperClient.getData().storingStatIn(status).forPath("/app1");
//查詢出版本
int version = status.getVersion();
System.out.println(version);
zookeeperClient.setData().withVersion(3).forPath("/app1","itcast".getBytes());
//關閉連接
zookeeperClient.close();
}
4.5 洗掉節點
4.5.1 基本洗掉
public static void main(String[] args) throws Exception {
//第二種連接方式:鏈式編程
CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.234:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
namespace("itheima").build();
//開啟連接
zookeeperClient.start();
/**
* 洗掉節點 : delete deleteall
* 1.洗掉單個節點 delete().forPath();
* 2.洗掉帶有子節點的節點 delete().deletingChildrenIfNeeded().forPath("/app1");
* 3.必須成功的洗掉 delete().guaranteed().forPath("/app1"); 為了防止網路抖動,本質就是重試.
* 4.洗掉回呼 zookeeperClient.delete().guaranteed().inBackground(
*/
zookeeperClient.delete().forPath("/app1");
//關閉連接
zookeeperClient.close();
}
4.5.2 帶有子節點的遞回洗掉
public static void main(String[] args) throws Exception {
//第二種連接方式:鏈式編程
CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.234:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
namespace("itheima").build();
//開啟連接
zookeeperClient.start();
/**
* 洗掉節點 : delete deleteall
* 1.洗掉單個節點 delete().forPath();
* 2.洗掉帶有子節點的節點 delete().deletingChildrenIfNeeded().forPath("/app1");
* 3.必須成功的洗掉 delete().guaranteed().forPath("/app1"); 為了防止網路抖動,本質就是重試.
* 4.洗掉回呼 zookeeperClient.delete().guaranteed().inBackground(
*/
zookeeperClient.delete().deletingChildrenIfNeeded().forPath("/app1");
//關閉連接
zookeeperClient.close();
}
4.5.3 必須洗掉成功
-
guaranteed();
public static void main(String[] args) throws Exception {
//第二種連接方式:鏈式編程
CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.234:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
namespace("itheima").build();
//開啟連接
zookeeperClient.start();
/**
* 洗掉節點 : delete deleteall
* 1.洗掉單個節點 delete().forPath();
* 2.洗掉帶有子節點的節點 delete().deletingChildrenIfNeeded().forPath("/app1");
* 3.必須成功的洗掉 delete().guaranteed().forPath("/app1"); 為了防止網路抖動,本質就是重試.
* 4.洗掉回呼 zookeeperClient.delete().guaranteed().inBackground(
*/
zookeeperClient.delete().guaranteed().forPath("/app1");
//關閉連接
zookeeperClient.close();
}
4.5.4 洗掉回呼
-
inBackground(()->{})
public static void main(String[] args) throws Exception {
//第二種連接方式:鏈式編程
CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.234:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
namespace("itheima").build();
//開啟連接
zookeeperClient.start();
/**
* 洗掉節點 : delete deleteall
* 1.洗掉單個節點 delete().forPath();
* 2.洗掉帶有子節點的節點 delete().deletingChildrenIfNeeded().forPath("/app1");
* 3.必須成功的洗掉 delete().guaranteed().forPath("/app1"); 為了防止網路抖動,本質就是重試.
* 4.洗掉回呼 zookeeperClient.delete().guaranteed().inBackground(
*/
zookeeperClient.delete().guaranteed().inBackground(new BackgroundCallback(){
@Override
public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
System.out.println("我被洗掉了");
System.out.println(event);
}
}).forPath("/app1");
//關閉連接
zookeeperClient.close();
}
5.Java API 高級操作
5.1 Watch事件監聽
5.1.1 基本概念
-
ZooKeeper允許用戶在指定節點上注冊一些Watchr,并且在一些特定事件觸發的時候,ZooKeeper服務端會將事件通知到感興趣的客戶端上去,該機制時ZooKeeper實作分布式協調服務的重要特性.
-
ZooKeeper中引入了Watcher機制來實作了發布/訂閱功能.能夠讓多個訂閱者同時監聽某一個物件,當一個物件自身狀態變化的時候,會通知所有訂閱者.
-
ZooKeeper原生支持通過注冊Watcher來進行事件監聽,但是其使用并不是特別方便需要開發人員自己反復注冊Watcher,比較繁瑣.
-
Curator引入了Cache來實作對ZooKeeper服務端事件的監聽.
-
ZooKeeper提供了三種Watcher;
-
NodeCache : 只是監聽了某一特定節點
-
PathChildrenCache : 監控一個ZNode的子節點
-
TreeCache : 可以監控整個樹上的所有節點,類似于PathChildrenCache和NodeCache組合.
-
5.1.2 NodeCache
public static void main(String[] args) throws Exception {
//第二種連接方式:鏈式編程
CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.234:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
namespace("itheima").build();
//開啟連接
zookeeperClient.start();
/**
* NodeCache : 給指定一個節點注冊監聽器
*/
//1.創建NodeCache物件
NodeCache nodeCache = new NodeCache(zookeeperClient, "/app1");
//2.注冊監聽
nodeCache.getListenable().addListener(new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
System.out.println("節點變化了");
//獲取修改節點后的資料
byte[] data = nodeCache.getCurrentData().getData();
System.out.println(new String(data));
}
});
//3.開啟監聽,如果設定為true,則開啟監聽時,加載快取資料
nodeCache.start();;
//while (true){} //保證執行緒不結束 , web環境不需要加,這里是主方法演示
//關閉連接
zookeeperClient.close();
}
5.1.3 PathChildrenCache
-
引數event可以獲得修改的詳細資訊
public static void main(String[] args) throws Exception {
//第二種連接方式:鏈式編程
CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.234:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
namespace("itheima").build();
//開啟連接
zookeeperClient.start();
/**
* PathChildrenCache : 監聽某個節點的位元組點
*/
//1.創建PathChildrenCache物件
PathChildrenCache p = new PathChildrenCache(zookeeperClient,"/app2",true);
//2.注冊監聽
p.getListenable().addListener(new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
System.out.println("子節點發送變化了");
System.out.println(event);
//監聽子節點的資料變更,并且拿到變更后的資料
//1.獲取型別
PathChildrenCacheEvent.Type type = event.getType();
//2.判斷型別是否為update
if(type.equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){
System.out.println("資料變了");
byte[] data = event.getData().getData();
System.out.println(new String(data));
}
}
});
//3.開啟監聽,如果設定為true,則開啟監聽時,加載快取資料
p.start();
//while (true){} //保證執行緒不結束 , web環境不需要加,這里是主方法演示
//關閉連接
zookeeperClient.close();
}
5.1.4 TreeCache
public static void main(String[] args) throws Exception {
//第二種連接方式:鏈式編程
CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.234:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
namespace("itheima").build();
//開啟連接
zookeeperClient.start();
/**
* TreeCache : 監聽某個節點及其子節點
*/
//1.創建NodeCache物件
TreeCache treeCache = new TreeCache(zookeeperClient, "/app1");
//2.注冊監聽
treeCache.getListenable().addListener(new TreeCacheListener() {
@Override
public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
System.out.println("結點變化了");
System.out.println(event);
}
});
//3.開啟監聽,如果設定為true,則開啟監聽時,加載快取資料
treeCache.start();
//關閉連接
zookeeperClient.close();
//while (true){} //保證執行緒不結束 , web環境不需要加,這里是主方法演示
}
6.分布式鎖
6.1 分布式鎖
-
在我們進行單機應用開發,涉及并發同步的時候,我們往往采用synchronized或者lock的方式來解決多執行緒見的代碼同步問題,這時多執行緒的運行都是運行在同一 JVM下,沒有任何問題
-
但當我們的應用時分布式集群作業的情況下,屬于JVM下的作業環境,跨JVM之間已經無法通過多執行緒的鎖解決同步問題
-
那么久需要一種更加高級的鎖機制,來處理跨機器的行程之間的資料同步問題---這就是分布式鎖.
6.2 分布式鎖原理
-
核心思想 : 當客戶端要獲取鎖,則創建節點,使用完鎖則洗掉該節點
-
客戶端獲取鎖時,在lock節點下創建臨時順序節點
-
然后分別獲取lock下面的所有子節點,客戶端獲取到所有子節點之后,如果發現自己創建的子節點序號最小,那么就認為該客戶端獲取到了鎖.
-
如果發現自己創建的節點并非lock所有子節點中最小的,說明還沒有獲取到鎖,此時客戶端需要找到比自己小的那個節點,同時對其注冊事件監聽器,監聽洗掉事件.
-
如果發現比自己小得那個節點被洗掉,則客戶端的Watcher會受到相應通知,此時再次判斷自己創建的節點是否是lock子節點中序號最小的,如果是則獲取到了鎖,如果不是則重復以上步驟繼續獲取比自己小的一個節點并注冊監聽.
-
6.3 模擬12306售票案例
-
在Curator中有五種鎖方案
-
InterProcessSemaphoreMutex : 分布式排它鎖 (非可重入鎖)
-
InterProcessMutex : 分布式可重入排它鎖
-
InterProcessReadWriteLock : 分布式讀寫鎖
-
InterProcessMultiLock : 將多個鎖作為單個物體管理的容器
-
InterProcessSemaphoreV2 : 共享信號量
-

Runnable
public class Ticket12306 implements Runnable {
private int tickets = 10;
//第二種連接方式:鏈式編程
private static CuratorFramework zookeeperClient = CuratorFrameworkFactory.builder().
connectString("116.62.71.235:2181").
sessionTimeoutMs(60 * 1000).
connectionTimeoutMs(15 * 1000).
retryPolicy(new ExponentialBackoffRetry(3000, 10)).
build();
private static InterProcessMutex lock = new InterProcessMutex(zookeeperClient,"/lock") ;
@Override
public void run() {
while (true){
//獲取鎖
try {
lock.acquire(3, TimeUnit.SECONDS);
if(tickets > 0){
System.out.println(Thread.currentThread().getName()+":"+tickets);
Thread.sleep(100);
tickets--;
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//釋放鎖
try {
lock.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
Main
public class Lock12306 {
public static void main(String[] args) {
Ticket12306 t = new Ticket12306();
Thread t1 = new Thread(t,"攜程");
Thread t2 = new Thread(t,"飛豬");
t1.start();
t2.start();
}
}
7 ZooKeeper集群
7.1 集群簡介
-
Leader選舉 :
-
Serverid ; 服務器ID
-
比如有三臺機器,編號為1,2,3.編號越大在選擇演算法中權重越大.
-
-
Zxid : 資料ID
-
服務器中存放的最大資料ID,值越大說明資料越新,在選舉演算法中資料越新則權重越大
-
-
在Leader選舉的程序中,如果某臺ZooKeeper獲得了超過半數的選票,則此ZooKeeper就可以成為Leader了
-
7.2 Zookeer集群搭建
-
與創建單機環境類似
-
修改conf目錄下的zoo_sample.cfg為zoo.cfg
-
修改data目錄為指定目錄,每個集群成員分別配置
-
在data目錄下創建myid檔案,內容分別為1,2,3
-
分別在conf目錄下的zoo.cfg檔案加入如下內容
server.1=192.168.149.135:2881:3881
server.2=192.168.149.135:2882:3882
server.3=192.168.149.135:2883:3883
-
解釋:server.服務器ID=服務器IP地址:服務器之間通信埠:服務器之間投票選舉埠,搭建偽集群,埠可以寫成127.0.0.1
7.3 Zookeeper集群角色
-
Leader領導者
-
處理事務請求(增刪改)
-
集群內部各個服務器的調度者
-
-
Follower跟隨者
-
處理客戶端非事務請求(查),轉發事務請求給Leader服務器.
-
引數Leader選舉投票
-
-
Observer觀察者
-
處理客戶端非事務請求,轉發事務請求給Leader服務器.
-
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/321048.html
標籤:其他
上一篇:C/C++程式員編程規范
下一篇:5-2 學習打卡(10.16)
