亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Redis分布式鎖一定要避開的兩個坑

 更新時間:2023年04月13日 09:03:40   作者:JAVA前線  
這篇文章主要為大家詳細介紹了Redis中分布式鎖一定要避開的兩個坑以及對應(yīng)的解決方法,文中的示例代碼講解詳細,希望對大家有所幫助

1 第一個坑:錯誤釋放鎖時機

1.1. 發(fā)現(xiàn)問題

分析以下代碼存在什么問題:

// 分布式鎖服務(wù)
public interface RedisLockService {
    // 獲取鎖
    public boolean getLock(String key);
    // 釋放鎖
    public boolean releaseLock(String key);
}

// 業(yè)務(wù)服務(wù)
public class BizService {

    @Resource
    private RedisLockService redisLockService;

    public void bizMethod(String bizId) {
        try {
            // 獲取鎖
            if(redisLockService.getLock(bizId)) {
                // 業(yè)務(wù)重復(fù)校驗
                if(!bizValidate(bizId)) {
                    throw new BizException(ErrorBizCode.REPEATED);
                }
                // 執(zhí)行業(yè)務(wù)
                return doBusiness();
            }
            // 獲取鎖失敗
            throw new BizException(ErrorBizCode.GET_LOCK_ERROR);
        } finally {
            // 釋放鎖
            redisLockService.releaseLock(bizId);
        }
    }
}

上述代碼看似沒問題,實則隱藏大問題。問題在于釋放鎖時沒有校驗當前線程是否拿到鎖:

  • 線程1和線程2同一時刻訪問業(yè)務(wù)方法
  • 線程2獲取鎖成功,進行業(yè)務(wù)處理
  • 線程1沒有獲取到鎖,但是釋放鎖成功
  • 此時有線程3嘗試獲取鎖成功,但是線程2業(yè)務(wù)沒有處理完,所以線程3不會導(dǎo)致業(yè)務(wù)重復(fù)異常
  • 最終導(dǎo)致線程2和線程3重復(fù)執(zhí)行業(yè)務(wù)

1.2 解決問題

解決方案是在確認獲取鎖成功后才允許釋放鎖:

public class BizService {

    @Resource
    private RedisLockService redisLockService;

    public void bizMethod(String bizId) {
        boolean getLockSuccess = false;
        try {
            // 嘗試獲取鎖
            getLockSuccess = redisLockService.getLock(bizId);
            // 獲取鎖成功
            if(getLockSuccess) {
                // 業(yè)務(wù)重復(fù)校驗
                if(!bizValidate(bizId)) {
                    throw new BizException(ErrorBizCode.REPEATED);
                }
                // 執(zhí)行業(yè)務(wù)
                return doBusiness();
            }
            // 獲取鎖失敗
            throw new BizException(ErrorBizCode.GET_LOCK_ERROR);
        } finally {
            // 獲取鎖成功才允許釋放鎖
            if(getLockSuccess) {
                redisLockService.releaseLock(bizId);
            }
        }
    }
}

2 第二個坑:緩存失效問題

第二個問題是Redis還存在內(nèi)存清理機制,可能會導(dǎo)致分布式鎖失效。

2.1 過期清理機制

(1) 定期刪除

Redis定時檢查哪些key已經(jīng)過期,發(fā)現(xiàn)過期則刪除

(2) 惰性刪除

如果key非常多,定期刪除會非常消耗資源,所以引入惰性刪除策略

如果Redis訪問key時發(fā)現(xiàn)已經(jīng)過期則直接刪除

2.2 內(nèi)存回收機制

當內(nèi)存不足時Redis會選擇一些元素進行刪除:

no-enviction

禁止驅(qū)逐數(shù)據(jù),新寫入操作會報錯

volatile-lru

從已設(shè)置過期時間的數(shù)據(jù)集選擇最近最少使用的數(shù)據(jù)淘汰

volatile-ttl

從已設(shè)置過期時間的數(shù)據(jù)集選擇將要過期的數(shù)據(jù)淘汰

volatile-random

