<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      java代碼怎樣實現分布式鎖 java代碼分布式編程的基礎教程

      實現分布式鎖的核心是利用共享存儲服務協調多個節點訪問資源,1. 使用setnx和expire命令結合uuid和lua腳本,以確保基于redis的方案的唯一性和原子性,適用于高性能場景;2. 基于zookeeper的解決方案是通過創建臨時順序節點和監控前驅節點來實現的。watcher機制用于減少輪詢,支持自動釋放鎖,適用于高可靠性場景;3. 在選擇方案時,需要權衡性能、可靠性、復雜性、鎖類型以及是否需要自動釋放等因素,redis適用于高性能、低延遲的需求,zookeeper適合強一致性要求;4. 避免死鎖等常見問題,設置過期時間或臨時節點,使用lua腳本確保刪除原子,避免提前釋放可啟用鎖續約,合理配置集群參數,支持重新訪問可記錄線程ID和重新訪問次數;5. 其它方案包括數據庫行鎖,etcd、consul和基于paxos/raft的一致性系統分別適用于不同性能、可靠性和復雜性要求的場景。最終選擇應根據實際業務需要進行綜合評估。

      實現分布式鎖的核心在于利用分布式系統中的共享存儲服務,如Redis、Zookeeper或數據庫協調多個節點訪問共享資源。選擇哪種方案取決于您的具體需求,如性能、可靠性和復雜性。

      解決方案:

      以下是基于Redis和Zookeper實現分布式鎖的Java代碼示例:

      立即學習“Java免費學習筆記(深入);

      1. 基于Redis的分布式鎖

      Redis

      SETNX

      (Set if Not Exists)命令和

      EXPIRE

      命令組合可以實現簡單的分布式鎖。為了避免死鎖,需要設置鎖的過期時間。

      import redis.clients.jedis.Jedis;
      import redis.clients.jedis.JedisPool;
      import redis.clients.jedis.JedisPoolConfig;
      
      import java.util.UUID;
      
      public class RedisDistributedLock {
      
          private static final String LOCK_PREFIX = "lock:";
          private static final String SUCCESS_RESULT = "OK";
          private static final Long RELEASE_SUCCESS = 1L;
      
          private JedisPool jedisPool;
      
          public RedisDistributedLock(String host, int port) {
              JedisPoolConfig config = new JedisPoolConfig();
              // 連接池配置可根據需要調整
              jedisPool = new JedisPool(config, host, port);
          }
      
          /**
           * 嘗試獲取鎖
           * @param lockName 鎖的名稱
           * @param expireTime 鎖的過期時間,單位:秒
           * @return 獲得鎖成功返回鎖的值,失敗返回nulll
           */
          public String tryLock(String lockName, int expireTime) {
              Jedis jedis = null;
              try {
                  jedis = jedisPool.getResource();
                  String lockKey = LOCK_PREFIX + lockName;
                  String lockValue = UUID.randomUUID().toString(); // 鎖的值,用于釋放鎖時的驗證
                  String result = jedis.set(lockKey, lockValue, "NX", "EX", expireTime);
      
                  if (SUCCESS_RESULT.equals(result)) {
                      return lockValue;
                  }
                  return null;
              } finally {
                  if (jedis != null) {
                      jedis.close();
                  }
              }
          }
      
          /**
           * 釋放鎖
           * @param lockName 鎖的名稱
           * @param lockValue 鎖的值
           * @return 釋放鎖是否成功
           */
          public boolean releaseLock(String lockName, String lockValue) {
              Jedis jedis = null;
              try {
                  jedis = jedisPool.getResource();
                  String lockKey = LOCK_PREFIX + lockName;
                  // 使用Lua腳本保證原子性
                  String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
                  Object result = jedis.eval(script, 1, lockKey, lockValue);
      
                  if (RELEASE_SUCCESS.equals(result)) {
                      return true;
                  }
                  return false;
              } finally {
                  if (jedis != null) {
                      jedis.close();
                  }
              }
          }
      
          public void close() {
              if (jedisPool != null) {
                  jedisPool.close();
              }
          }
      
          public static void main(String[] args) throws InterruptedException {
              RedisDistributedLock lock = new RedisDistributedLock("localhost", 6379);
              String lockName = "myLock";
              String lockValue = lock.tryLock(lockName, 10); // 嘗試獲得鎖,過期時間為10秒
      
              if (lockValue != null) {
                  try {
                      System.out.println("成功獲取鎖,lockValue: " + lockValue);
                      // 模擬業務邏輯
                      Thread.sleep(5000);
                  } finally {
                      boolean released = lock.releaseLock(lockName, lockValue);
                      System.out.println("釋放鎖結果: " + released);
                      lock.close();
                  }
              } else {
                  System.out.println("獲取鎖失敗");
                  lock.close();
              }
          }
      }

      關鍵點:

      • 鎖的唯一標志: 使用UUID作為鎖的值,防止其他客戶端的鎖被誤刪。
      • Lua腳本:Lua腳本: 使用Lua腳本保證刪除鎖的原子性,避免并發問題。
      • 連接池: 利用JedisPol管理Redis連接,提高性能。

      2. 基于Zoookeeper的分布式鎖

      Zookeeper通過創建臨時序列節點來實現分布式鎖。當客戶創建鎖節點時,如果該節點是序列號最小的節點,則認為該客戶獲得鎖。釋放鎖時,刪除該節點。

      import org.apache.zookeeper.*;
      import org.apache.zookeeper.data.Stat;
      
      import java.io.IOException;
      import java.util.Collections;
      import java.util.List;
      import java.util.concurrent.CountDownLatch;
      import java.util.concurrent.TimeUnit;
      
      public class ZookeeperDistributedLock {
      
          private static final String ZK_ADDRESS = "localhost:2181";
          private static final String LOCK_ROOT_PATH = "/locks";
          private static final String LOCK_NODE_PREFIX = "lock-";
      
          private ZooKeeper zkClient;
          private String lockPath;
          private String currentLockNode;
          private CountDownLatch latch = new CountDownLatch(1);
      
          public ZookeeperDistributedLock(String lockName) throws IOException, InterruptedException, KeeperException {
              zkClient = new ZooKeeper(ZK_ADDRESS, 5000, new Watcher() {
                  @Override
                  public void process(WatchedEvent event) {
                      if (event.getState() == Event.KeeperState.SyncConnected) {
                          latch.countDown();
                      }
                  }
              });
              latch.await();
      
              // 檢查根節點是否存在,不存在就創造
              Stat stat = zkClient.exists(LOCK_ROOT_PATH, false);
              if (stat == null) {
                  zkClient.create(LOCK_ROOT_PATH, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
              }
              this.lockPath = LOCK_ROOT_PATH + "/" + lockName;
      
              Stat lockStat = zkClient.exists(this.lockPath, false);
              if(lockStat == null){
                  zkClient.create(this.lockPath, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
              }
          }
      
          /**
           * 嘗試獲取鎖
           * @param timeout 超時時間,單位:毫秒
           * @return 獲取鎖是否成功
           */
          public boolean tryLock(long timeout) throws InterruptedException, KeeperException {
              try {
                  // 創建臨時順序節點
                  currentLockNode = zkClient.create(lockPath + "/" + LOCK_NODE_PREFIX, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
      
                  // 獲取所有子節點
                  List<String> children = zkClient.getChildren(lockPath, false);
                  Collections.sort(children);
      
                  // 假如當前的節點是最小的節點,成功獲得鎖
                  if (currentLockNode.equals(lockPath + "/" + children.get(0))) {
                      return true;
                  }
      
                  // 監控前一節點
                  String previousNode = null;
                  for (int i = 0; i < children.size(); i++) {
                      if (currentLockNode.equals(lockPath + "/" + children.get(i))) {
                          previousNode = lockPath + "/" + children.get(i - 1);
                          break;
                      }
                  }
      
                  final CountDownLatch waitLatch = new CountDownLatch(1);
                  Watcher watcher = new Watcher() {
                      @Override
                      public void process(WatchedEvent event) {
                          if (event.getType() == Event.EventType.NodeDeleted) {
                              waitLatch.countDown();
                          }
                      }
                  };
      
                  zkClient.exists(previousNode, watcher);
                  return waitLatch.await(timeout, TimeUnit.MILLISECONDS); // 等待前一個節點被刪除
              } catch (KeeperException e) {
                  // 處理連接斷開的情況,再試一次獲得鎖
                  if (e.code() == KeeperException.Code.CONNECTIONLOSS) {
                      return tryLock(timeout);
                  } else {
                      throw e;
                  }
              }
          }
      
          /**
           * 釋放鎖
           */
          public void unlock() throws InterruptedException, KeeperException {
              if (currentLockNode != null) {
                  zkClient.delete(currentLockNode, -1);
                  currentLockNode = null;
              }
          }
      
          public void close() throws InterruptedException {
              if (zkClient != null) {
                  zkClient.close();
              }
          }
      
          public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
              ZookeeperDistributedLock lock = new ZookeeperDistributedLock("myLock");
              try {
                  if (lock.tryLock(5000)) { // 嘗試獲得鎖,超時時間5秒
                      System.out.println("獲取鎖成功");
                      Thread.sleep(5000); // 模擬業務邏輯
                  } else {
                      System.out.println("獲取鎖失敗");
                  }
              } finally {
                  lock.unlock();
                  lock.close();
              }
          }
      }

      關鍵點:

      • 臨時順序節點: 使用臨時順序節點,確保鎖的自動釋放,避免死鎖。
      • Watcher機制: 利用Watcher監控前一個節點的刪除事件,減少輪詢。
      • 連接丟失處理: 處理連接丟失,重新嘗試獲取鎖。

      選擇Redis還是Zookeper取決于你的應用場景。Redis適用于性能要求高的場景,Zookeper適用于可靠性要求高的場景。此外,還可以考慮使用Redison等包裝好的客戶端,提供更先進的分布式鎖定功能。

      如何選擇合適的分布式鎖實現方案?

      選擇合適的分布式鎖實現方案,需要綜合考慮以下幾個方面:

      1. 性能: Redis通常性能更高,因為它基于內存,讀寫速度快。Zookeper的性能相對較低,因為它需要磁盤寫入和節點同步。如果您的應用程序對性能有很高的要求,Redis可能更合適。
      2. 可靠性: Zookeper具有更高的可靠性,因為它是一種專門為分布式協調設計的服務,具有容錯性和數據一致性的保證。雖然Redis也可以通過主復制和Sentinel實現高可用性,但在某些情況下可能存在數據丟失的風險。如果您的應用程序對可靠性有很高的要求,Zookeper可能更合適。
      3. 復雜度: Redis的實現相對簡單,只需要使用
        SETNX

        EXPIRE

        命令。Zookeeper的實現相對復雜,需要創建臨時順序節點、監控節點刪除事件等。如果您的應用程序需要開發效率,Redis可能更合適。

      4. 鎖的類型: Redis只支持排他鎖,即同時只有一個客戶端。Zookeeper可以支持多種類型的鎖,如排他鎖、共享鎖等。如果您的應用程序需要支持多種類型的鎖,Zookeeper可能更合適。
      5. 鎖是否需要自動釋放: 即使客戶端出現故障,Zookeeper的臨時節點也可以自動釋放鎖。Redis需要設置鎖的過期時間,以避免死鎖,但如果客戶端在過期前完成操作,鎖可能會提前釋放。如果您的應用程序需要自動釋放鎖的功能,Zookeeper可能更合適。

      一般來說,Redis適用于性能要求高、可靠性要求低的場景,而Zookeper適用于可靠性要求高、性能要求低的場景。在實際應用中,可根據具體需要進行選擇。

      如何避免分布式鎖的常見問題?

      使用分布式鎖時,應注意以下常見問題:

      1. 死鎖: 如果客戶端在獲得鎖后出現故障,鎖未釋放,可能會導致死鎖。為了避免死鎖,需要設置鎖的過期時間或使用Zookeeper的臨時節點。
      2. 提前釋放鎖: 如果客戶端在鎖過期之前完成操作,鎖可能會提前釋放,其他客戶端可以獲得鎖,從而導致并發問題。為了避免提前釋放鎖,可以使用Lua腳本來確保刪除鎖的原子性,或者使用Redisson等包裝好的客戶端。
      3. 鎖的續約: 如果客戶端的操作時間超過鎖的過期時間,鎖可能會自動釋放,導致并發問題。為了避免鎖自動釋放,可以使用鎖的續約機制,即當鎖即將過期時,客戶端會自動延長鎖的過期時間。Redison等客戶端提供鎖的續約功能。
      4. 腦裂: 在Redis集群中,如果發生腦破裂,即集群分裂成多個獨立的子集群,多個客戶端可能同時獲得鎖,從而導致并發問題。為了避免腦破裂,Redis集群的參數需要合理配置,例如設置
        min-replicas-to-write

        min-replicas-max-lag

        參數。

      5. 重入性: 在某些情況下,相同的線程可能需要多次獲得相同的鎖。如果鎖不支持重新進入,可能會導致死鎖。為了支持重新進入,可以在鎖中記錄線程ID和重新進入次數。Redison等客戶提供可重新進入鎖。
      除了Redis和Zookeeper,還有哪些方案可以實現分布式鎖?

      除Redis和ZooKeeper外,還有以下幾種實現分布式鎖定的方法:

      1. 數據庫: 可使用數據庫的行鎖或樂觀鎖實現分布式鎖。例如,可以使用
        SELECT ... FOR UPDATE

        語句獲取行鎖,或使用版本號實現樂觀鎖。數據庫實現分布式鎖的優點簡單易懂,缺點是性能低,因為需要磁盤IO。

      2. etcd: etcd是一種可用于實現分布式鎖的分布式鍵值存儲系統。etcd的性能高于Zookeeper,但可靠性相對較低。
      3. Consul: Consul是一種服務發現和配置管理系統,也可用于實現分布式鎖。Consul的優點是使用簡單,缺點是性能低。
      4. 基于Paxos/Raft算法的分布式一致性系統: 基于Paxos/Raft算法的分布式一致性系統,如TiDBBOS、為了實現分布式鎖,CockroachDB等。該方案具有可靠性高、復雜性高等優點。

      選擇哪個方案取決于你的具體需求。如果性能要求很高,可以選擇Redis或者ETCD。如果對可靠性要求很高,可以選擇基于Paxos/Raft算法的Zookeeper或分布式一致性系統。如果對復雜性有要求,可以選擇數據庫或者Consul。

      以上是java代碼如何實現分布式鎖 關于java代碼分布式編程基礎教程的詳細信息。

      posted @ 2025-08-25 22:11  天狼座  閱讀(16)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 粉嫩av一区二区三区蜜臀| 欧美人与动牲交A免费观看| 精品综合久久久久久97| 国产迷姦播放在线观看| 辉南县| 黑人好猛厉害爽受不了好大撑| 色吊丝二区三区中文字幕| 亚洲a人片在线观看网址| 四虎永久精品免费视频| 成人午夜免费一区二区三区| 中文字幕在线日韩| 亚洲午夜精品国产电影在线观看| 国产蜜臀av在线一区二区| 欧洲无码一区二区三区在线观看 | 国产成人一区二区三区免费| 国产精品自拍视频我看看| 疯狂做受xxxx高潮欧美日本| 激情综合网激情五月伊人| 午夜福利国产区在线观看| 免费看国产精品3a黄的视频| 亚洲乱码精品久久久久..| 日本一本无道码日韩精品| 国产免费无遮挡吸奶头视频| 男人的天堂av一二三区| 国产最新精品系列第三页| 午夜dv内射一区二区| 欧美男男作爱videos可播放| 国产成人亚洲欧美二区综合| 曲麻莱县| 免费无码中文字幕A级毛片| 日本A级视频在线播放| 国产精品v片在线观看不卡| 五月天丁香婷婷亚洲欧洲国产| 中文字幕有码无码AV| 日韩精品中文字幕人妻| 亚洲最大色综合成人av| 亚洲av片在线免费观看| 光棍天堂在线手机播放免费| 亚洲一区二区三区自拍偷拍| 激情伊人五月天久久综合| 亚洲人成人伊人成综合网无码|