zookeeper實(shí)現(xiàn)分布式鎖

分布式鎖有多重實(shí)現(xiàn)方式,比如數(shù)據(jù)庫 、 redis都可以實(shí)現(xiàn)莲镣。作為分布式協(xié)同工具zookeeper也可以實(shí)現(xiàn)分布式鎖曙强。

1残拐、實(shí)現(xiàn)思路

  1. 每個(gè)客戶端往/Locks下創(chuàng)建臨時(shí)有序節(jié)點(diǎn),/Locks/Lock_ 創(chuàng)建成功后/Locks下面會(huì)有每個(gè)客戶端對(duì)應(yīng)的節(jié)點(diǎn)碟嘴,比如 /Locks/Lock_000001
  2. 客戶端取得/Locks下的子節(jié)點(diǎn)溪食,并進(jìn)行排序,判斷在最前面的是否為自己娜扇,如果自己的鎖節(jié)點(diǎn)在第一位错沃,代表獲得鎖成功。
  3. 如果自己的鎖節(jié)點(diǎn)不再第一位雀瓢,則監(jiān)聽自己前一位的鎖節(jié)點(diǎn)枢析。例如, 自己鎖節(jié)點(diǎn)/Lock_000002刃麸,那么則監(jiān)聽Lock_000001
  4. 當(dāng)前一位鎖節(jié)點(diǎn)(Lock_000001)對(duì)應(yīng)的客戶端執(zhí)行完成醒叁,釋放鎖,將會(huì)觸發(fā)監(jiān)聽客戶端(Lock_0000002) 的邏輯
  5. 監(jiān)聽客戶端重新執(zhí)行第2步邏輯泊业,判斷自己是否獲得了鎖

監(jiān)聽機(jī)制把沼,臨時(shí)有序節(jié)點(diǎn)



public class Mylock{
    //zk的連接串
    String IP = "127.0.0.1:2181";
   //計(jì)數(shù)器對(duì)象
   CountDownLatch countDownLatch = new CountDownLatch(1);
   
   //zk配置信息
   Zookeeper zooKeeper;
   private static final String LOCK_ROOT_PATH = "/Locks";
    private static final String LOCK_NODE_PATH = "Lock_";
    
    private String lockPath;
    
    //打開zookeeper的鏈接
    public MyLock(){
        try{
        zooKeeper = new ZooKeeper(IP,5000,new watcher(){
            @Override
            public void process(WatchedEvent event){
                if(event.getType==Event.EventType.None){
                  if(event.getState()==Event.KeeperState.SyncConnected){
                      System.out.println("連接創(chuàng)建成功~~~");
                      countDownLatch.countDown();
                  }
                }
            }
        });
        countDownLatch.await();
            
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    
    
    
public void acquireLock() throws Exception{
    //創(chuàng)建鎖節(jié)點(diǎn)
    createLock();
    //嘗試獲取鎖
    attempLock();
}

//創(chuàng)建鎖節(jié)點(diǎn)
public void createLock() throws Exception{
    //1、打開zookeeper連接

    //2吁伺、創(chuàng)建Locks根節(jié)點(diǎn)(創(chuàng)建前先用exit判斷是否存在饮睬,不存在創(chuàng)建)
   Stat stat =  zooKeeper.exists(LOCK_ROOT_PATH,false);
    if(stat == null){
        zooKeeper.create(LOCK_ROOT_PATH,new byte[0],ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
    }
    
   // 3、創(chuàng)建臨時(shí)有序節(jié)點(diǎn)
  lockPath = zooKeeper.create(LOCK_ROOT_PATH + "/" +LOCK_NODE_PATH,new byte[0] ,
             ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
 
 System.out.println("創(chuàng)建節(jié)點(diǎn)成功~~~" + lockPath);
 //進(jìn)行測(cè)試一下~~箱蝠,看看我們的代碼是否有問題~~
}
    
}

  • 嘗試獲取鎖
//監(jiān)視器對(duì)象续捂,監(jiān)視上一個(gè)節(jié)點(diǎn)是否被刪除\
Watcher watcher = new Watcher(){
    @Override
    public void proccess(WatcherEvent event){
        if(event.getType()==EventType.NodeDeleted){
            sychronized(this){
                notifyAll();
            }
        }
    }
}



private void attempLock() throws Exception{

//1垦垂、獲取locks下的所有子節(jié)點(diǎn) 

List<String> list = zookeeper.getChildren(LOCK_ROOT_PATH,false);

//2、對(duì)子節(jié)點(diǎn)進(jìn)行排序

Collections.sort(list);


//3牙瓢、截取掉前面部分

int index = list.indexOf(lockPath.substring(LOCK_ROOT_PATH.length()+1));

//4劫拗、對(duì)索引進(jìn)行判斷
if(index == 0) {
    System.out.ptintln("說明是第1位,獲取鎖成功矾克!")
    return;
}eles{
    //獲取上一個(gè)節(jié)點(diǎn)的路徑
    String path = list.get(index-1);
    //監(jiān)視上一個(gè)節(jié)點(diǎn)
    Stat stat = zookeeper.exists(LOCk_ROOT_PATH+"/"+path,watcher); //監(jiān)視器對(duì)象页慷,監(jiān)視上一個(gè)節(jié)點(diǎn)是否被刪除
    
    if(stat==null){
        //回調(diào),嘗試重新獲得鎖
        attempLock();
    }else{
        //阻塞等待
        synchronized(watcher){
            watcher.wait();
        }
        
        attempLock();
    }
}

}
  • 釋放鎖
public void releaseLock() throws Exception{
    //刪除臨時(shí)有序節(jié)點(diǎn)
    zooKeeper.delete(this.lockPath,-1);
    zooKeeper.close();
    System.out.println("鎖已經(jīng)釋放了~~~);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末胁附,一起剝皮案震驚了整個(gè)濱河市酒繁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌控妻,老刑警劉巖州袒,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異弓候,居然都是意外死亡郎哭,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門菇存,熙熙樓的掌柜王于貴愁眉苦臉地迎上來夸研,“玉大人,你說我怎么就攤上這事依鸥『ブ粒” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵贱迟,是天一觀的道長(zhǎng)姐扮。 經(jīng)常有香客問我,道長(zhǎng)关筒,這世上最難降的妖魔是什么溶握? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任杯缺,我火速辦了婚禮蒸播,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘萍肆。我一直安慰自己袍榆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布塘揣。 她就那樣靜靜地躺著包雀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪亲铡。 梳的紋絲不亂的頭發(fā)上才写,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天葡兑,我揣著相機(jī)與錄音,去河邊找鬼赞草。 笑死讹堤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的厨疙。 我是一名探鬼主播洲守,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼沾凄!你這毒婦竟也來了梗醇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤撒蟀,失蹤者是張志新(化名)和其女友劉穎叙谨,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體保屯,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡唉俗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了配椭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片虫溜。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖股缸,靈堂內(nèi)的尸體忽然破棺而出衡楞,到底是詐尸還是另有隱情,我是刑警寧澤敦姻,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布瘾境,位于F島的核電站,受9級(jí)特大地震影響镰惦,放射性物質(zhì)發(fā)生泄漏迷守。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一旺入、第九天 我趴在偏房一處隱蔽的房頂上張望兑凿。 院中可真熱鬧,春花似錦茵瘾、人聲如沸礼华。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽圣絮。三九已至,卻和暖如春雕旨,著一層夾襖步出監(jiān)牢的瞬間扮匠,已是汗流浹背捧请。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棒搜,地道東北人血久。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像帮非,于是被迫代替她去往敵國和親氧吐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355