從已設(shè)置過期時間的數(shù)據(jù)集選擇任意的數(shù)據(jù)淘汰

allkeys-lru

從數(shù)據(jù)集選擇最近最少使用的數(shù)據(jù)淘汰

allkeys-random

從數(shù)據(jù)集選擇任意的數(shù)據(jù)淘汰

至少存在兩種場景導(dǎo)致分布式鎖失效問題:

  • 場景一:Redis內(nèi)存不足進行內(nèi)存回收,使用allkeys-lru或者allkeys-random回收策略導(dǎo)致鎖失效
  • 場景二:線程獲取分布式鎖成功,但處理業(yè)務(wù)時間過長,此時鎖到期被定時清理,導(dǎo)致其它線程獲取鎖成功并重復(fù)執(zhí)行業(yè)務(wù)

2.3 樂觀鎖

通用方案是在數(shù)據(jù)庫層保護,例如庫存扣減業(yè)務(wù)在數(shù)據(jù)庫層用樂觀鎖,原理參看《MySQL樂觀鎖扣減庫存原理圖解》這篇文章。

udpate goods set stock = stock - #{acquire} 
where sku_id = #{skuId} and stock - #{acquire} >= 0

到此這篇關(guān)于Redis分布式鎖一定要避開的兩個坑的文章就介紹到這了,更多相關(guān)Redis分布式鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis之Redisson原理詳解

    Redis之Redisson原理詳解

    Redisson 顧名思義,Redis 的兒子,本質(zhì)上還是 Redis 加鎖,不過是對 Redis 做了很多封裝,它不僅提供了一系列的分布式的 Java 常用對象,還提供了許多分布式服務(wù),本文將詳細給大家介紹Redisson原理
    2023-06-06
  • 使用Redis如何設(shè)置永久有效

    使用Redis如何設(shè)置永久有效

    這篇文章主要介紹了使用Redis如何設(shè)置永久有效,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 聊一聊Redis與MySQL雙寫一致性如何保證

    聊一聊Redis與MySQL雙寫一致性如何保證

    一致性就是數(shù)據(jù)保持一致,在分布式系統(tǒng)中,可以理解為多個節(jié)點中數(shù)據(jù)的值是一致的。本文給大家分享Redis與MySQL雙寫一致性該如何保證,感興趣的朋友一起看看吧
    2021-06-06
  • Redis數(shù)據(jù)結(jié)構(gòu)之鏈表詳解

    Redis數(shù)據(jù)結(jié)構(gòu)之鏈表詳解

    大家好,本篇文章主要講的是Redis數(shù)據(jù)結(jié)構(gòu)之鏈表詳解,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • redis實現(xiàn)的四種常見限流策略

    redis實現(xiàn)的四種常見限流策略

    因為在網(wǎng)站運行期間可能會因為突然的訪問量導(dǎo)致業(yè)務(wù)異常、也有可能遭受別人惡意攻,所以我們對網(wǎng)站要進行限流,本文主要介紹了redis四種常見限流策略,感興趣的可以了解一下
    2021-06-06
  • Redis Cluster集群動態(tài)擴容的實現(xiàn)

    Redis Cluster集群動態(tài)擴容的實現(xiàn)

    本文主要介紹了Redis Cluster集群動態(tài)擴容的實現(xiàn),文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • Windows環(huán)境部署Redis集群

    Windows環(huán)境部署Redis集群

    這篇文章主要為大家詳細介紹了Windows環(huán)境部署Redis集群的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Redis存取序列化與反序列化性能問題詳解

    Redis存取序列化與反序列化性能問題詳解

    這篇文章主要給大家介紹了關(guān)于Redis存取序列化與反序列化性能問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Redis主從復(fù)制操作和配置詳情

    Redis主從復(fù)制操作和配置詳情

    這篇文章主要介紹了Redis主從復(fù)制操作和配置詳情,文章通過圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • 通過kubesphere部署redis的方法

    通過kubesphere部署redis的方法

    這篇文章主要介紹了通過kubesphere部署redis的方法,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11

最新評論