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

Java實(shí)現(xiàn)Redisson分布式鎖的10大陷阱與避坑指南

 更新時(shí)間:2026年04月16日 08:58:08   作者:別掉進(jìn)我的異常  
本文介紹了Redisson分布式鎖的基礎(chǔ)用法與高級(jí)特性,包括基本鎖操作、公平鎖、讀寫鎖、聯(lián)鎖和紅鎖等實(shí)現(xiàn)方式,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一、Redisson分布式鎖基礎(chǔ)用法

1.1 基礎(chǔ)依賴配置

<!-- Maven依賴配置 -->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.18.0</version>
</dependency>

yaml

singleServerConfig:
  address: "redis://127.0.0.1:6379"
  database: 0
  connectionPoolSize: 64
  connectionMinimumIdleSize: 10

1.2 基本鎖操作

// 獲取分布式鎖實(shí)例
RLock lock = redissonClient.getLock("myLock");
// 方式1:阻塞式加鎖(推薦用法)
lock.lock();
try {
    // 執(zhí)行業(yè)務(wù)邏輯
    executeBusiness();
} finally {
    // 確保鎖被釋放
    lock.unlock();
}
// 方式2:帶超時(shí)的嘗試加鎖
boolean isLocked = lock.tryLock(10, 30, TimeUnit.SECONDS);
if (isLocked) {
    try {
        executeBusiness();
    } finally {
        lock.unlock();
    }
}
// 方式3:異步加鎖
RFuture<Void> lockFuture = lock.lockAsync();
lockFuture.whenComplete((result, exception) -> {
    try {
        executeBusiness();
    } finally {
        lock.unlockAsync();
    }
});

二、高級(jí)特性使用

2.1 公平鎖(Fair Lock)

// 獲取公平鎖實(shí)例(按請(qǐng)求順序獲得鎖)
RLock fairLock = redissonClient.getFairLock("fairLock");
fairLock.lock();
try {
    // 業(yè)務(wù)邏輯
} finally {
    fairLock.unlock();
}

2.2 讀寫鎖(ReadWrite Lock)

// 讀寫鎖實(shí)現(xiàn)讀多寫少場(chǎng)景
RReadWriteLock rwLock = redissonClient.getReadWriteLock("rwLock");
// 讀鎖(共享鎖,允許多個(gè)線程同時(shí)持有)
RLock readLock = rwLock.readLock();
readLock.lock();
try {
    // 讀取操作
} finally {
    readLock.unlock();
}
// 寫鎖(排他鎖,只能有一個(gè)線程持有)
RLock writeLock = rwLock.writeLock();
writeLock.lock();
try {
    // 寫入操作
} finally {
    writeLock.unlock();
}

2.3 聯(lián)鎖(MultiLock)

// 同時(shí)鎖定多個(gè)資源
RLock lock1 = redissonClient.getLock("lock1");
RLock lock2 = redissonClient.getLock("lock2");
RLock lock3 = redissonClient.getLock("lock3");
RedissonMultiLock multiLock = new RedissonMultiLock(lock1, lock2, lock3);
multiLock.lock();
try {
    // 操作多個(gè)資源的業(yè)務(wù)邏輯
} finally {
    multiLock.unlock();
}

2.4 紅鎖(RedLock)

// 紅鎖(RedLock算法,需要多個(gè)Redis實(shí)例)
Config config1 = new Config();
config1.useSingleServer().setAddress("redis://127.0.0.1:6379");
RedissonClient client1 = Redisson.create(config1);
Config config2 = new Config();
config2.useSingleServer().setAddress("redis://127.0.0.1:6380");
RedissonClient client2 = Redisson.create(config2);
RLock lock1 = client1.getLock("lock");
RLock lock2 = client2.getLock("lock");
RedissonRedLock redLock = new RedissonRedLock(lock1, lock2);
redLock.lock();
try {
    // 高安全要求的業(yè)務(wù)邏輯
} finally {
    redLock.unlock();
}

三、鎖失效場(chǎng)景及解決方案

3.1 鎖過期時(shí)間設(shè)置不當(dāng)

// ? 錯(cuò)誤示例:鎖過期時(shí)間太短
lock.lock(5, TimeUnit.SECONDS);  // 業(yè)務(wù)如果超過5秒會(huì)出問題
// ? 正確做法:合理評(píng)估并設(shè)置鎖超時(shí)時(shí)間
// 或者使用看門狗機(jī)制(默認(rèn)30秒,每10秒續(xù)期)
lock.lock();  // 使用看門狗自動(dòng)續(xù)期
// ? 或明確指定足夠長(zhǎng)的超時(shí)時(shí)間
lock.lock(30, TimeUnit.SECONDS);

3.2 未正確處理鎖釋放

// ? 錯(cuò)誤示例:未在finally中釋放鎖
lock.lock();
executeBusiness();
// 如果這里拋出異常,鎖永遠(yuǎn)不會(huì)釋放
// ? 正確示例:確保鎖釋放
lock.lock();
try {
    executeBusiness();
} finally {
    // 檢查當(dāng)前線程是否持有鎖
    if (lock.isHeldByCurrentThread()) {
        lock.unlock();
    }
}

