欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Zookeeper實(shí)現(xiàn)分布式鎖代碼實(shí)例

 更新時(shí)間:2023年12月07日 09:47:01   作者:外星喵  
這篇文章主要介紹了Zookeeper實(shí)現(xiàn)分布式鎖代碼實(shí)例,Zookeeper?分布式鎖應(yīng)用了其?臨時(shí)順序節(jié)點(diǎn)?的特性,在Zookeeper中創(chuàng)建一個(gè)持久節(jié)點(diǎn)ParentLock,當(dāng)?shù)谝粋€(gè)客戶(hù)端要獲取鎖時(shí),在ParentLock節(jié)點(diǎn)下創(chuàng)建一個(gè)臨時(shí)順序節(jié)點(diǎn),需要的朋友可以參考下

Zookeeper分布式鎖原理

在這里插入圖片描述

臨時(shí)順序節(jié)點(diǎn)

該類(lèi)型的節(jié)點(diǎn)創(chuàng)建完成之后,若客戶(hù)端與服務(wù)端斷開(kāi)連接之前沒(méi)有執(zhí)行delete操作,Zookeeper會(huì)自動(dòng)刪除該類(lèi)型的節(jié)點(diǎn),同時(shí)該類(lèi)型的節(jié)點(diǎn)創(chuàng)建之后,Zookeeper會(huì)為該類(lèi)型的節(jié)點(diǎn)在節(jié)點(diǎn)名稱(chēng)的基礎(chǔ)上增加一個(gè)單調(diào)遞增的編號(hào);

Zookeeper 分布式鎖應(yīng)用了其 臨時(shí)順序節(jié)點(diǎn) 的特性。實(shí)現(xiàn)步驟如下:

獲取鎖

首先在Zookeeper中創(chuàng)建一個(gè)持久節(jié)點(diǎn)ParentLock,當(dāng)?shù)谝粋€(gè)客戶(hù)端要獲取鎖時(shí),在ParentLock節(jié)點(diǎn)下創(chuàng)建一個(gè)臨時(shí)順序節(jié)點(diǎn)Lock1;

接下來(lái)客戶(hù)端1會(huì)獲取ParentLock下的所有臨時(shí)順序子節(jié)點(diǎn)并進(jìn)行排序,然后與自身創(chuàng)建的Lock1比較,判斷Lock1是不是最小的(最靠前的),如果是最靠前的,則獲取鎖成功;

此時(shí),假設(shè)又有一個(gè)客戶(hù)端2前來(lái)獲取鎖,則在ParentLock下創(chuàng)建一個(gè)臨時(shí)順序節(jié)點(diǎn)Lock2;

接下來(lái)客戶(hù)端2會(huì)獲取ParentLock下的所有臨時(shí)順序子節(jié)點(diǎn)并進(jìn)行排序,然后與自身創(chuàng)建的Lock2比較,判斷Lock2是不是最小的(最靠前的),結(jié)果發(fā)現(xiàn)Lock2不是最小的;

于是,Lock2向排序比它靠前的第一個(gè)節(jié)點(diǎn)Lock1注冊(cè)一個(gè)Watcher,用于監(jiān)聽(tīng)Lock1是否存在,此時(shí)意味著客戶(hù)端2搶鎖失敗,客戶(hù)端2進(jìn)入等待狀態(tài);

此時(shí),假設(shè)現(xiàn)在又有一個(gè)客戶(hù)端3前來(lái)獲取鎖,則在ParentLock下創(chuàng)建一個(gè)臨時(shí)順序節(jié)點(diǎn)Lock3;

接下來(lái)客戶(hù)端3將獲取ParentLock下的所有臨時(shí)順序節(jié)點(diǎn)并排序,與自身創(chuàng)建的節(jié)點(diǎn)Lock3比較,判斷Lock3是不是最小的(最靠前的),結(jié)果發(fā)現(xiàn)Lock3不是最小的;

于是,Lock3向比它靠前的第一個(gè)節(jié)點(diǎn)Lock2注冊(cè)一個(gè)Watcher,用于監(jiān)聽(tīng)Lock2是否存在,此時(shí)意味著Lock3也搶鎖失敗,進(jìn)入阻塞狀態(tài); 這樣的話(huà),客戶(hù)端1獲取到了鎖,客戶(hù)端2監(jiān)聽(tīng)了Lock1、客戶(hù)端3監(jiān)聽(tīng)了Lock2;

客戶(hù)端崩潰釋放鎖(避免死鎖)

假設(shè)由于網(wǎng)絡(luò)原因或者其他物理原因,導(dǎo)致客戶(hù)端1與Zookeeper失去連接,根據(jù)臨時(shí)節(jié)點(diǎn)的特性,Zookeeper會(huì)自動(dòng)刪除相關(guān)聯(lián)的節(jié)點(diǎn)Lock1。 Lock1刪除之后,因?yàn)榭蛻?hù)端2在Lock1上注冊(cè)了Watcher,因此Lock1刪除之后,客戶(hù)端2會(huì)立即收到通知,這時(shí)客戶(hù)端2會(huì)再次獲取ParentLock下的所有臨時(shí)順序子節(jié)點(diǎn)并進(jìn)行排序,然后與自身創(chuàng)建的Lock2比較,判斷Lock2是不是最小的(最靠前的),結(jié)果發(fā)現(xiàn)Lock2是最小的,因此客戶(hù)端2獲取鎖成功;

