第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

ZooKeeper 實現分布式鎖

1. 前言

在我們的應用中,經常會碰見多個請求去訪問同一個資源的情況。如果請求 A 拿到這個資源數據,想要對它進行修改,但是還沒有進行事務提交,此時請求 B 訪問這個資源就會拿到修改前的數據,很顯然請求 B 拿到的是歷史數據,是不正確的。

在單個服務器的應用中,我們可以使用系統(tǒng)的線程來對這個資源進行加鎖。那么在分布式環(huán)境中我們有什么方案來解決這個問題呢?答案就是使用分布式鎖。那么什么是分布式鎖?分布式鎖又是如何實現的呢?本節(jié)我們就來講解如何使用 Zookeeper 實現分布式鎖,以及它的實現原理。

2. 分布式鎖

在講解 Zookeeper 實現的分布式鎖之前,我們先來了解什么是分布式鎖,分布式鎖的實現技術,以及分布式鎖常用的類型。

2.1 分布式鎖的特點

顧名思義,分布式鎖就是實現在分布式網絡環(huán)境中的鎖。也就是說,在鎖的基礎上加上分布式的特性,我們來分析一下分布式鎖實現的必要條件:

  1. 在分布式環(huán)境中,多個進程對資源的訪問必須具有順序性;
  2. 獲取鎖和釋放鎖的過程需要高可用和高性能;
  3. 具有鎖失效的機制,避免死鎖;
  4. 非阻塞的鎖,沒有獲取到鎖直接返回獲取鎖失敗。

介紹了分布式鎖的特點,那么有哪些技術能夠實現分布式鎖呢?

2.2 分布式鎖的實現技術

  1. Memcached: 使用 add 命令來添加 key,key 添加成功說明當前無人使用此 key,也就是說無人使用此資源,相當于獲取鎖。再次使用 add 命令來添加相同的 key 時,此時 key 已存在就會添加失敗,說明有人已經使用了這個 key,也就是說此資源被人占用,相當于獲取鎖失??;
  2. Redis: 使用 setnx 命令來添加 key,key 添加成功說明當前無人使用此 key,也就是說無人使用此資源,相當于獲取鎖。再次使用 setnx 命令來添加相同的 key 時,此時 key 已存在就會添加失敗,說明有人已經使用了這個 key,也就是說此資源被人占用,相當于獲取鎖失敗;
  3. Chubby: Google 使用 Paxos 一致性算法實現的粗粒度分布式鎖;
  4. Zookeeper: 使用 Zookeeper 臨時順序節(jié)點的特性,實現分布式鎖和鎖的等待隊列。

介紹了分布式鎖的實現技術,接下來我們來介紹分布式鎖常用的類型。

2.3 分布式鎖常用的類型

分布式鎖常用的類型有兩種:一種是排他鎖,一種是共享鎖。接下來我們分別介紹這兩鎖的特點。

  • 排他鎖

排他鎖也叫獨占鎖,顧名思義,也就是對資源進行獨占。排他鎖只允許獲取了該鎖的線程,對具有排他鎖的資源進行訪問,無論是寫操作還是讀操作,直到該線程主動釋放掉排他鎖。

  • 共享鎖

共享鎖也就是把資源進行共享,當然共享的只有讀操作。共享鎖只對寫操作進行加鎖,其它線程的讀操作不做加鎖操作,這樣的共享機制提高了對資源訪問的性能。

介紹完分布式鎖的常用類型,接下來我們開始學習如何使用 Zookeeper 實現分布式鎖。

3. Zookeeper 實現分布式鎖

上面我們提到,Zookeeper 是根據它的臨時順序節(jié)點來實現的分布式鎖,這里我們來回顧一下臨時順序節(jié)點的特性。

3.1 臨時順序節(jié)點

臨時順序節(jié)點:

  • 節(jié)點具有臨時性,創(chuàng)建該節(jié)點的 Zookeeper 客戶端與 Zookeeper 服務端斷開連接時,該節(jié)點會自動被 Zookeeper 服務端刪除;
  • 節(jié)點具有順序性,創(chuàng)建該節(jié)點時,Zookeeper 服務端會根據創(chuàng)建時間的順序在該節(jié)點名稱后面加上順序編號。

回顧了臨時順序節(jié)點的特性,接下來我們就使用 Zookeeper 的 Java 客戶端 Curator 來創(chuàng)建臨時順序節(jié)點,我們可以使用在 Zookeeper Curator 一節(jié)創(chuàng)建的 Spring Boot 測試項目來進行測試。

