最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

分布式鎖詳解以及Spring?Boot實(shí)戰(zhàn)示例代碼

 更新時(shí)間:2025年09月03日 09:25:02   作者:老張還是少年  
在分布式系統(tǒng)中,使用分布式鎖是保證共享資源獨(dú)占性的重要方式,這篇文章主要介紹了分布式鎖詳解及Spring?Boot實(shí)戰(zhàn)的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

在分布式系統(tǒng)中,多個(gè)服務(wù)實(shí)例可能同時(shí)操作共享資源(如數(shù)據(jù)庫中的同一訂單、庫存記錄),若缺乏協(xié)調(diào)機(jī)制,會(huì)導(dǎo)致數(shù)據(jù)不一致(如超賣、重復(fù)下單)。分布式鎖正是解決這類問題的核心技術(shù),它能保證同一時(shí)間只有一個(gè)服務(wù)實(shí)例執(zhí)行特定臨界區(qū)代碼。

一、分布式鎖的核心特性

一個(gè)可靠的分布式鎖需滿足以下特性:

  • 互斥性:任意時(shí)刻只有一個(gè)線程持有鎖。
  • 安全性:鎖只能被持有它的線程釋放。
  • 可用性:即使部分節(jié)點(diǎn)故障,鎖仍能正常獲取和釋放。
  • 防死鎖:避免因線程崩潰導(dǎo)致鎖永久無法釋放。
  • 冪等性:重復(fù)獲取 / 釋放鎖不會(huì)產(chǎn)生副作用。

二、分布式鎖的實(shí)現(xiàn)方案及原理

常見實(shí)現(xiàn)方式包括基于數(shù)據(jù)庫、Redis、ZooKeeper 等,不同方式的原理各有不同。

1. 基于數(shù)據(jù)庫的分布式鎖

原理:利用數(shù)據(jù)庫的唯一索引或悲觀鎖來實(shí)現(xiàn)。例如,創(chuàng)建一張鎖表,包含資源標(biāo)識(shí)、持有線程標(biāo)識(shí)、過期時(shí)間等字段,給資源標(biāo)識(shí)字段創(chuàng)建唯一索引。當(dāng)需要獲取鎖時(shí),向表中插入一條記錄,若插入成功則表示獲取到鎖;釋放鎖時(shí),刪除該記錄。為防止死鎖,可定期清理過期未釋放的鎖。

優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):實(shí)現(xiàn)簡單,無需額外中間件。
  • 缺點(diǎn):性能較差,數(shù)據(jù)庫壓力大;易出現(xiàn)鎖表問題;不支持鎖自動(dòng)續(xù)期等高級(jí)特性。

2. 基于 Redis 的分布式鎖

原理:利用 Redis 的SET命令的原子性。核心命令如下:

# 僅當(dāng)key不存在時(shí)設(shè)置值,過期時(shí)間10秒,返回OK表示獲取鎖成功

SET lock:resource true NX PX 10000
  • NX:僅在鍵不存在時(shí)才設(shè)置(保證互斥性)。
  • PX 10000:設(shè)置鍵的過期時(shí)間為 10 秒(防死鎖)。

釋放鎖時(shí),需通過 Lua 腳本保證原子性,先判斷鎖是否由當(dāng)前線程持有,再刪除鎖:

if redis.call('get', KEYS[1]) == ARGV[1] then
    return redis.call('del', KEYS[1])
else
    return 0
end

優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):性能高,操作簡單;支持過期時(shí)間設(shè)置。
  • 缺點(diǎn):在 Redis 集群環(huán)境下,可能存在主從同步延遲導(dǎo)致的鎖丟失問題;需自行處理鎖續(xù)期等問題。

由于 Redis 的高性能和易用性,它成為分布式鎖的主流選擇,本文后續(xù)重點(diǎn)介紹基于 Redis 的分布式鎖實(shí)現(xiàn)。

3. 基于 ZooKeeper 的分布式鎖