客戶(hù)端2崩潰同理;

顯示釋放(客戶(hù)端任務(wù)執(zhí)行完畢,主動(dòng)釋放鎖)

當(dāng)客戶(hù)端2執(zhí)行完任務(wù)之后,調(diào)用delete方法刪除Lock2節(jié)點(diǎn),因?yàn)榭蛻?hù)端3在Lock2上注冊(cè)了Watcher,因此Lock2刪除之后,客戶(hù)端3會(huì)立即收到通知,這時(shí)客戶(hù)端3會(huì)再次獲取ParentLock下的所有臨時(shí)順序子節(jié)點(diǎn)并進(jìn)行排序,然后與自身創(chuàng)建的Lock3比較,判斷Lock3是不是最小的(最靠前的),結(jié)果發(fā)現(xiàn)Lock3是最小的,因此客戶(hù)端3獲取鎖成功;

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

配置文件pom.xml

        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipesss</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.0.1</version>
        </dependency>

配置文件application.properties

##ZooKeeper 集成 Curator
zk.url = 127.0.0.1:2181

conf

@Configuration
@Slf4j
public class ZooKeeperConf {
    @Value("${zk.url}")
    private String zkUrl;
    @Bean
    public CuratorFramework getCuratorFramework() {
        // 用于重連策略,1000毫秒是初始化的間隔時(shí)間,3代表嘗試重連次數(shù)
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        CuratorFramework client = CuratorFrameworkFactory.newClient(zkUrl, retryPolicy);
        //必須調(diào)用start開(kāi)始連接ZooKeeper
        client.start();
//        /**
//         * 使用Curator,可以通過(guò)LeaderSelector來(lái)實(shí)現(xiàn)領(lǐng)導(dǎo)選?。?
//         * 領(lǐng)導(dǎo)選?。哼x出一個(gè)領(lǐng)導(dǎo)節(jié)點(diǎn)來(lái)負(fù)責(zé)其他節(jié)點(diǎn);如果領(lǐng)導(dǎo)節(jié)點(diǎn)不可用,則在剩下的機(jī)器里再選出一個(gè)領(lǐng)導(dǎo)節(jié)點(diǎn)
//         */
//        // 構(gòu)造一個(gè)監(jiān)聽(tīng)器
//        LeaderSelectorListenerAdapter listener = new LeaderSelectorListenerAdapter() {
//            @Override
//            public void takeLeadership(CuratorFramework curatorFramework) throws Exception {
//                log.info("get leadership");
//                // 領(lǐng)導(dǎo)節(jié)點(diǎn),方法結(jié)束后退出領(lǐng)導(dǎo)。zk會(huì)再次重新選擇領(lǐng)導(dǎo)
//
//            }
//        };
//        LeaderSelector selector = new LeaderSelector(client, "/schedule", listener);
//        selector.autoRequeue();
//        selector.start();
        return client;
    }
}

controller

