zookeeper咱們經常使用來作分佈式協調中間件,不少時候咱們都接觸不到它的原理和用法,我對他的瞭解也僅限於知道它能夠作分佈式協調、配置管理、分佈式鎖,而且有個watch節點監聽經常能聽到。接下來我要系統的學下zookeeper的功能和原理,一塊兒走進zookeeper的世界html
zookeeper主要目的就是爲了分佈式應用提供協同服務,zookeeper的節點管理機制,當節點發生變化時(建立、刪除、數據變動),能夠通知各個客戶端,利用這種特性,zk的主要場景就如我前面說的:java
1. 統一配置:把配置放在ZooKeeper的節點中維護,當配置變動時,客戶端能夠收到變動的通知,並應用最新的配置。 2. 集羣管理:集羣中的節點,建立ephemeral的節點,一旦斷開鏈接,ephemeral的節點會消失,其它的集羣機器能夠收到消息。 3. 分佈式鎖:多個客戶端發起節點建立操做,只有一個客戶端建立成功,從而得到鎖。
參考 https://blog.51cto.com/nileader/932948node
create [-s] [-e] path data acl
acl專門一節講git
[zk: localhost:2181(CONNECTED) 4] create -s -e /mynode/subnode hellp Node does not exist: /mynode/subnode [zk: localhost:2181(CONNECTED) 5] create -s -e /mynode/ hellp Node does not exist: /mynode/ [zk: localhost:2181(CONNECTED) 6] create -s -e /mynode hellp Created /mynode0000000001 [zk: localhost:2181(CONNECTED) 7] create -s -e /mynode/subnode hello Node does not exist: /mynode/subnode [zk: localhost:2181(CONNECTED) 8] ls /mynode Node does not exist: /mynode [zk: localhost:2181(CONNECTED) 9] ls / [mycat, mynode0000000001, zookeeper] [zk: localhost:2181(CONNECTED) 10] create -s -e /mynode0000000001/subnode hello Ephemerals cannot have children: /mynode0000000001/subnode
ls path [watch]
ls2 path [watch]
[zk: localhost:2181(CONNECTED) 17] ls2 /persistence [] cZxid = 0x12 ctime = Tue Mar 26 06:52:28 GMT 2019 mZxid = 0x12 mtime = Tue Mar 26 06:52:28 GMT 2019 pZxid = 0x12 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 3 numChildren = 0 [zk: localhost:2181(CONNECTED) 18] ls /persistence []
[zk: localhost:2181(CONNECTED) 2] ls / 1 [persistence, temporary, mycat, zookeeper] [zk: localhost:2181(CONNECTED) 3] create -e /temp 123 WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/ Created /temp [zk: localhost:2181(CONNECTED) 4] create -e /temp2 123 Created /temp2
get path [watch]
[zk: localhost:2181(CONNECTED) 5] get /temp2 123 cZxid = 0x17 ctime = Tue Mar 26 06:59:20 GMT 2019 mZxid = 0x17 mtime = Tue Mar 26 06:59:20 GMT 2019 pZxid = 0x17 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x103c831d4dc0003 dataLength = 3 numChildren = 0
stat path [watch]
set path data [version]
[zk: localhost:2181(CONNECTED) 10] set /temp2 456 cZxid = 0x17 ctime = Tue Mar 26 06:59:20 GMT 2019 mZxid = 0x18 mtime = Tue Mar 26 07:12:27 GMT 2019 pZxid = 0x17 cversion = 0 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x103c831d4dc0003 dataLength = 3 numChildren = 0
rmr path
[zk: localhost:2181(CONNECTED) 12] rmr /temp2 [zk: localhost:2181(CONNECTED) 13] get /temp2 Node does not exist: /temp2
delete path [version]
[zk: localhost:2181(CONNECTED) 17] create /per 1 Created /per [zk: localhost:2181(CONNECTED) 18] create /per/subper 2 Created /per/subper [zk: localhost:2181(CONNECTED) 19] delete /per Node not empty: /per [zk: localhost:2181(CONNECTED) 20] delete /per/subper [zk: localhost:2181(CONNECTED) 21] delete /per [zk: localhost:2181(CONNECTED) 22] ls /per Node does not exist: /per
history
列出最近的10條歷史記錄[zk: localhost:2181(CONNECTED) 23] history 13 - get /temp2 14 - ls / 15 - ls /temp 16 - get /temp 17 - create /per 1 18 - create /per/subper 2 19 - delete /per 20 - delete /per/subper 21 - delete /per 22 - ls /per 23 - history
redo cmdno
根據 cmdno 重複以前的命令,cmdno 就是方括號裏面最後的數字,每次執行命令都會自增。[zk: localhost:2181(CONNECTED) 25] redo 22 Node does not exist: /per [zk: localhost:2181(CONNECTED) 26] redo 17 Created /per
printwatches on|off
[zk: localhost:2181(CONNECTED) 28] printwatches printwatches is on [zk: localhost:2181(CONNECTED) 29] ls /mynode Node does not exist: /mynode [zk: localhost:2181(CONNECTED) 30] create /mynode 123 Created /mynode [zk: localhost:2181(CONNECTED) 31] ls /mynode watch [] [zk: localhost:2181(CONNECTED) 34] create /mynode/subnode 234 WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/mynode Created /mynode/subnode [zk: localhost:2181(CONNECTED) 35] printwatches off [zk: localhost:2181(CONNECTED) 36] ls /mynode 2 [subnode] [zk: localhost:2181(CONNECTED) 37] create /mynode/subnode2 567 Created /mynode/subnode2
close
[zk: localhost:2181(CONNECTED) 38] close 2019-03-26 07:26:59,240 [myid:] - INFO [main:ZooKeeper@693] - Session: 0x103c831d4dc0003 closed [zk: localhost:2181(CLOSED) 39] 2019-03-26 07:26:59,241 [myid:] - INFO [main-EventThread:ClientCnxn$EventThread@522] - EventThread shut down for session: 0x103c831d4dc0003 ls Not connected [zk: localhost:2181(CLOSED) 40] ls / Not connected
connect host:port
[zk: localhost:2181(CLOSED) 42] connect 2019-03-26 07:28:18,093 [myid:] - INFO [main:ZooKeeper@442] - Initiating client connection, connectString=localhost:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@782830e [zk: localhost:2181(CONNECTING) 43] 2019-03-26 07:28:18,096 [myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1029] - Opening socket connection to server localhost/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error) 2019-03-26 07:28:18,097 [myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@879] - Socket connection established to localhost/127.0.0.1:2181, initiating session 2019-03-26 07:28:18,100 [myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1303] - Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0x103c831d4dc0004, negotiated timeout = 30000 [zk: localhost:2181(CONNECTED) 43] ls / [mycat, mynode, zookeeper, persistence, per]
quit
直接退出當前的 zkCli 命令行。sync path
ACL 權限 | ACL 簡寫 | 容許的操做 |
---|---|---|
CREATE | c | 建立子節點 |
READ | r | 獲取節點的數據和它的子節點 |
WRITE | w | 設置節點的數據 |
DELETE | d | 刪除子節點 (僅下一級節點) |
ADMIN | a | 設置 ACL 權限 |
命令 | 語法 | 描述 |
---|---|---|
getAcl | getAcl path | 讀取ACL權限 |
setAcl | setAcl path acl | 設置ACL權限 |
addauth | addauth scheme auth | 添加認證用戶 |
create | create [-s] [-e] path data acl | 建立節點時指明 ACL 權限 |
方案 | 描述 |
---|---|
world | 只有一個用戶:anyone,表明全部人(默認) |
ip | 使用IP地址認證 |
auth | 使用已添加認證的用戶認證 |
digest | 使用「用戶名:密碼」方式認證 |
setAcl <path> world:anyone:<acl>
[zk: localhost:2181(CONNECTED) 7] getAcl /world 'world,'anyone : cdrwa [zk: localhost:2181(CONNECTED) 8] setAcl /world world:anyone:cdr cZxid = 0x27 ctime = Tue Mar 26 07:41:43 GMT 2019 mZxid = 0x27 mtime = Tue Mar 26 07:41:43 GMT 2019 pZxid = 0x27 cversion = 0 dataVersion = 0 aclVersion = 1 ephemeralOwner = 0x0 dataLength = 1 numChildren = 0 [zk: localhost:2181(CONNECTED) 9] set /world 234 Authentication is not valid : /world
setAcl <path> ip:<ip>:<acl>
[zk: localhost:2181(CONNECTED) 10] create /ip hello Created /ip [zk: localhost:2181(CONNECTED) 11] getAcl /ip 'world,'anyone : cdrwa [zk: localhost:2181(CONNECTED) 12] setAcl /ip ip:52.231.163.100:cdrwa cZxid = 0x2a ctime = Tue Mar 26 07:56:21 GMT 2019 mZxid = 0x2a mtime = Tue Mar 26 07:56:21 GMT 2019 pZxid = 0x2a cversion = 0 dataVersion = 0 aclVersion = 1 ephemeralOwner = 0x0 dataLength = 5 numChildren = 0 [zk: localhost:2181(CONNECTED) 13] getAcl /ip 'ip,'52.231.163.100 : cdrwa [zk: localhost:2181(CONNECTED) 14] get /ip Authentication is not valid : /ip
addauth digest <user>:<password> #添加認證用戶 setAcl <path> auth:<user>:<acl>
[zk: localhost:2181(CONNECTED) 15] create /auth hello Created /auth [zk: localhost:2181(CONNECTED) 16] addauth digest admin:tom [zk: localhost:2181(CONNECTED) 17] setAcl /auth auth:tom:cdrwa cZxid = 0x2c ctime = Tue Mar 26 08:04:23 GMT 2019 mZxid = 0x2c mtime = Tue Mar 26 08:04:23 GMT 2019 pZxid = 0x2c cversion = 0 dataVersion = 0 aclVersion = 1 ephemeralOwner = 0x0 dataLength = 5 numChildren = 0 [zk: localhost:2181(CONNECTED) 18] getAcl /auth 'digest,'admin:cFk4QI8k/ZVgHVEnb06Vtoc651o= : cdrwa
斷開之後再連上,須要從新認證github
WatchedEvent state:SyncConnected type:None path:null [zk: localhost:2181(CONNECTED) 0] get /auth Authentication is not valid : /auth
setAcl <path> digest:<user>:<password>:<acl>
這裏的密碼是通過SHA1及BASE64處理的密文,在SHELL中能夠經過如下命令計算:算法
echo -n
: apache| openssl dgst -binary -sha1 | openssl base64
[root@izbp1itlw36onyj4m9b4hiz ~]# echo -n admin:123456 | openssl dgst -binary -sha1 | openssl base64 0uek/hZ/V9fgiM35b0Z2226acMQ=
[zk: localhost:2181(CONNECTED) 21] create /digest hello Created /digest [zk: localhost:2181(CONNECTED) 22] setAcl /digest digest:admin:0uek/hZ/V9fgiM35b0Z2226acMQ=:cdrw cZxid = 0x39 ctime = Tue Mar 26 08:22:04 GMT 2019 mZxid = 0x39 mtime = Tue Mar 26 08:22:04 GMT 2019 pZxid = 0x39 cversion = 0 dataVersion = 0 aclVersion = 1 ephemeralOwner = 0x0 dataLength = 5 numChildren = 0 [zk: localhost:2181(CONNECTED) 23] getAcl /digest 'digest,'admin:0uek/hZ/V9fgiM35b0Z2226acMQ= : cdrw [zk: localhost:2181(CONNECTED) 24] get /digest Authentication is not valid : /digest [zk: localhost:2181(CONNECTED) 25] addauth digest admin:123456 [zk: localhost:2181(CONNECTED) 26] get /digest hello cZxid = 0x39 ctime = Tue Mar 26 08:22:04 GMT 2019 mZxid = 0x39 mtime = Tue Mar 26 08:22:04 GMT 2019 pZxid = 0x39 cversion = 0 dataVersion = 0 aclVersion = 1 ephemeralOwner = 0x0 dataLength = 5 numChildren = 0
[zk: localhost:2181(CONNECTED) 27] addauth digest admin:tim [zk: localhost:2181(CONNECTED) 28] create /createnode hello auth:tim:cdrwa Created /createnode [zk: localhost:2181(CONNECTED) 29] getAcl [zk: localhost:2181(CONNECTED) 30] getAcl /createnode 'digest,'admin:0uek/hZ/V9fgiM35b0Z2226acMQ= : cdrwa 'digest,'admin:H4JbicQawMpoqvA2LI0LFNFSMNE= : cdrwa [zk: localhost:2181(CONNECTED) 31] get /createnode hello cZxid = 0x3b ctime = Tue Mar 26 08:27:27 GMT 2019 mZxid = 0x3b mtime = Tue Mar 26 08:27:27 GMT 2019 pZxid = 0x3b cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 5 numChildren = 0 [zk: localhost:2181(CONNECTED) 32] close [zk: localhost:2181(CLOSED) 33] connect [zk: localhost:2181(CONNECTED) 34] get /createnode Authentication is not valid : /createnode [zk: localhost:2181(CONNECTED) 35] getAcl /createnode 'digest,'admin:0uek/hZ/V9fgiM35b0Z2226acMQ= : cdrwa 'digest,'admin:H4JbicQawMpoqvA2LI0LFNFSMNE= : cdrwa [zk: localhost:2181(CONNECTED) 36] addauth digest admin:tim [zk: localhost:2181(CONNECTED) 37] get /createnode hello cZxid = 0x3b ctime = Tue Mar 26 08:27:27 GMT 2019 mZxid = 0x3b mtime = Tue Mar 26 08:27:27 GMT 2019 pZxid = 0x3b cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 5 numChildren = 0
listquota path
、setquota -n|-b val path
、delquota [-n|-b] path
[zk: localhost:2181(CONNECTED) 10] ls /zookeeper/quota [] [zk: localhost:2181(CONNECTED) 11] get /zookeeper/quota cZxid = 0x0 ctime = Thu Jan 01 00:00:00 GMT 1970 mZxid = 0x0 mtime = Thu Jan 01 00:00:00 GMT 1970 pZxid = 0x0 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 0 numChildren = 0 [zk: localhost:2181(CONNECTED) 12] listquota /persistence absolute path is /zookeeper/quota/persistence/zookeeper_limits quota for /persistence does not exist. [zk: localhost:2181(CONNECTED) 13] setquota -n 3 /persistence Comment: the parts are option -n val 3 path /persistence [zk: localhost:2181(CONNECTED) 14] create /persistence/node1 123 Created /persistence/node1 [zk: localhost:2181(CONNECTED) 15] create /persistence/node2 124 Created /persistence/node2 [zk: localhost:2181(CONNECTED) 16] create /persistence/node3 125 Created /persistence/node3 [zk: localhost:2181(CONNECTED) 17] listquota /persistence absolute path is /zookeeper/quota/persistence/zookeeper_limits Output quota for /persistence count=3,bytes=-1 Output stat for /persistence count=4,bytes=12
[zk: localhost:2181(CONNECTED) 18] delquota -n /persistence [zk: localhost:2181(CONNECTED) 19] listquota /persistence absolute path is /zookeeper/quota/persistence/zookeeper_limits Output quota for /persistence count=-1,bytes=-1 Output stat for /persistence count=4,bytes=12
主流異步操做api
參考 https://github.com/llohellohe/zookeeper/blob/master/src/main/java/yangqi/zookeeper/example/masterworker/AsynMaster.java服務器
public void process(WatchedEvent event)
public void processResult(int rc, String path, Object ctx, List<String> children)
@Override public Set<Watcher> materialize(Watcher.Event.KeeperState state, Watcher.Event.EventType type, String clientPath) { Set<Watcher> result = new HashSet<Watcher>(); switch (type) { case None://初始化鏈接時進入 result.add(defaultWatcher);//defaultWatcher若是填空,後續會報錯
private void processEvent(Object event) { try { if (event instanceof WatcherSetEventPair) { // each watcher will process the event WatcherSetEventPair pair = (WatcherSetEventPair) event; for (Watcher watcher : pair.watchers) { try { watcher.process(pair.event);//watcher爲null
zk.create("/mypath", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zkc.create().withMode(CreateMode.PERSISTENT).forPath("/mypath", new byte[0]);
在ZK集羣中,Leader的做用是保證變動操做(create\setData\delete)的順序性。
它將接收到的請求轉換成事務,而後提議followers按照順序應用這些事務。在初始階段,全部的ZK服務端都處於LOOKING狀態,要麼找到已經存在Leader結點,要麼本身選舉出Leader。成爲Leader的節點將進入LEADING狀態,其它則將進入FOLLOWING狀態。網絡
192.168.0.1:2181/app/X
protected int electionAlg = 3;
case 3: qcm = createCnxnManager(); QuorumCnxManager.Listener listener = qcm.listener; if(listener != null){ listener.start(); le = new FastLeaderElection(this, qcm); } else { LOG.error("Null listener when initializing cnx manager"); } break;
參考
https://blog.csdn.net/feixiang2039/article/details/79810102#zookeeper-%E5%91%BD%E4%BB%A4 zookeeper 客戶端 zkCli 命令詳解
https://github.com/llohellohe/llohellohe.github.com/blob/master/readers/ZooKeeper llohellohe/llohellohe.github.com
http://www.cnblogs.com/leesf456/p/6098255.html Zookeeper客戶端
https://blog.csdn.net/cxhzqhzq/article/details/6568040 Zookeeper全解析——Paxos做爲靈魂
http://blog.chinaunix.net/uid-26726125-id-4038581.html zookeeper跟經典paxos的對比(附源碼)
https://blog.csdn.net/panxj856856/article/details/80403487 FastLeaderElection選舉算法