詳解SpringBoot分散式鎖

一、為什麼需要分散式鎖?

在分散式系統中,多個節點需要對同一資源進行並發訪問和操作。如果沒有分散式鎖,很容易出現資源競爭問題,引發數據錯誤或系統崩潰的風險。

例如,假設有兩個客戶端對訂單進行支付,如果沒有分散式鎖,那麼可能會出現一次性支付多次的問題。

分散式鎖能夠有效地解決這些問題,保證各節點之間數據訪問的正確性。

二、SpringBoot分散式鎖的實現方式

1. 基於Redis實現分散式鎖

Redis相當於開發人員搭建分散式鎖的一種途徑,在Redis中提供了setnx方法,如果key不存在則設置成功。因此,我們可以在加鎖時採用setnx方法,如果設置成功則獲取到鎖,否則等待。同時,為了消除其他線程在出現競爭時獲取鎖的等待時間,需使用Redis的Expire命令。


 public boolean lock(String key) {
        long expires = 5 * 60 * 1000;
        long currentValue = System.currentTimeMillis() + expires + 1;
        String currentValueStr = String.valueOf(currentValue);
        if (redisTemplate.opsForValue().setIfAbsent(key, currentValueStr)){
            return true;
        }

        //key 存在,獲取值
        String oldValueStr = (String) redisTemplate.opsForValue().get(key);
        if (oldValueStr !=null && Long.parseLong(oldValueStr) < System.currentTimeMillis()){
            // 獲取上一個鎖到期時間,並設置現在的鎖到期時間
            String  getValue = (String) redisTemplate.opsForValue().getAndSet(key, currentValueStr);
            if (getValue !=null && getValue.equals(oldValueStr)){
                return true;
            }
        }
        return false;
    }

2. 基於Zookeeper實現的分散式鎖

Zookeeper提供豐富的鎖機制,Zookeeper鎖節點的特性自動具有排他性質,基於此可以輕鬆地搭建分散式鎖,實現分散式鎖的本質就是創建一個znode節點。同樣的,當多個線程嘗試創建znode時,只會有最先創建的線程創建成功,其他線程創建失敗,並進入等待狀態。一旦擁有鎖的客戶端釋放了鎖,Zookeeper集群中的所有客戶端都會被通知,然後再次嘗試鎖。


public boolean lock(String lockName) {
    if (zookeeper == null) {
        return false;
    }
    String path = "/lock/" + lockName;
    try {
        Stat stat = zookeeper.exists(path, false);
        if (stat == null) {
            // 如果節點不存在,則創建
            zookeeper.create(path, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        }
        return true;
    } catch (KeeperException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return false;
}

三、SpringBoot分散式鎖的應用

1. 避免緩存穿透

緩存穿透指查詢一個一定不存在的數據,導致這個查詢落在資料庫上,造成資料庫壓力過大。可以通過分散式鎖來避免緩存穿透的問題。當鎖被佔用時,其他線程只需要等待鎖釋放即可,不會重複查詢資料庫。

2. 避免重複提交

在高並發環境下,重複提交請求會使得服務端創建多個相同的訂單,導致數據錯誤。可以在用戶提交訂單時,採用分散式鎖來避免重複提交。

3. 控制資源訪問數量

有時候,我們需要限制並發數,比如簡訊發送介面,單個用戶每次只能發送一個簡訊。這時可以通過分散式鎖來限制並發數,保證介面的正常可用。

四、總結

SpringBoot分散式鎖是解決分散式系統資源安全共享和並發操作的一種重要手段。本文從實現方式和應用場景兩個方面闡述了SpringBoot分散式鎖的實現方法以及常見應用場景。但該方案並非萬能之策,我們在實際使用中也需要根據具體情況進行分析,避免誤用。

原創文章,作者:MYQDI,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/371606.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
MYQDI的頭像MYQDI
上一篇 2025-04-23 18:08
下一篇 2025-04-23 18:08

相關推薦

  • KeyDB Java:完美的分散式高速緩存方案

    本文將從以下幾個方面對KeyDB Java進行詳細闡述:KeyDB Java的特點、安裝和配置、使用示例、性能測試。 一、KeyDB Java的特點 KeyDB Java是KeyD…

    編程 2025-04-29
  • 從ga角度解讀springboot

    springboot作為目前廣受歡迎的Java開發框架,其中的ga機制在整個開發過程中起著至關重要的作用。 一、ga是什麼 ga即Group Artifacts的縮寫,它是Mave…

    編程 2025-04-29
  • Java Hmily分散式事務解決方案

    分散式系統是現在互聯網公司架構中的必備項,但隨著業務的不斷擴展,分散式事務的問題也日益凸顯。為了解決分散式事務問題,Java Hmily分散式事務解決方案應運而生。本文將對Java…

    編程 2025-04-28
  • JL Transaction – 實現分散式事務管理的利器

    本文將為大家介紹JL Transaction,這是一款可以實現分散式事務管理的開源事務框架,它可以幫助企業在分散式環境下有效地解決事務的一致性問題,從而保障系統的穩定性和可靠性。 …

    編程 2025-04-28
  • 使用RPC研發雲實現分散式服務交互

    本文將基於RPC研發雲,闡述分散式服務交互實現的過程和實現方式。 一、RPC研發雲簡介 RPC研發雲是一種基於分散式架構的服務框架,在處理不同語言之間的通信上變得越來越流行。通過使…

    編程 2025-04-28
  • SpringBoot Get方式請求傳參用法介紹

    本文將從以下多個方面對SpringBoot Get方式請求傳參做詳細的闡述,包括URL傳參、路徑傳參、請求頭傳參、請求體傳參等,幫助讀者更加深入地了解Get請求方式下傳參的相關知識…

    編程 2025-04-27
  • 分散式文件系統數據分布演算法

    數據分布演算法是分散式文件系統中的重要技術之一,它能夠實現將文件分散存儲於各個節點上,提高系統的可靠性和性能。在這篇文章中,我們將從多個方面對分散式文件系統數據分布演算法進行詳細的闡述…

    編程 2025-04-27
  • SpringBoot如何設置不輸出Info日誌

    本篇文章將帶您了解如何在SpringBoot項目中關閉Info級別日誌輸出。 一、為什麼要關閉Info日誌 在開發中,我們經常會使用Log4j、Logback等框架來輸出日誌信息,…

    編程 2025-04-27
  • 神經網路代碼詳解

    神經網路作為一種人工智慧技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網路的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網路模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁碟中。在執行sync之前,所有的文件系統更新將不會立即寫入磁碟,而是先緩存在內存…

    編程 2025-04-25

發表回復

登錄後才能評論