我們可以在測試類 CuratorDemoApplicationTests 中編寫測試用例:

@SpringBootTest
class CuratorDemoApplicationTests {

    @Autowired
    private CuratorService curatorService;

    @Test
    void contextLoads() throws Exception {
        // 獲取客戶端
        CuratorFramework client = curatorService.getCuratorClient();
        // 開啟會話
        client.start();
        
        // 第一次創(chuàng)建臨時順序節(jié)點
        String s1 = client.create()
            // 如果有父節(jié)點會一起創(chuàng)建
            .creatingParentsIfNeeded()
            // 節(jié)點類型:臨時順序節(jié)點
            .withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
            // 節(jié)點路徑 /wiki
            .forPath("/wiki-");
        // 輸出
        System.out.println(s1);
        
        // 第二次創(chuàng)建臨時順序節(jié)點
        String s2 = client.create()
            // 如果有父節(jié)點會一起創(chuàng)建
            .creatingParentsIfNeeded()
            // 節(jié)點類型:臨時順序節(jié)點
            .withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
            // 節(jié)點路徑 /wiki
            .forPath("/wiki-");
        // 輸出
        System.out.println(s2);
        
        // 關閉客戶端
        client.close();
    }
}

執(zhí)行測試方法,控制臺輸出:

/wiki-0000000000
/wiki-0000000001

我們可以發(fā)現,控制臺一共輸出了兩個 /wiki 節(jié)點,而且每個 /wiki 節(jié)點后面都增加了編號,此時我們去 zkCli 命令行客戶端查看所有節(jié)點,發(fā)現并沒有 /wiki 節(jié)點。因為在我們的測試程序中,我們關閉了客戶端,所以臨時節(jié)點會被移除。

Tips: 如果這里創(chuàng)建失敗,請同學們注意父節(jié)點是否存在 ACL 訪問控制。

回顧了臨時順序節(jié)點,那么如何使用 Zookeeper 的臨時順序節(jié)點來實現分布式鎖呢?接下來我們就開始介紹如何使用 Zookeeper 的臨時順序節(jié)點來控制它們的訪問順序。

3.2 分布式鎖實現

本節(jié)我們來介紹分布式鎖實現的具體步驟:

  1. 創(chuàng)建臨時順序節(jié)點: 每一次獲取資源的請求,我們都需要使用 Zookeeper 客戶端創(chuàng)建一個臨時順序節(jié)點,用這個臨時順序節(jié)點在 Zookeeper 服務端中獲取鎖。

  2. 獲取鎖: 這里的鎖并不具體指代什么,而是根據 Zookeeper 的臨時順序節(jié)點的順序來決定是否獲取了鎖。如果該節(jié)點的順序編號是最小的,則說明該節(jié)點是排在最前面的,在它之前無人占領資源,也就可以說該節(jié)點獲取了鎖,具有訪問資源的權限。

圖片描述

  1. 監(jiān)聽鎖: 如果獲取鎖這一步發(fā)現 Zookeeper 客戶端創(chuàng)建的臨時順序節(jié)點的順序編號不是最小的,也就是在這個臨時順序節(jié)點之前存在其它臨時順序節(jié)點,那么就可以說這個節(jié)點獲取鎖失敗了,它會進入等待隊列。我們可以監(jiān)聽它的前一個節(jié)點,只要它的前一個臨時順序節(jié)點的刪除事件觸發(fā),我們就可以獲取臨時順序節(jié)點的列表來重新確認這個節(jié)點的順序。

圖片描述

  1. 釋放鎖: 當一個請求對資源的操作結束后,我們可以使用 Zookeeper 客戶端的節(jié)點刪除 API 來刪除這個請求創(chuàng)建的臨時順序節(jié)點。除了使用 API 來主動釋放鎖之外,根據臨時順序節(jié)點的特性,當創(chuàng)建這個臨時順序節(jié)點的 Zookeeper 客戶端與 Zookeeper 服務端斷開連接時,這個臨時順序節(jié)點會被 Zookeeper 服務端移除。這兩種方式都會觸發(fā)臨時節(jié)點的刪除事件,讓下一個臨時順序節(jié)點來確認自身的順序。

4. 總結

本節(jié)內容中,我們學習了什么是分布式鎖,以及它的特點和類型,還學習了使用 Zookeeper 實現分布式鎖的主要步驟。以下是本節(jié)內容的總結:

  1. 分布式鎖的特點和常用類型。
  2. 臨時順序節(jié)點的特性。
  3. 使用 Zookeeper 實現分布式鎖的主要步驟。