欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Redis分布式鎖一定要避開(kāi)的兩個(gè)坑

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

1 第一個(gè)坑:錯(cuò)誤釋放鎖時(shí)機(jī)

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

分析以下代碼存在什么問(wè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ù)校驗(yàn)
                if(!bizValidate(bizId)) {
                    throw new BizException(ErrorBizCode.REPEATED);
                }
                // 執(zhí)行業(yè)務(wù)
                return doBusiness();
            }
            // 獲取鎖失敗
            throw new BizException(ErrorBizCode.GET_LOCK_ERROR);
        } finally {
            // 釋放鎖
            redisLockService.releaseLock(bizId);
        }
    }
}

上述代碼看似沒(méi)問(wèn)題,實(shí)則隱藏大問(wèn)題。問(wèn)題在于釋放鎖時(shí)沒(méi)有校驗(yàn)當(dāng)前線(xiàn)程是否拿到鎖:

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

1.2 解決問(wèn)題

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

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ù)校驗(yàn)
                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 第二個(gè)坑:緩存失效問(wèn)題

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

2.1 過(guò)期清理機(jī)制

(1) 定期刪除

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

(2) 惰性刪除

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

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

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

當(dāng)內(nèi)存不足時(shí)Redis會(huì)選擇一些元素進(jìn)行刪除:

no-enviction

禁止驅(qū)逐數(shù)據(jù),新寫(xiě)入操作會(huì)報(bào)錯(cuò)

volatile-lru

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

volatile-ttl

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

volatile-random

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

allkeys-lru

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

allkeys-random

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

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

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

2.3 樂(lè)觀(guān)鎖

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

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

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

相關(guān)文章

  • Redis之Redisson原理詳解

    Redis之Redisson原理詳解

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

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

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

    聊一聊Redis與MySQL雙寫(xiě)一致性如何保證

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

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

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

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

    因?yàn)樵诰W(wǎng)站運(yùn)行期間可能會(huì)因?yàn)橥蝗坏脑L(fǎng)問(wèn)量導(dǎo)致業(yè)務(wù)異常、也有可能遭受別人惡意攻,所以我們對(duì)網(wǎng)站要進(jìn)行限流,本文主要介紹了redis四種常見(jiàn)限流策略,感興趣的可以了解一下
    2021-06-06
  • Redis Cluster集群動(dòng)態(tài)擴(kuò)容的實(shí)現(xiàn)

    Redis Cluster集群動(dòng)態(tài)擴(kuò)容的實(shí)現(xiàn)

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

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

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

    Redis存取序列化與反序列化性能問(wèn)題詳解

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

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

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

    通過(guò)kubesphere部署redis的方法

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

最新評(píng)論