[TOC]java
ZooKeeper致力於提供一個高性能、高可用,且具有嚴格的順序訪問控制能力的分佈式協調服務,是雅虎公司建立,是Google的Chubby一個開源的實現,也是Hadoop和Hbase的重要組件. node
設計目標:算法
CAP理論:一個分佈式系統不可能同時知足一致性、可用性和分區容錯性這三個 基本需求,最多隻能同時知足其中的兩項; apache
TIPS:架構師的精力每每就花在怎麼樣根據業務場景在A和C直接尋求平衡;api
BASE理論:即便沒法作到強一致性,但分佈式系統能夠根據本身的業務特色,採 用適當的方式來使系統達到最終的一致性;緩存
Zookeeper常應用如下場景:bash
序號 | 參數名 | 說明 |
---|---|---|
1 | clientPort | 客戶端鏈接server的端口,即對外服務端口,通常設置爲2181 |
2 | dataDir | 存儲快照文件snapshot的目錄。默認狀況下,事務日誌也會存儲在這裏。建議同時配置參數dataLogDir, 事務日誌的寫性能直接影響zk性能。 |
3 | tickTime | ZK中的一個時間單元。ZK中全部時間都是以這個時間單元爲基礎,進行整數倍配置的。例如,session的最小超時時間是2*tickTime |
4 | dataLogDir | 事務日誌輸出目錄。儘可能給事務日誌的輸出配置單獨的磁盤或是掛載點,這將極大的提高ZK性能 |
5 | globalOutstandingLimit | 最大請求堆積數。默認是1000。ZK運行的時候, 儘管server已經 沒有空閒來處理更多的客戶端請求了,可是仍是容許客戶端將請求提交到服務器上來,以提升吞吐性能。固然,爲了防止Server內存 溢出,這個請求堆積數仍是須要限制下的。(Java system property: zookeeper.globalOutstandingLimit.) |
6 | preAllocSize | 預先開闢磁盤空間,用於後續寫入事務日誌。默認是64M,每一個事務日誌大小就是64M。若是ZK的快照頻率較大的話,建議適當減少 這個參數。(Java system property: zookeeper.preAllocSize) |
7 | snapCount | 每進行snapCount次事務日誌輸出後,觸發一次快照(snapshot),此時,ZK會生成一個snapshot.文件,同時建立一個新的事務日誌文件log.。 默認是100000.(真正的代碼實現中,會進行必定的隨機數處理,以避 免 所 有 服 務 器 在 同 一 時 間 進 行 快 照 而 影 響 性 能 )(Java system property: zookeeper.snapCount) |
8 | traceFile | 用於記錄全部請求的log,通常調試過程當中可使用,可是生產環境不建 議使用,會嚴重影響性能。(Java system property:? requestTraceFile) |
9 | maxClientCnxns | 單個客戶端與單臺服務器之間的鏈接數的限制,是ip級別的,默認是60若是設置爲0,那麼代表不做任何限制。請注意這個限制的使用範圍,僅僅是單臺客戶端機器與單臺ZK服務器之間的鏈接數限制,不是針對指定客戶端IP,也不是ZK集羣的鏈接數限制,也不是單臺ZK對全部客戶端的 鏈接數限制。 |
10 | clientPortAddress | 對於多網卡的機器,能夠爲每一個IP指定不一樣的監聽端口。默認狀況是所 有IP都監聽 clientPort指定的端口。 New in 3.3.0 |
11 | minSessionTimeou tmaxSessionTimeout | Session超時時間限制,若是客戶端設置的超時時間不在這個範圍,那麼會被強制設置爲最大或最小時間。默認的Session超時時間是在2* tickTime ~ 20 * tickTime 這 個 範 圍 New in 3.3.0 |
12 | fsync.warningthresholdms | 事務日誌輸出時,若是調用fsync方法超過指定的超時時間,那麼會在日誌中輸出警告信息,默認是1000ms |
13 | autopurge.purgeInterval | 清理任務的時間間隔,單位爲hours |
14 | autopurge.snapRetainCount | zkserver啓動時會開啓一個org.apache.zookeeper.server.DatadirCleanupManager的線程,用於清理"過時"的snapshot文件和其相應的txn log file,此參數用於設定須要被retain保留的文件個數(從QuorumPeerMain跟蹤代碼) |
15 | electionAlg | 選舉算法,默認爲3,能夠選擇(0,1,2,3), 0表示使用原生的UDP(LeaderElection), 1表示使用費受權的UDP 2表示使用受權的UDP(AuthFastLeaderElection) 3基於TCP的快速選舉(FastLeaderElection) |
16 | initLimit | Leader與learner創建鏈接中 socket通信read所阻塞的時間(initLimit * tickTime) 若是是Leaner數量較多或者leader的數量很大, 能夠增長此值 |
17 | SyncLimit | learner與leader創建鏈接中,socket通信read阻塞的時間.其中包括數據同步/數據提交等 |
18 | peerType | zkserver 類型 observer 觀察者, participant參與者 ,默認爲參與者 |
19 | leaderServes | 系統屬性 zookeeper.leaderServes leader是否接受client請求,默認爲yes即leader能夠接受client的鏈接,在zk cluster 環境中,當節點數爲>3時,建議關閉 |
20 | cnxTimeout | 系統屬性:zookeeper.cnxTimeout leader選舉時socket鏈接打開的時長,只有在electionAlg=3有效 |
21 | skipACL | 系統屬性:zookeeper.skipACL 默認爲no,是否跳過ACL檢查 |
22 | forceSync | 系統屬性:zookeeper.forceSync 默認yes 在update執行以前,是否強制對操做當即持久寫入txn log文件.關閉此選項,會形成服務器失效後,還沒有持久化的數據丟失 |
23 | jute.maxbuffer | 每一個節點最大數據量,是默認是1M。這個限制必須在server和client 端都進行設置纔會生效。 |
客戶端與服務端的一次會話鏈接,本質是TCP長鏈接,經過會話能夠進行心跳檢測和數據傳輸; 服務器
ZooKeeper的視圖結構和標準的Unix文件系統相似,其中每一個節點稱爲「數據節點」或ZNode,每一個znode能夠存儲數據,還能夠掛載子節點,所以能夠稱之爲「樹」網絡
特性:session
Zookeeper節點類型
對於持久接地啊和臨時節點,同一個Znode下,節點的名稱是惟一的 -實現分佈式鎖的基礎
Zookeeper節點狀態屬性
事件監聽器,客戶端能夠在節點上註冊監聽器,當特定的事件發生後,zk會通知到感興趣的客戶 端;eventType: NodeCreated、NodeDeleted、NodeDataChanged、NodeChildrenChange
Zk採用ACL(access control lists)策略來控制權限,5種權限:create、read,write,delete,admin。
ACL機制,表示爲scheme:id:permissions,第一個字段表示採用哪種機制,第二個id表示用戶,permissions表示相關權限(如只讀,讀寫,管理等)。zookeeper提供了以下幾種機制( scheme):
world: 它下面只有一個id, 叫anyone, world:anyone表明任何人,zookeeper中對全部人有權限的結點就是屬於world:anyone的
auth: 它不須要id, 只要是經過authentication的user都有權限(zookeeper支持經過kerberos來進行authencation, 也支持username/password形式的authentication)
digest: 它對應的id爲username:BASE64(SHA1(password)),它須要先經過username:password形式的authentication
ip: 它對應的id爲客戶機的IP地址,設置的時候能夠設置一個ip段,好比ip:192.168.1. 0/16, 表示匹配前16個bit的IP段
super: 在這種scheme狀況下,對應的id擁有超級權限,能夠作任何事情(cdrwa)
在準備好相應的配置以後能夠直接經過zkServer.sh 這個腳本進行服務的相關操做:
使用zkCli.sh -server 127.0.0.1:2181 鏈接到Zookeeper服務
ls/
複製代碼
ls2 /
複製代碼
查看當前節點數據並能看到更新次數等數據
create /zk "test"
複製代碼
建立一個新的znode節點「zk" 以及與它關聯的字符串
get /zk
複製代碼
確認znode是否包含建立的字符串
set /zk "zkbak"
複製代碼
對zk所關聯的字符串進行設置和修改
delete /zk
複製代碼
將建立的znode節點進行刪除,若是存在子節點則刪除會失敗
rmr /zk
複製代碼
將剛纔建立的znode刪除,同時刪除子節點
quit
複製代碼
help
複製代碼
獲取指定節點的ACL信息
設置指定節點的ACL信息
註冊會話受權信息
echo stat|nc 127.0.0.1 2181
複製代碼
echo ruok|nc 127.0.0.1 2181
複製代碼
echo kill | nc 127.0.0.1 2181
複製代碼
echo conf | nc 127.0.0.1 2181
複製代碼
echo cons | nc 127.0.0.1 2181
複製代碼
echo envi |nc 127.0.0.1 2181
複製代碼
echo reqs | nc 127.0.0.1 2181
複製代碼
echo wchs | nc 127.0.0.1 2181
複製代碼
echo wchc | nc 127.0.0.1 2181
複製代碼
echo wchp | nc 127.0.0.1 2181
複製代碼
java -cp ../../zookeeper-3.4.6.jar;../../lib/slf4j-api-1.6.1.jar org.apache.zookeeper.server.LogFormatter log.xxxx
複製代碼
java -cp ../../zookeeper-3.4.6.jar;../../lib/slf4j-api-1.6.1.jar org.apache.zookeeper.server.SnapshotFormatter snapshot.xxxx
複製代碼
zookeeper官方提供的java客戶端API;
核心API
public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher, long sessionId, byte[] sessionPasswd, boolean canBeReadOnly)
複製代碼
public String void create(final String path, byte data[], List<ACL> acl, CreateMode createMode, StringCallback cb, Object ctx)
複製代碼
public List<String> void getChildren(final String path, Watcher watcher, Stat stat, Children2Callback cb, Object ctx)
複製代碼
public List<String> void getData(final String path, Watcher watcher, Stat stat, DataCallback cb, Object ctx)
複製代碼
public Static void setData(final String path, byte data[], int version, StatCallback cb, Object ctx)
複製代碼
public Static void exists(final String path, Watcher watcher, StatCallback cb, Object ctx)
複製代碼
public void addAuthInfo(String scheme, byte auth[])
複製代碼
org.apache.zookeeper.Watcher(KeeperState、EventType)
(1)沒有專門的API去註冊watcher,依附於增刪改查API;
(2)watch是一次性產品
(3)watch的process方法中,可對不一樣事件進行處理;
原生客戶端開發弊端
開源的zk客戶端,在原生API基礎上封裝,是一個更易於使用的zookeeper客戶端; 引入Maven依賴
<!-- zkclient依賴 -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
複製代碼
核心API
public ZkClient(final String zkServers, final int sessionTimeout,final int connectionTimeout, final ZkSerializer zkSerializer, final long operationRetryTimeout)
複製代碼
String create(final String path, Object data, final CreateMode mode)
複製代碼
public void createPersistent(String path,boolean createParents,List<ACL> acl)
複製代碼
public void createPersistent(String path, Object data, List<ACL> acl)
複製代碼
public String createPersistentSequential(String path,Object data,List<ACL> acl)
複製代碼
public String createPersistentSequential(String path,Object data,List<ACL> acl
複製代碼
public String createEphemeralSequential(String path,Object data,List<ACL> acl)
複製代碼
public boolean delete(String path,int version)
複製代碼
public boolean deleteRecursive(String path)
複製代碼
public List<String> getChildren(String path)
複製代碼
public <T> T readData(String path, boolean returnNullIfPathNotExists)
複製代碼
public <T> T readData(String path, Stat stat)
複製代碼
public void writeData(String path, Object datat, int expectedVersion)
複製代碼
public Stat writeDataReturnStat(String path,Object datat,int expectedVersion)
複製代碼
public boolean exists(String path)
複製代碼
public void addAuthInfo(String scheme, final byte[] auth);
複製代碼
public void setAcl(final String path, final List<ACL> acl);
複製代碼
開源的zk客戶端,在原生API基礎上封裝,apache頂級項目;
<!-- curator依賴 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.0</version>
</dependency>
複製代碼
序列化支持很差
Curator 核心API
CuratorFrameworkFactory.newClient(String connectString, int sessionTimeoutM int connectionTimeoutMs, RetryPolicy retryPolicy)
複製代碼
CuratorFrameworkFactory.builder().connectString("192.168.11.56:2180")
.sessionTimeoutMs(30000).connectionTimeoutMs(30000)
.canBeReadOnly(false)
.retryPolicy(new ExponentialBackoffRetry(1000, Integer.MAX_VALUE))
.build();
複製代碼
retryPolicy 鏈接策略:
RetryOneTime: 只重連一次.
RetryNTime: 指定重連的次數N.
RetryUtilElapsed: 指定最大重連超時時間和重連時間間隔,間歇性重連直到超時或者連接成功.
ExponentialBackoffRetry: 基於"backoff"方式重連,和RetryUtilElapsed的區別是重連的時間間隔是動態
BoundedExponentialBackoffRetry: 同ExponentialBackoffRetry,增長了最大重試次數的控制.
複製代碼
client.create().creatingParentIfNeeded()
.withMode(CreateMode.PERSISTENT)
.withACL(aclList)
.forPath(path, "hello, zk".getBytes());
複製代碼
client.delete().guaranteed().deletingChildrenIfNeeded()
.withVersion(version).forPath(path)
複製代碼
client.getData().storingStatIn(stat).forPath(path);
client.getChildren().forPath(path);
複製代碼
client.setData().withVersion(version).forPath(path, data)
複製代碼
client.checkExists().forPath(path);
複製代碼
Build.authorization(String scheme, byte[] auth)
複製代碼
client.setACL().withVersion(version)
.withACL(ZooDefs.Ids.CREATOR_ALL_ACL)
.forPath(path);
複製代碼
Cache是curator中對事件監聽的包裝,對事件的監聽能夠近似看作是本地緩存視圖和遠程zk視圖的對比過程
- NodeCache 節點緩存用於處理節點自己的變化 ,回調接口NodeCacheListener
- PathChildrenCache 子節點緩存用於處理節點的子節點變化,回調接口 PathChildrenCacheListener
- TreeCache NodeCache和PathChildrenCache的結合體,回調接口TreeCacheListener
複製代碼
Collection<CuratorTransactionResult> results = client.transaction().forOperations(operations);
複製代碼
public void processResult(CuratorFramework client, CuratorEvent event)
CuratorEventType 事件類型
org.apache.zookeeper.KeeperException.Code
複製代碼