3.3 鎖重入問題

// ? 錯(cuò)誤示例:在遞歸調(diào)用中重復(fù)加鎖
public void recursiveMethod(int n) {
    lock.lock();
    try {
        if (n > 0) {
            recursiveMethod(n - 1);  // 重復(fù)獲取鎖,造成死鎖
        }
    } finally {
        lock.unlock();
    }
}
// ? 正確示例:Redisson鎖支持可重入
public void recursiveMethod(int n) {
    lock.lock();
    try {
        if (n > 0) {
            recursiveMethod(n - 1);  // 可重入鎖,不會(huì)死鎖
        }
    } finally {
        lock.unlock();
    }
}

3.4 集群環(huán)境下的特殊問題

// ? 錯(cuò)誤示例:主從切換導(dǎo)致鎖丟失
// 在主從架構(gòu)中,主節(jié)點(diǎn)寫入鎖后未同步到從節(jié)點(diǎn)就宕機(jī)
// ? 解決方案1:使用紅鎖(RedLock)
RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);
// ? 解決方案2:使用高可用集群模式
Config config = new Config();
config.useClusterServers()
    .addNodeAddress("redis://127.0.0.1:7001")
    .addNodeAddress("redis://127.0.0.1:7002")
    .addNodeAddress("redis://127.0.0.1:7003");

四、最佳實(shí)踐與注意事項(xiàng)

4.1 鎖命名規(guī)范

// ? 使用業(yè)務(wù)相關(guān)的有意義的鎖名
// 格式:業(yè)務(wù):資源類型:資源標(biāo)識(shí)
String lockKey = "order:pay:lock:" + orderId;
RLock lock = redissonClient.getLock(lockKey);
// ? 避免使用通用鎖名
RLock badLock = redissonClient.getLock("lock");  // 過于通用,易沖突

4.2 避免鎖粒度過粗或過細(xì)

// ? 鎖粒度過粗(性能瓶頸)
RLock globalLock = redissonClient.getLock("globalOrderLock");
// ? 鎖粒度過細(xì)(管理復(fù)雜)
RLock itemLock = redissonClient.getLock("orderItem:" + itemId + ":" + userId);
// ? 合適的鎖粒度
RLock orderLock = redissonClient.getLock("order:" + orderId);

4.3 超時(shí)和重試策略

// 配置合理的重試策略
boolean locked = false;
int retryCount = 0;
int maxRetries = 3;
while (!locked && retryCount < maxRetries) {
    try {
        locked = lock.tryLock(100, 10000, TimeUnit.MILLISECONDS);
        if (locked) {
            // 執(zhí)行業(yè)務(wù)邏輯
            executeBusiness();
        }
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        break;
    } finally {
        if (locked) {
            lock.unlock();
        }
    }
    retryCount++;
    if (!locked && retryCount < maxRetries) {
        Thread.sleep(100 * retryCount); // 指數(shù)退避
    }
}

4.4 監(jiān)控與日志

// 添加鎖操作的監(jiān)控點(diǎn)
@Slf4j
@Component
public class DistributedLockService {
    @Autowired
    private RedissonClient redissonClient;
    public <T> T executeWithLock(String lockKey, long waitTime, long leaseTime, 
                                Supplier<T> supplier) {
        RLock lock = redissonClient.getLock(lockKey);
        long start = System.currentTimeMillis();
        try {
            boolean acquired = lock.tryLock(waitTime, leaseTime, TimeUnit.MILLISECONDS);
            if (!acquired) {
                log.warn("獲取鎖失敗,lockKey: {}", lockKey);
                throw new LockAcquireException("獲取分布式鎖失敗");
            }
            log.info("成功獲取鎖,lockKey: {}, 耗時(shí): {}ms", 
                    lockKey, System.currentTimeMillis() - start);
            return supplier.get();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new LockAcquireException("鎖獲取被中斷", e);
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
                log.info("釋放鎖,lockKey: {}", lockKey);
            }
        }
    }
}

4.5 性能優(yōu)化建議

# 優(yōu)化配置示例
lockWatchdogTimeout: 30000  # 看門狗超時(shí)時(shí)間
keepPubSubOrder: true       # 保持訂閱順序
retryInterval: 300          # 重試間隔(ms)
retryAttempts: 3            # 重試次數(shù)
timeout: 3000               # 命令超時(shí)時(shí)間(ms)

五、常見問題排查清單

問題現(xiàn)象可能原因解決方案
鎖無故釋放業(yè)務(wù)執(zhí)行時(shí)間超過鎖過期時(shí)間合理設(shè)置leaseTime或使用看門狗
鎖無法釋放未在finally中釋放鎖確保鎖釋放邏輯在finally塊中
鎖競(jìng)爭(zhēng)激烈鎖粒度過粗細(xì)化鎖粒度,按資源拆分
Redis連接失敗網(wǎng)絡(luò)問題或Redis宕機(jī)檢查網(wǎng)絡(luò),配置連接池和重試機(jī)制
死鎖鎖重入問題或異常未釋放鎖使用可重入鎖,確保異常時(shí)釋放鎖

