集中式 向 分佈式演變,高併發、海量存儲java
應用場景:apache
* 數據發佈、訂閱的兩種方式:推模式、拉模式 * 命名服務 * 分佈式協調/通知(心跳檢測) * 負載均衡
自增加id和uuid的缺點,前者只能在單表中使用,後者可在分佈式環境使用,但不易於理解、尋找規律api
一、集羣中的角色:服務器
* Leader * Follower * Observer
二、會話併發
客戶端與Zookeeper的鏈接,其鏈接是經過TCP長鏈接,保持會話,客戶端會向Zookeeper端上報心跳。會話也被叫作Session
三、版本負載均衡
版本的做用是進行分佈式鎖控制,鎖分爲兩種,悲觀鎖和樂觀鎖 悲觀鎖適合併發競爭激烈的場景,能避免數據不一致的狀況,上一個事務沒完成,下一個事務不能開始。樂觀鎖的併發控制是,加入版本號,每次讀取記錄時首先會得到版本號,插入數據時,也會將版本號帶到參數中,若更新失敗,說明其餘事務已經修改過數據,會拋出異常給客戶端,讓其進行處理(重試) version 當前數據內容節點版本號 cversion 當前數據子節點版本號 aversion 當前數據節點ACL變動版本號
四、節點分佈式
服務器(節點)
數據模型中的節點高併發
五、watcher測試
客戶端能夠在zookeeper中註冊watcher,當zookpeer上的內容改變時,會通知客戶端獲取ui
六、ACL權限控制
CREATE 建立子節點的權限
READ 讀取節點數據、子節點列表的權限
WRITE 更新節點數據的權限
DELETE 刪除子節點的權限
ADMIN 設置節點ACL權限
一、建立文件夾
/opt 用來安裝本身的應用軟件
/var 用來存放日誌輸出
二、下載zookeeper
wget 下載連接
三、進行配置
(1)修改Zoo.cfg
dataDir 是用來存放數據快照
clientPort 對外提供的端口號,默認2181
server.id=ip:port:port
server.1=ip:port:port
server.2=ip:port:port
server.3=ip:port:port
(2)在/var/zookeeper中建立myid,內容爲id編號,如1
四、啓動
export ZK_HOME = /../zookeeper
export PATH=\(PATH:\)ZK_HOME/bin
Zookeeper/bin zkServer.sh start
telnet ip port(2181)
輸入 stat 查看狀態
一、啓動客戶端鏈接到服務器
zkCli.sh -server serverip:2181
help quit ls / //列出節點 create /path content get /path //查看數據 set /path conent //設置數據 delete /path //刪除一個節點 rmr /a //遞歸刪除全部節點
一、獲取根下的目錄
(1) 導入依賴包
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.9</version> </dependency>
(2)測試代碼
fonxian1 對應的是zk服務器的ip地址
@org.junit.Test public void ls() throws Exception{ ZooKeeper zk = new ZooKeeper("fonxian1:2181",10000,null); List<String> list = zk.getChildren("/",false); for(String str:list){ System.out.println(str); } }
二、遞歸獲取根下全部文件名
@org.junit.Test public void lsAll() { try { ls("/"); } catch (Exception e) { e.printStackTrace(); } } public void ls(String path) throws Exception { ZooKeeper zk = new ZooKeeper("fonxian1:2181", 10000, null); List<String> list = zk.getChildren(path, false); if (list == null || list.isEmpty()) { return; } for (String str : list) { if ("/".equals(path)) { System.out.println(path + str); ls(path + str); } else { System.out.println(path + "/" + str); ls(path + "/" + str); } } }
三、添加數據
@org.junit.Test public void setData () { try{ ZooKeeper zk = new ZooKeeper("fonxian1:2181", 10000, null); zk.setData("/a","fonxian".getBytes(),2); }catch (Exception e){ e.printStackTrace(); } }
出現版本號錯誤的提示
org.apache.zookeeper.KeeperException$BadVersionException: KeeperErrorCode = BadVersion for /a at org.apache.zookeeper.KeeperException.create(KeeperException.java:115) at org.apache.zookeeper.KeeperException.create(KeeperException.java:51) at org.apache.zookeeper.ZooKeeper.setData(ZooKeeper.java:1327) at com.fonxian.ZookeepTest.setData(ZookeepTest.java:47)
緣由是Zookeeper服務器中/a的版本號爲0,將代碼中的版本號設置爲0,便可執行成功
[zk: 127.0.0.1(CONNECTED) 0] get /a tom cZxid = 0x200000002 ctime = Sun Mar 18 15:49:45 CST 2018 mZxid = 0x200000002 mtime = Sun Mar 18 15:49:45 CST 2018 pZxid = 0x20000000f cversion = 3 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 3 numChildren = 3
四、添加臨時節點
create [-s] [-e] path data acl
參數s ,表示序列節點,會在父節點下建立一個10個0+父節點名的節點
參數e,表示臨時節點,臨時節點在會話結束時會被刪除,在leader選舉中扮演重要做用
@Test public void setTempData() { try { ZooKeeper zk = new ZooKeeper("fonxian1:2181", 10000, null); zk.create("/a/t","fonxian".getBytes(), ZooDefs.Ids.READ_ACL_UNSAFE, CreateMode.EPHEMERAL); System.out.println("hello"); } catch (Exception e) { e.printStackTrace(); } }
五、使用觀察者
觀察者的做用在於,當數據發生修改,服務器會通知客戶端數據修改,每次註冊,只會通知一次。
@Test public void testWatch(){ try { final ZooKeeper zk = new ZooKeeper("fonxian1:2181", 50000, null); Watcher w = new Watcher() { public void process(WatchedEvent watchedEvent) { try{ System.out.println("data change"); byte[] newData = zk.getData("/a",this,null); System.out.println("new data = "+new String(newData)); }catch (Exception e){ e.printStackTrace(); } } } ; byte[] data = zk.getData("/a",w,null); System.out.println(new String(data)); while(true){ } } catch (Exception e) { e.printStackTrace(); } }