巨乳在线中文字幕,巨乳诱惑中文字幕,中文字幕人成乱码熟女_腾讯视频
  • 當前位置: 首頁 / 技術分享 / 正文
    分布式鎖的實現(二)

    2023-01-12

       節點

      4.4. 子節點實現的鎖

      在生產環境中,使用子節點做分布式鎖的實現的場景是最常見的,包括阻塞型的鎖和非阻塞型的鎖。因此,設計子節點實現的鎖的父類,提供公共的處理邏輯。將阻塞型和非阻塞型的實現不同的邏輯分別在子類中實現即可。

      package com.qianfeng.lock.childNodeLock;

      import com.qianfeng.lock.ZkLocker;

      import com.qianfeng.lock.ZkLockerBase;

      import org.apache.zookeeper.CreateMode;

      import org.apache.zookeeper.KeeperException;

      import java.util.Collections;

      import java.util.List;

      /**

      * @author 千鋒大數據教研院 - 章魚哥

      * @company 北京千鋒互聯科技有限公司

      */

      public abstract class ZkChildNodeLockerBase extends ZkLockerBase implements ZkLocker {

      /**

      * 創建的子節點鎖的全路徑

      */

      protected String nodeFullPath;

      public ZkChildNodeLockerBase(String connectString, String lockName) {

      super(connectString, lockName);

      createLockNode();

      }

      public ZkChildNodeLockerBase(String lockName) {

      super();

      this.lockName = lockName;

      createLockNode();

      }

      // 創建鎖節點

      public void createLockNode() {

      // 1. 判斷節點是否存在

      if (!exists(getLockName())) {

      // 3. 創建鎖節點

      createNode(getLockName(), CreateMode.CONTAINER);

      }

      }

      @Override

      public boolean lock() {

      // 1. 在鎖節點下創建子節點

      this.nodeFullPath = createNode(getLockName() + "/child-", CreateMode.EPHEMERAL_SEQUENTIAL);

      // 2. 判斷是否可以成功上鎖

      return canLock();

      }

      @Override

      public boolean unlock() {

      return deleteNode(this.nodeFullPath);

      }

      @Override

      public boolean exists() {

      // 獲取當前鎖節點下的子節點數量,如果大于0,說明有鎖存在

      try {

      Listchildren = getZkCli().getChildren(getLockName(), false);

      return children.size() > 0;

      } catch (KeeperException | InterruptedException ignored) {

      }

      return false;

      }

      protected abstract boolean canLock();

      /**

      * 獲取當前創建的子節點之前的節點(根據序號)

      * @return 之前的節點

      */

      protected String getPreviousNode() {

      // 定義變量,記錄上一個節點名稱

      String previousNodeName = null;

      try {

      // 1. 獲取鎖節點下所有的子節點

      Listchildren = getZkCli().getChildren(getLockName(), false);

      // 2. 對所有的節點進行名字排序

      Collections.sort(children);

      // 3. 獲取當前創建的子節點名稱

      String childNodeName = this.nodeFullPath.substring(getLockName().length() + 1);

      // 4. 遍歷所有的節點,進行名稱的比對

      for (String child : children) {

      if (child.equals(childNodeName)) {

      break;

      }

      previousNodeName = child;

      }

      } catch (KeeperException | InterruptedException e) {

      e.printStackTrace();

      }

      return previousNodeName;

      }

      }

      4.5. 子節點實現的非阻塞型鎖

      package com.qianfeng.lock.childNodeLock;

      /**

      * @author 千鋒大數據教研院 - 章魚哥

      * @company 北京千鋒互聯科技有限公司

      */

      public class ZkChildNodeNoneBlockingLocker extends ZkChildNodeLockerBase {

      public ZkChildNodeNoneBlockingLocker(String connectString, String lockName) {

      super(connectString, lockName);

      }

      public ZkChildNodeNoneBlockingLocker(String lockName) {

      super(lockName);

      }

      @Override

      protected boolean canLock() {

      // 1. 判斷是否有之前的節點

      String previousNodeName = getPreviousNode();

      // 2. 如果不存在之前的節點,說明上鎖成功

      if (previousNodeName == null) {

      return true;

      }

      // 3. 如果存在之前的節點,說明上鎖失敗,刪除自己創建的子節點即可

      deleteNode(this.nodeFullPath);

      return false;

      }

      }

      4.6. 子節點實現的阻塞型鎖

      A程序在進行上鎖的時候,發現已經被其他的程序獲取到鎖了,自己需要等待其他的程序釋放鎖?;镜膶崿F邏輯就是自己監控已經創建好的節點,發現這個節點消失的時候,自己去創建節點。但是為什么沒有用節點作為鎖來實現阻塞型的鎖呢?是因為這里有“羊群效應”。

      假如有100個程序來獲取鎖,結果發現鎖已經被其他的程序注冊了,于是這100個程序都去監聽這個節點。一旦這個節點被刪除,這100個程序都可以獲取到狀態的變更,會同時請求ZooKeeper創建節點。這樣會帶來瞬時的資源占用劇增,嚴重的甚至可能導致服務器宕機。因此,我們在實現阻塞型鎖的時候,使用的是有序的子節點來實現的,每一個程序監控比自己編號小的節點即可。詳情可參考3.2.章節的內容。

      package com.qianfeng.lock.childNodeLock;

      import org.apache.zookeeper.AddWatchMode;

      import org.apache.zookeeper.KeeperException;

      import java.util.concurrent.CountDownLatch;

      /**

      * @author 千鋒大數據教研院 - 章魚哥

      * @company 北京千鋒互聯科技有限公司

      */

      public class ZkChildNodeBlockingLocker extends ZkChildNodeLockerBase {

      // 等待釋放信號

      private CountDownLatch latch = new CountDownLatch(1);

      public ZkChildNodeBlockingLocker(String connectString, String lockName) {

      super(connectString, lockName);

      }

      public ZkChildNodeBlockingLocker(String lockName) {

      super(lockName);

      }

      @Override

      protected boolean canLock() {

      // 獲取自己創建的子節點之前序號的節點

      String previousNode = getPreviousNode();

      // 如果之前節點不存在,說明已經上鎖成功

      if (previousNode == null) {

      return true;

      }

      // 如果有比當前創建的節點序號更小的節點,說明上鎖失敗,自己阻塞,監聽之前的節點即可

      try {

      getZkCli().addWatch(getLockName() + "/" + previousNode, event -> {

      if (event.getType().equals(Event.EventType.NodeDeleted)) {

      // 說明之前節點被刪除掉了

      latch.countDown();

      }

      }, AddWatchMode.PERSISTENT);

      // 等待信號

      latch.await();

      } catch (KeeperException | InterruptedException e) {

      e.printStackTrace();

      }

      // 自己成為了最小的節點,上鎖成功

      return true;

      }

      }

    好程序員公眾號

    • · 剖析行業發展趨勢
    • · 匯聚企業項目源碼

    好程序員開班動態

    More+
    • HTML5大前端 <高端班>

      開班時間:2021-04-12(深圳)

      開班盛況

      開班時間:2021-05-17(北京)

      開班盛況
    • 大數據+人工智能 <高端班>

      開班時間:2021-03-22(杭州)

      開班盛況

      開班時間:2021-04-26(北京)

      開班盛況
    • JavaEE分布式開發 <高端班>

      開班時間:2021-05-10(北京)

      開班盛況

      開班時間:2021-02-22(北京)

      開班盛況
    • Python人工智能+數據分析 <高端班>

      開班時間:2021-07-12(北京)

      預約報名

      開班時間:2020-09-21(上海)

      開班盛況
    • 云計算開發 <高端班>

      開班時間:2021-07-12(北京)

      預約報名

      開班時間:2019-07-22(北京)

      開班盛況
    在線咨詢
    試聽
    入學教程
    立即報名

    Copyright 2011-2023 北京千鋒互聯科技有限公司 .All Right 京ICP備12003911號-5 京公網安備 11010802035720號

    巨乳在线中文字幕,巨乳诱惑中文字幕,中文字幕人成乱码熟女_腾讯视频