原理:利用 ZooKeeper 的節(jié)點(diǎn)特性和 Watcher 機(jī)制。ZooKeeper 的節(jié)點(diǎn)分為持久節(jié)點(diǎn)、臨時(shí)節(jié)點(diǎn)、持久順序節(jié)點(diǎn)、臨時(shí)順序節(jié)點(diǎn)。分布式鎖通常使用臨時(shí)順序節(jié)點(diǎn),當(dāng)需要獲取鎖時(shí),在指定節(jié)點(diǎn)下創(chuàng)建一個(gè)臨時(shí)順序節(jié)點(diǎn),然后判斷當(dāng)前節(jié)點(diǎn)是否為序號(hào)最小的節(jié)點(diǎn),若是則獲取到鎖;若不是,則監(jiān)聽序號(hào)比當(dāng)前節(jié)點(diǎn)小的最后一個(gè)節(jié)點(diǎn),當(dāng)該節(jié)點(diǎn)被刪除時(shí),重新判斷。釋放鎖時(shí),刪除創(chuàng)建的臨時(shí)節(jié)點(diǎn),由于是臨時(shí)節(jié)點(diǎn),當(dāng)持有鎖的線程崩潰時(shí),節(jié)點(diǎn)會(huì)自動(dòng)刪除,避免死鎖。

優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):可靠性高,不存在鎖丟失問題;支持公平鎖;自帶 Watcher 機(jī)制,可實(shí)現(xiàn)鎖的自動(dòng)釋放和喚醒。
  • 缺點(diǎn):性能相對(duì) Redis 較低;部署和維護(hù)成本高。

三、Spring Boot 集成分布式鎖的相關(guān)依賴及對(duì)比

1. 基于 Redis 的依賴

  • spring-boot-starter-data-redis
    • 提供了 Redis 的基本操作模板(RedisTemplate),可用于手動(dòng)實(shí)現(xiàn)分布式鎖。
    • 需自行處理鎖的獲取、釋放、續(xù)期等邏輯,實(shí)現(xiàn)相對(duì)復(fù)雜,但靈活性高。
  • redisson-spring-boot-starter
    • 是 Redis 官方推薦的 Java 客戶端,內(nèi)置了分布式鎖的完整實(shí)現(xiàn),支持自動(dòng)續(xù)期、公平鎖、可重入鎖等高級(jí)特性。
    • 封裝了復(fù)雜的底層邏輯,使用簡單,適合生產(chǎn)環(huán)境。

2. 基于 ZooKeeper 的依賴

  • spring-cloud-starter-zookeeper-discovery
    • 主要用于服務(wù)發(fā)現(xiàn),但也可借助 ZooKeeper 客戶端操作 ZooKeeper 實(shí)現(xiàn)分布式鎖。
    • 需要自行基于 ZooKeeper 的 API 實(shí)現(xiàn)鎖的邏輯,較為繁瑣。
  • curator-recipes
    • 是 ZooKeeper 的客戶端框架,提供了分布式鎖等常用功能的封裝,如 InterProcessMutex 等類可直接用于實(shí)現(xiàn)分布式鎖。
    • 簡化了 ZooKeeper 分布式鎖的實(shí)現(xiàn),可靠性高。

3. 依賴對(duì)比

依賴

基于中間件

特點(diǎn)

適用場景

spring-boot-starter-data-redis

Redis

基礎(chǔ)操作支持,需自行實(shí)現(xiàn)鎖邏輯

簡單場景,對(duì)靈活性要求高

redisson-spring-boot-starter

Redis

內(nèi)置完整鎖實(shí)現(xiàn),支持高級(jí)特性

生產(chǎn)環(huán)境,復(fù)雜業(yè)務(wù)場景

spring-cloud-starter-zookeeper-discovery

ZooKeeper

主要用于服務(wù)發(fā)現(xiàn),鎖實(shí)現(xiàn)需自行開發(fā)

已使用 ZooKeeper 做服務(wù)發(fā)現(xiàn),簡單鎖場景

curator-recipes

ZooKeeper

封裝了分布式鎖功能,可靠性高

對(duì)鎖可靠性要求高的場景

四、Spring Boot 集成 Redis 分布式鎖實(shí)戰(zhàn)

1. 環(huán)境準(zhǔn)備

pom.xml 依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
    <groupId>org.redisson</groupId> <!-- 推薦使用Redisson簡化鎖操作 -->
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.23.3</version>
</dependency>

Redis 配置(application.yml)

spring:
  redis:
    host: localhost
    port: 6379
    database: 0
    timeout: 3000ms

2. 基于 Redisson 的分布式鎖實(shí)現(xiàn)

Redisson 是 Redis 官方推薦的 Java 客戶端,內(nèi)置了分布式鎖的完整實(shí)現(xiàn),支持自動(dòng)續(xù)期、公平鎖、可重入鎖等高級(jí)特性。

分布式鎖工具類

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;

@Component
public class RedisDistributedLock {

    private final RedissonClient redissonClient;

