分布式之Zookeeper一(分布式鎖與Zookeeper集群)

說到分布式開發(fā),不得不說的就是zookeeper了;zookeeper官網(wǎng)說到Apache ZooKeeper致力于開發(fā)和維護(hù)可實(shí)現(xiàn)高度可靠的分布式協(xié)調(diào)的開源服務(wù)器。那么zk作為一個(gè)協(xié)調(diào)者的存在,是分布式比不可少的一部分。廢話不多說,直接上干貨

成都創(chuàng)新互聯(lián)擁有一支富有激情的企業(yè)網(wǎng)站制作團(tuán)隊(duì),在互聯(lián)網(wǎng)網(wǎng)站建設(shè)行業(yè)深耕十載,專業(yè)且經(jīng)驗(yàn)豐富。十載網(wǎng)站優(yōu)化營銷經(jīng)驗(yàn),我們已為上1000+中小企業(yè)提供了網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)解決方案,按需求定制制作,設(shè)計(jì)滿意,售后服務(wù)無憂。所有客戶皆提供一年免費(fèi)網(wǎng)站維護(hù)!

Zookeeper(https://zookeeper.apache.org/)的安裝包可以直接在官網(wǎng)上獲取,https://zookeeper.apache.org/doc/current/zookeeperStarted.html這里有Zookeeper的一些常用的簡單命令,我們可以嘗試著去試試它。

下面來說分布式鎖,它用到的場景;比如:我們常說的驚群效應(yīng)、Zookeeper集群爭先讀取緩存等。這里可能有人提到用redis實(shí)現(xiàn)的分布式鎖,其實(shí)對比redis和Zookeeper的官網(wǎng)敘述,我們就能清晰的發(fā)現(xiàn):Zookeeper比Redis更適合去做分布式鎖。Zookeeper的擔(dān)保第一條就是它的順序性和一致性,其次是它的原子性。大家也可以詳細(xì)的去了解一下。再分清楚這些之后,我們可以試著思考下Zookeeper它是怎么去實(shí)現(xiàn)的分布式鎖?根據(jù)什么去實(shí)現(xiàn)的?

可以想到如何獲取到Zookeeper的每個(gè)節(jié)點(diǎn)以及子節(jié)點(diǎn)變化,Zookeeper的Watch機(jī)制充分的實(shí)現(xiàn)了這一點(diǎn)。通過Watch機(jī)制可以清晰的監(jiān)聽到Zookeeper的每個(gè)節(jié)點(diǎn)的變化。自然而然的這里也要用到Zookeeper的第三方客戶端。Zookeeper的第三方客戶端有兩個(gè);一個(gè)是zkclient、一個(gè)是curator。在curator中它自己已經(jīng)實(shí)現(xiàn)了分布式鎖,感興趣的可以去看看它的實(shí)現(xiàn)源碼。

在第三方客戶端連接到Zookeeper之后,就可以開始實(shí)現(xiàn)分布式鎖了。鎖的排他性、堵塞性、可重入性。排他性zk默認(rèn)就實(shí)現(xiàn)了,zk的節(jié)點(diǎn)必須是唯一的。分布式鎖采用Zookeeper的臨時(shí)順序節(jié)點(diǎn)來實(shí)現(xiàn),首先獲取鎖,創(chuàng)建一個(gè)Zookeeper的臨時(shí)順序節(jié)點(diǎn);然后需要一個(gè)柵欄(CountDownLatch),確保所有人都拿到自己的編號,即在同一起跑線上。然后開始搶鎖,給一個(gè)發(fā)令槍(CountDown)。然后搶到鎖的就去執(zhí)行自己的業(yè)務(wù),watch再次監(jiān)聽節(jié)點(diǎn)數(shù)據(jù)變化,然后請求線程去進(jìn)行阻塞等待,接下來再刪除節(jié)點(diǎn),釋放鎖。

public boolean tryLock() {

        if(currentPath.get() == null || !client.exists(currentPath.get())) {
            String node = client.createEphemeralSequential(LockPath+"/", "locked");
            currentPath.set(node);
        }

        List<String> children =client.getChildren(LockPath);
        // 排序list
        Collections.sort(children);

        // 判斷當(dāng)前節(jié)點(diǎn)是否是最小的
        if(currentPath.get().equals(LockPath+"/"+children.get(0))) {
            return true;
        }else {

            int curIndex = children.indexOf(currentPath.get().substring(LockPath.length() + 1));
            String bnode = LockPath+"/"+children.get(curIndex -1);
            beforePath.set(bnode);
        }
        return false;
    }

    public void lock() {
        if(! tryLock()) {
            // 阻塞等待鎖的釋放
            waitForLock();
            // 重新?lián)屾i
            lock();
        }
    }
    private void waitForLock() {

        CountDownLatch cdl = new CountDownLatch(1);
        // 用zkwatcher事件來通知
            IZkDataListener listener = new IZkDataListener() {

            public void handleDataDeleted(String dataPath) throws Exception {
                System.out.println("================zk節(jié)點(diǎn)被刪除================");
                cdl.countDown();
            }

            public void handleDataChange(String dataPath, Object data) throws Exception {
            }
        };
        // watcher /zk 數(shù)據(jù)變化
        client.subscribeDataChanges(beforePath.get(), listener);

        // 請求線程去進(jìn)行阻塞等待
        if(client.exists(beforePath.get())) {
            try {
                cdl.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 取消注冊事件
        client.unsubscribeDataChanges(beforePath.get(), listener);
    }

至此一個(gè)分布式鎖就實(shí)現(xiàn)了。

接下來說Zookeeper的偽集群。搭建的時(shí)候需要注意的情況:
1、DataDir的位置。
2、Zookeeper的端口號
3、myid文件,myid文件是創(chuàng)建在DataDir目錄下的,myid文件就是給一個(gè)id數(shù),id數(shù)需與server.1 ... 后邊的編號一致。
然后分別啟動(dòng)三臺服務(wù)器,注意看服務(wù)器輸出的日志消息。不出意外的話Zookeeper的集群就可以搭建成功了!

網(wǎng)站名稱:分布式之Zookeeper一(分布式鎖與Zookeeper集群)
鏈接URL:http://bm7419.com/article14/jjcjge.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站建設(shè)商城網(wǎng)站、用戶體驗(yàn)、電子商務(wù)、域名注冊、網(wǎng)站導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)