簡單的說,zookeeper就是爲了解決集羣環境中數據一致性的問題。服務器
舉個很簡單栗子:多線程
有一個變量A,分別存在於兩臺服務器中,某個程序須要用到變量A,就隨機地訪問其中一臺服務器並取得變量A的值,對吧?如今有兩個客戶端分別修改兩臺服務器上的變量A,其中一個客戶端把其中一臺服務器的變量A的值修改成1,另外一個客戶端把另外一臺服務器的變量A修改成2。那麼以後,程序訪問取得這個變量的值,究竟是1仍是2呢?zookeeper就是爲了解決這種問題的。ide
本文主要是講一個demo,利用zookeeper的特性來實現一個互斥鎖,原理性的東西本文不贅述。函數
咱們用多線程的方式來模擬多個客戶端爭搶鎖,線程類代碼以下:spa
public class Thread1 implements Runnable { ZooKeeper zk = null; @Override public void run() { try { zk = new ZooKeeper("127.0.0.1:2181", 2000, new Watcher() { @Override public void process(WatchedEvent event) { // 獲取事件類型 String type = event.getType().toString(); /** * 咱們使用節點/lock/mylock爲鎖的標誌 * 事件類型爲「None」表示線程剛啓動,線程啓動後就當即去搶鎖 * 事件類型爲「NodeDeleted」表示有節點被刪除了 * ,也就表示有線程釋放鎖了,當前線程獲得事件通知後就當即搶鎖 * 。if塊裏面的代碼都是搶鎖、處理業務邏輯、釋放鎖這個流程 */ if ("None".equals(type) || ("NodeDeleted".equals(type) && event.getPath().equals("/lock/mylock"))) { try { // 建立一個/lock/mylock節點,即執行搶鎖。若是節點建立失敗,則會拋出一個異常,進入下面的catch塊中 zk.create("/lock/mylock", new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); // 繼續監控/lock/mylock節點的變化狀況,由於zookeeper的watcher是一次性的,因此用完後要從新watch zk.exists("/lock/mylock", true); // /lock/mylock節點建立成功,表示搶到了鎖 System.out.println("----------------------------------"); System.out.println(Thread.currentThread().getName() + "搶到鎖了"); System.out.println(Thread.currentThread().getName() + "處理業務邏輯……"); Thread.sleep(2000); // 刪除/lock/mylock節點,釋放鎖,以後全部的watch這個節點的線程都會收到事件通知,從而當即搶鎖 zk.delete("/lock/mylock", -1); System.out.println(Thread.currentThread().getName() + "已釋放鎖"); } catch (Exception e) { System.out.println(Thread.currentThread().getName() + "沒搶到鎖"); try { // 搶鎖失敗,繼續監控鎖標誌節點的變化狀況 zk.exists("/lock/mylock", true); } catch (Exception e1) { e1.printStackTrace(); } } } } }); } catch (Exception e) { e.printStackTrace(); } }
main函數代碼以下:線程
for (int i = 0; i < 5; i++) { new Thread(new Thread1()).start(); } System.in.read();
運行結果:code
Thread-3-EventThread搶到鎖了 Thread-3-EventThread處理業務邏輯…… Thread-2-EventThread沒搶到鎖 Thread-4-EventThread沒搶到鎖 Thread-0-EventThread沒搶到鎖 Thread-1-EventThread沒搶到鎖 Thread-3-EventThread已釋放鎖 ---------------------------------- Thread-2-EventThread沒搶到鎖 Thread-0-EventThread沒搶到鎖 Thread-1-EventThread沒搶到鎖 Thread-3-EventThread沒搶到鎖 Thread-4-EventThread搶到鎖了 Thread-4-EventThread處理業務邏輯…… Thread-4-EventThread已釋放鎖 ---------------------------------- Thread-3-EventThread沒搶到鎖 Thread-1-EventThread沒搶到鎖 Thread-2-EventThread沒搶到鎖 Thread-4-EventThread沒搶到鎖 Thread-0-EventThread搶到鎖了 Thread-0-EventThread處理業務邏輯…… Thread-0-EventThread已釋放鎖 ---------------------------------- Thread-4-EventThread沒搶到鎖 Thread-3-EventThread沒搶到鎖 Thread-2-EventThread沒搶到鎖 Thread-0-EventThread沒搶到鎖 Thread-1-EventThread搶到鎖了 Thread-1-EventThread處理業務邏輯…… Thread-1-EventThread已釋放鎖 ---------------------------------- Thread-0-EventThread沒搶到鎖 Thread-2-EventThread沒搶到鎖 Thread-4-EventThread沒搶到鎖 Thread-1-EventThread沒搶到鎖 Thread-3-EventThread搶到鎖了 Thread-3-EventThread處理業務邏輯…… Thread-3-EventThread已釋放鎖 ---------------------------------- Thread-0-EventThread沒搶到鎖 Thread-4-EventThread沒搶到鎖 Thread-2-EventThread沒搶到鎖 Thread-3-EventThread沒搶到鎖 Thread-1-EventThread搶到鎖了 Thread-1-EventThread處理業務邏輯…… Thread-1-EventThread已釋放鎖 ---------------------------------- Thread-3-EventThread沒搶到鎖 Thread-2-EventThread沒搶到鎖 Thread-4-EventThread沒搶到鎖 Thread-1-EventThread沒搶到鎖 Thread-0-EventThread搶到鎖了 Thread-0-EventThread處理業務邏輯…… Thread-0-EventThread已釋放鎖 ---------------------------------- Thread-2-EventThread沒搶到鎖 Thread-0-EventThread沒搶到鎖 Thread-4-EventThread沒搶到鎖 Thread-1-EventThread沒搶到鎖 Thread-3-EventThread搶到鎖了 Thread-3-EventThread處理業務邏輯…… Thread-3-EventThread已釋放鎖 ---------------------------------- Thread-0-EventThread沒搶到鎖 Thread-2-EventThread沒搶到鎖 Thread-3-EventThread沒搶到鎖 Thread-1-EventThread搶到鎖了 Thread-1-EventThread處理業務邏輯…… Thread-4-EventThread沒搶到鎖
咱們能夠看到每次只有一個線程獲取到了鎖,並處理業務邏輯blog