六、總結(jié)

Redisson分布式鎖提供了強(qiáng)大的功能和靈活的配置選項(xiàng),但在使用時(shí)需要注意:

  • 合理設(shè)置超時(shí)時(shí)間:避免業(yè)務(wù)未完成鎖已過期
  • 確保鎖必定釋放:在finally塊中釋放鎖
  • 選擇合適的鎖類型:根據(jù)場(chǎng)景選擇普通鎖、公平鎖、讀寫鎖等
  • 注意鎖粒度:平衡并發(fā)性能和數(shù)據(jù)安全
  • 考慮高可用:在集群環(huán)境下使用紅鎖或集群模式
  • 添加監(jiān)控:記錄鎖的獲取和釋放情況,便于排查問題

通過遵循以上最佳實(shí)踐,可以有效避免分布式鎖的常見問題,確保分布式系統(tǒng)的數(shù)據(jù)一致性和高可用性。

到此這篇關(guān)于Java實(shí)現(xiàn)Redisson分布式鎖的10大陷阱與避坑指南的文章就介紹到這了,更多相關(guān)Java Redisson分布式鎖陷阱內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java 集合去重的三種方法

    Java 集合去重的三種方法

    本主要介紹了Java 集合去重的三種方法,包含HashSet,Stream API和手動(dòng)遍歷并使用Map三種,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-07-07
  • Java枚舉與.net枚舉區(qū)別詳解

    Java枚舉與.net枚舉區(qū)別詳解

    這篇文章主要介紹了Java枚舉與.net枚舉區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • Mybatisplus如何存儲(chǔ)List、Map

    Mybatisplus如何存儲(chǔ)List、Map

    這篇文章主要介紹了Mybatisplus如何存儲(chǔ)List、Map問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 關(guān)于idea2022.2?閃退的問題

    關(guān)于idea2022.2?閃退的問題

    最近更新了idea2022.2版本,這是一個(gè)比較大的軟件版本更迭,下面小編給大家介紹下idea2022.2?閃退的問題及解決方法,需要的朋友可以參考下
    2022-08-08
  • 詳解SpringBoot與SpringCloud的版本對(duì)應(yīng)詳細(xì)版

    詳解SpringBoot與SpringCloud的版本對(duì)應(yīng)詳細(xì)版

    這篇文章主要介紹了詳解SpringBoot與SpringCloud的版本對(duì)應(yīng)詳細(xì)版,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 深入理解Java設(shè)計(jì)模式之抽象工廠模式

    深入理解Java設(shè)計(jì)模式之抽象工廠模式

    這篇文章主要介紹了JAVA設(shè)計(jì)模式之抽象工廠模式的的相關(guān)資料,文中示例代碼非常詳細(xì),供大家參考和學(xué)習(xí),感興趣的朋友可以了解下
    2021-11-11
  • 詳解springboot?springsecuroty中的注銷和權(quán)限控制問題

    詳解springboot?springsecuroty中的注銷和權(quán)限控制問題

    這篇文章主要介紹了springboot-springsecuroty?注銷和權(quán)限控制,賬戶注銷需要在SecurityConfig中加入開啟注銷功能的代碼,權(quán)限控制要導(dǎo)入springsecurity和thymeleaf的整合依賴,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2022-03-03
  • 淺談SpringCloud之Ribbon詳解

    淺談SpringCloud之Ribbon詳解

    這篇文章主要介紹了淺談SpringCloud之Ribbon,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)SpringCloud的小伙伴們有很大的幫助,需要的朋友可以參考下
    2021-05-05
  • 如何使用Maven管理項(xiàng)目?Maven管理項(xiàng)目實(shí)例

    如何使用Maven管理項(xiàng)目?Maven管理項(xiàng)目實(shí)例

    下面小編就為大家?guī)硪黄绾问褂肕aven管理項(xiàng)目?Maven管理項(xiàng)目實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-06-06
  • IDEA2020.1使用LeetCode插件運(yùn)行并調(diào)試本地樣例的方法詳解

    IDEA2020.1使用LeetCode插件運(yùn)行并調(diào)試本地樣例的方法詳解

    這篇文章主要介紹了IDEA2020.1使用LeetCode插件運(yùn)行并調(diào)試本地樣例的方法,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2020-09-09

最新評(píng)論

凉城县| 平武县| 左权县| 墨竹工卡县| 甘泉县| 礼泉县| 句容市| 山丹县| 灯塔市| 进贤县| 九江县| 分宜县| 原阳县| 开平市| 万载县| 商丘市| 桂林市| 潼南县| 开江县| 龙门县| 平乐县| 沅陵县| 武宁县| 深泽县| 香格里拉县| 嘉义县| 普兰县| 伊吾县| 洞口县| 栖霞市| 台安县| 蒲江县| 牡丹江市| 河曲县| 拜城县| 铜梁县| 和龙市| 崇礼县| 西充县| 双鸭山市| 洛川县|