    public RedisDistributedLock(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    /**
     * 獲取分布式鎖
     * @param lockKey 鎖標(biāo)識(shí)
     * @param waitTime 等待時(shí)間(獲取鎖的最大等待時(shí)長)
     * @param leaseTime 鎖持有時(shí)間(自動(dòng)釋放時(shí)間)
     * @return 鎖對(duì)象
     */
    public RLock lock(String lockKey, long waitTime, long leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            // 嘗試獲取鎖,最多等待waitTime,持有l(wèi)easeTime后自動(dòng)釋放
            boolean isLocked = lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
            if (isLocked) {
                return lock;
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return null;
    }

    /**
     * 釋放鎖
     * @param lock 鎖對(duì)象
     */
    public void unlock(RLock lock) {
        if (lock != null && lock.isHeldByCurrentThread()) {
            lock.unlock();
        }
    }
}

3. 業(yè)務(wù)場景示例:庫存扣減

Service 層代碼

import org.redisson.api.RLock;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

@Service
public class InventoryService {

    @Resource
    private RedisDistributedLock distributedLock;
    @Resource
    private InventoryMapper inventoryMapper;  // 假設(shè)已實(shí)現(xiàn)數(shù)據(jù)庫操作

    /**
     * 扣減商品庫存
     * @param productId 商品ID
     * @param quantity 扣減數(shù)量
     * @return 操作結(jié)果
     */
    public boolean deductInventory(Long productId, int quantity) {
        // 鎖標(biāo)識(shí):通常用業(yè)務(wù)資源唯一標(biāo)識(shí)(如商品ID)
        String lockKey = "lock:inventory:" + productId;
        RLock lock = null;
        try {
            // 獲取鎖:最多等待3秒,持有10秒后自動(dòng)釋放
            lock = distributedLock.lock(lockKey, 3, 10);
            if (lock == null) {
                // 獲取鎖失?。ㄈ绯瑫r(shí))
                return false;
            }

            // 臨界區(qū)代碼:查詢庫存并扣減
            int currentStock = inventoryMapper.selectStockByProductId(productId);
            if (currentStock >= quantity) {
                inventoryMapper.updateStock(productId, currentStock - quantity);
                return true;
            } else {
                // 庫存不足
                return false;
            }
        } finally {
            // 確保鎖釋放
            distributedLock.unlock(lock);
        }
    }
}

五、關(guān)鍵注意事項(xiàng)

  • 鎖的粒度:鎖標(biāo)識(shí)應(yīng)精準(zhǔn)到具體資源(如lock:order:123而非lock:order),避免鎖范圍過大導(dǎo)致性能瓶頸。
  • 過期時(shí)間設(shè)置:需大于業(yè)務(wù)執(zhí)行時(shí)間,Redisson 的watch dog機(jī)制會(huì)自動(dòng)續(xù)期(默認(rèn)每 30 秒續(xù)期一次)。
  • 異常處理:必須在finally塊中釋放鎖,避免因業(yè)務(wù)異常導(dǎo)致鎖泄漏。
  • 重試機(jī)制:獲取鎖失敗時(shí)可添加有限重試邏輯(如循環(huán) 3 次),提高成功率。

六、進(jìn)階優(yōu)化方向

  • 公平鎖:通過redissonClient.getFairLock(lockKey)實(shí)現(xiàn),避免線程饑餓。
  • 紅鎖(RedLock):在多 Redis 節(jié)點(diǎn)環(huán)境中,通過多個(gè)實(shí)例獲取鎖提高可靠性(適合極高一致性場景)。
  • 緩存與數(shù)據(jù)庫一致性:結(jié)合本地鎖(synchronized)與分布式鎖,減少分布式鎖的使用頻率。

通過不同的分布式鎖實(shí)現(xiàn)方式和相關(guān)依賴,Spring Boot 應(yīng)用可在分布式環(huán)境中安全地操作共享資源。在實(shí)際開發(fā)中,需根據(jù)業(yè)務(wù)場景和性能需求選擇合適的實(shí)現(xiàn)方式和依賴,Redisson 等成熟工具可大幅降低實(shí)現(xiàn)復(fù)雜度,建議在生產(chǎn)環(huán)境中優(yōu)先采用。

總結(jié)

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

相關(guān)文章

  • 解決idea 通過build project 手動(dòng)觸發(fā)熱部署失敗的問題

    解決idea 通過build project 手動(dòng)觸發(fā)熱部署失敗的問題

    在debug運(yùn)行項(xiàng)目的過程中,并且保證(不添加方法,不修改方法名)一定的規(guī)則的情況下,可以通過build project 來手動(dòng)熱部署項(xiàng)目,本文給大家介紹解決idea 通過build project 手動(dòng)觸發(fā)熱部署失敗的問題,感興趣的朋友一起看看吧
    2023-12-12
  • java代碼實(shí)現(xiàn)編譯源文件

    java代碼實(shí)現(xiàn)編譯源文件

    這篇文章主要為大家詳細(xì)介紹了Java通過?JavaCompiler?實(shí)現(xiàn)編譯源文件的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2025-01-01
  • Java生產(chǎn)者和消費(fèi)者例子_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java生產(chǎn)者和消費(fèi)者例子_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    生產(chǎn)者-消費(fèi)者(producer-consumer)問題,也稱作有界緩沖區(qū)(bounded-buffer)問題,兩個(gè)進(jìn)程共享一個(gè)公共的固定大小的緩沖區(qū)。下文通過實(shí)例給大家介紹java生產(chǎn)者和消費(fèi)者,感興趣的朋友一起學(xué)習(xí)吧
    2017-05-05
  • Java的HashMap源碼解析

    Java的HashMap源碼解析

    這篇文章主要介紹了Java的HashMap源碼解析,HashMap是一個(gè)用于存儲(chǔ)Key-Value鍵值對(duì)的集合,每一個(gè)鍵值對(duì)是一個(gè)Node,后臺(tái)是用一個(gè)Node數(shù)組來存放數(shù)據(jù),這個(gè)Node數(shù)組就是HashMap的主干,需要的朋友可以參考下
    2023-11-11
  • 通過Java實(shí)現(xiàn)添加或刪除PDF中的附件

    通過Java實(shí)現(xiàn)添加或刪除PDF中的附件

    當(dāng)我們?cè)谥谱鱌DF文件或者PPT演示文稿的時(shí)候,為了讓自己的文件更全面詳細(xì),就會(huì)在文件中添加附件。本文為大家整理了Java實(shí)現(xiàn)添加或刪除PDF中的附件的方法,需要的可以參考下
    2023-01-01
  • Java 設(shè)計(jì)模式之適配器模式詳解