@RestController
@RequestMapping("/zookeeper")
public class ZooKeeperController {
    @Autowired
    private CuratorFramework zkClient;
    @Autowired
    private ZooKeeperImpl zooKeeper;
    /**
     * zookeeper 獲取節(jié)點(diǎn)下的數(shù)據(jù)
     * <p>
     * post請(qǐng)求: http://localhost:8082/zookeeper/makeOrder?path=/task
     *
     * @param path
     * @return
     */
    @PostMapping("/getData")
    public String getData(@RequestParam String path) {
        byte[] bytes = null;
        try {
            bytes = zkClient.getData().forPath(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String str = new String(bytes);
        return str;
    }
    @PostMapping("/create")
    public String create(@RequestParam String path) {
        try {
            zkClient.create().forPath(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "success";
    }
    @PostMapping("/delete")
    public String delete(@RequestParam String path) {
        try {
            zkClient.delete().forPath(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "success";
    }
    @PostMapping("/setData")
    public String setData(@RequestParam(value = "path") String path, @RequestParam(value = "data") String data) {
        try {
            zkClient.setData().forPath(path, data.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "success";
    }
    @PostMapping("/check")
    public String check(@RequestParam(value = "path") String path) {
        Stat stat = null;
        try {
            stat = zkClient.checkExists().forPath(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "stat" + stat;
    }
    @PostMapping("/children")
    public String children(@RequestParam(value = "path") String path) {
        List<String> children = null;
        try {
            children = zkClient.getChildren().forPath(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "children" + children;
    }
    @PostMapping("/watch")
    public String watch(@RequestParam(value = "path") String path) {
        Stat stat = null;
        try {
            stat = zkClient.checkExists().watched().forPath(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "watch " + stat;
    }
    /**
     * zookeeper分布式鎖
     *
     * @param product
     * @return
     */
    @PostMapping("/makeOrder")
    public String makeOrder(@RequestParam(value = "product") String product) {
        zooKeeper.makeOrder(product);
        return "success";
    }
}

service

@Service
@Slf4j
public class ZooKeeperImpl {
    private static final String lockPath = "/lock/order";
    @Autowired
    private CuratorFramework zkClient;
    public void makeOrder(String product) {
        log.info("try do job for " + product);
        String path = lockPath + "/" + product;
        try {
        	// InterProcessMutex 構(gòu)建一個(gè)分布式鎖
            InterProcessMutex lock = new InterProcessMutex(zkClient, path);
            try {
                if (lock.acquire(5, TimeUnit.HOURS)) {
                	// 模擬業(yè)務(wù)處理耗時(shí)5秒
                    Thread.sleep(5*1000);
                    log.info("do job " + product + "done");
                }
            } finally {
            	// 釋放該鎖
                lock.release();
            }
        } catch (Exception e) {
        	// zk異常
            e.printStackTrace();
        }
    }
}

到此這篇關(guān)于Zookeeper實(shí)現(xiàn)分布式鎖代碼實(shí)例的文章就介紹到這了,更多相關(guān)Zookeeper分布式鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • J2SE基礎(chǔ)之JDK環(huán)境變量配置

    J2SE基礎(chǔ)之JDK環(huán)境變量配置

    進(jìn)行java開(kāi)發(fā),首先要安裝jdk,安裝了jdk后還要進(jìn)行環(huán)境變量配置,下面我們就來(lái)詳細(xì)探討下這個(gè)問(wèn)題。
    2016-05-05
  • Spring配置多個(gè)數(shù)據(jù)源并實(shí)現(xiàn)數(shù)據(jù)源的動(dòng)態(tài)切換功能

    Spring配置多個(gè)數(shù)據(jù)源并實(shí)現(xiàn)數(shù)據(jù)源的動(dòng)態(tài)切換功能

    這篇文章主要介紹了Spring配置多個(gè)數(shù)據(jù)源并實(shí)現(xiàn)數(shù)據(jù)源的動(dòng)態(tài)切換功能,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2024-01-01
  • java實(shí)現(xiàn)簡(jiǎn)易局域網(wǎng)聊天功能

    java實(shí)現(xiàn)簡(jiǎn)易局域網(wǎng)聊天功能

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)易局域網(wǎng)聊天功能,使用UDP模式編寫(xiě)一個(gè)聊天程序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • java編譯時(shí)指定classpath的實(shí)現(xiàn)方法

    java編譯時(shí)指定classpath的實(shí)現(xiàn)方法

    在Java編程中,classpath是用于指定Java虛擬機(jī)在運(yùn)行時(shí)查找類(lèi)文件的路徑,本文主要介紹了java編譯時(shí)指定classpath的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-10-10
  • 淺談@Aspect@Order各個(gè)通知的執(zhí)行順序

    淺談@Aspect@Order各個(gè)通知的執(zhí)行順序

    這篇文章主要介紹了@Aspect@Order各個(gè)通知的執(zhí)行順序,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • SpringBoot整合mybatis使用Druid做連接池的方式

    SpringBoot整合mybatis使用Druid做連接池的方式

    這篇文章主要介紹了SpringBoot整合mybatis使用Druid做連接池的方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • SpringBoot實(shí)現(xiàn)Tomcat集群的會(huì)話(huà)管理功能

    SpringBoot實(shí)現(xiàn)Tomcat集群的會(huì)話(huà)管理功能

    在使用 Tomcat 集群時(shí),由于每個(gè) Tomcat 實(shí)例的 Session 存儲(chǔ)是獨(dú)立的,導(dǎo)致無(wú)法實(shí)現(xiàn) Session 的共享,這可能影響到用戶(hù)跨節(jié)點(diǎn)的訪問(wèn),為了實(shí)現(xiàn)跨 Tomcat 實(shí)例共享 Session,可以使用 Spring Session 配合 Redis 進(jìn)行集中式會(huì)話(huà)管理,需要的朋友可以參考下
    2024-12-12
  • Mybatis自定義SQL的關(guān)系映射、分頁(yè)、排序功能的實(shí)現(xiàn)

    Mybatis自定義SQL的關(guān)系映射、分頁(yè)、排序功能的實(shí)現(xiàn)

    這篇文章主要介紹了Mybatis自定義SQL的關(guān)系映射、分頁(yè)、排序功能的實(shí)現(xiàn),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • 基于java URL和URLConnection(詳解)

    基于java URL和URLConnection(詳解)

    下面小編就為大家分享一篇基于java URL和URLConnection(詳解),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • java高級(jí)用法之JNA中使用類(lèi)型映射

    java高級(jí)用法之JNA中使用類(lèi)型映射

    JNA中有很多種映射,本文主要介紹了java高級(jí)用法之JNA中使用類(lèi)型映射,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-03-03

最新評(píng)論