    Java 設(shè)計(jì)模式之適配器模式詳解

    設(shè)計(jì)模式(Design pattern)是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類編目的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。使用設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性
    2021-11-11
  • 原理分析SonarQube中IdentityProvider賬戶互斥現(xiàn)象

    原理分析SonarQube中IdentityProvider賬戶互斥現(xiàn)象

    這篇文章主要為大家介紹分析SonarQube中IdentityProvider賬戶互斥現(xiàn)象原理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-02-02
  • 關(guān)于mybatis if else if 條件判斷SQL片段表達(dá)式取值和拼接問題

    關(guān)于mybatis if else if 條件判斷SQL片段表達(dá)式取值和拼接問題

    這篇文章主要介紹了mybatis if else if 條件判斷SQL片段表達(dá)式取值和拼接,文章通過自己真實(shí)使用的例子給大家詳細(xì)介紹,需要的朋友可以參考下
    2021-09-09
  • java繪制國際象棋與中國象棋棋盤

    java繪制國際象棋與中國象棋棋盤

    這篇文章主要為大家詳細(xì)介紹了java繪制國際象棋與中國象棋棋盤,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • SpringCloud中的Ribbon負(fù)載均衡詳細(xì)解讀

    SpringCloud中的Ribbon負(fù)載均衡詳細(xì)解讀

    這篇文章主要介紹了SpringCloud中的Ribbon負(fù)載均衡詳細(xì)解讀,當(dāng)系統(tǒng)面臨大量的用戶訪問,負(fù)載過高的時(shí)候,通常會(huì)增加服務(wù)器數(shù)量來進(jìn)行橫向擴(kuò)展(集群),多個(gè)服務(wù)器的負(fù)載需要均衡,以免出現(xiàn)服務(wù)器負(fù)載不均衡,部分服務(wù)器負(fù)載較大,部分服務(wù)器負(fù)載較小的情況,需要的朋友可以參考下
    2023-11-11

最新評(píng)論

阳江市| 昭平县| 盐津县| 金寨县| 北流市| 桦甸市| 仁寿县| 綦江县| 丰都县| 渭南市| 凤山市| 沂南县| 天峻县| 罗平县| 贵阳市| 南澳县| 胶州市| 黎川县| 桂东县| 伊川县| 青川县| 灵璧县| 宝坻区| 思茅市| 名山县| 靖安县| 鸡泽县| 贵阳市| 富裕县| 临沧市| 永修县| 鄯善县| 麦盖提县| 清镇市| 灌南县| 安达市| 噶尔县| 许昌县| 固始县| 三明市| 黔西县|