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

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

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

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

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ù)校驗(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);
        }
    }
}

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

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

1.2 解決問題

解決方案是在確認(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è)坑:緩存失效問題

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

2.1 過期清理機(jī)制

(1) 定期刪除

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

(2) 惰性刪除

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

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

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

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

no-enviction

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

volatile-lru

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

volatile-ttl

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

volatile-random

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

allkeys-lru

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

allkeys-random

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

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

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

2.3 樂觀鎖

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

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

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

相關(guān)文章

  • 深入解析Redis的LRU與LFU算法實(shí)現(xiàn)

    深入解析Redis的LRU與LFU算法實(shí)現(xiàn)

    這篇文章主要重點(diǎn)介紹了Redis的LRU與LFU算法實(shí)現(xiàn),并分析總結(jié)了兩種算法的實(shí)現(xiàn)效果以及存在的問題,并闡述其優(yōu)劣特性,感興趣的小伙伴跟著小編一起來看看吧
    2023-07-07
  • Redis集群水平擴(kuò)展、集群中添加以及刪除節(jié)點(diǎn)的操作

    Redis集群水平擴(kuò)展、集群中添加以及刪除節(jié)點(diǎn)的操作

    這篇文章主要介紹了Redis集群水平擴(kuò)展、集群中添加以及刪除節(jié)點(diǎn)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • redis做websocket分布式消息推送服務(wù)的實(shí)現(xiàn)

    redis做websocket分布式消息推送服務(wù)的實(shí)現(xiàn)

    本文介紹了使用Redis作為消息隊(duì)列實(shí)現(xiàn)WebSocket分布式消息推送服務(wù)的方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-12-12
  • Redis 2.8-4.0過期鍵優(yōu)化過程全紀(jì)錄

    Redis 2.8-4.0過期鍵優(yōu)化過程全紀(jì)錄

    這篇文章主要給大家介紹了關(guān)于Redis 2.8-4.0過期鍵優(yōu)化的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Redis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Redis實(shí)現(xiàn)主從復(fù)制方式(Master&Slave)

    Redis實(shí)現(xiàn)主從復(fù)制方式(Master&Slave)

    這篇文章主要介紹了Redis實(shí)現(xiàn)主從復(fù)制方式(Master&Slave),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 解決Redis分布式鎖的誤刪問題和原子性問題

    解決Redis分布式鎖的誤刪問題和原子性問題

    Redis的分布式鎖是通過利用Redis的原子操作和特性來實(shí)現(xiàn)的,為了保證數(shù)據(jù)的一致性和避免沖突,可以使用分布式鎖來進(jìn)行同步控制,本文給大家介紹了如何解決Redis分布式鎖的誤刪問題和原子性問題,需要的朋友可以參考下
    2024-02-02
  • Redis總結(jié)筆記(一):安裝和常用命令

    Redis總結(jié)筆記(一):安裝和常用命令

    這篇文章主要介紹了Redis總結(jié)筆記(一):安裝和常用命令,本文著重總結(jié)了常用命令,如對(duì)value操作的命令、對(duì)String操作的命令、對(duì)List操作的命令、對(duì)Set操作的命令等,需要的朋友可以參考下
    2015-01-01
  • Redis使用ZSET實(shí)現(xiàn)消息隊(duì)列的項(xiàng)目實(shí)踐

    Redis使用ZSET實(shí)現(xiàn)消息隊(duì)列的項(xiàng)目實(shí)踐

    本文主要介紹了Redis使用ZSET實(shí)現(xiàn)消息隊(duì)列的項(xiàng)目實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Redis的數(shù)據(jù)存儲(chǔ)及String類型的實(shí)現(xiàn)

    Redis的數(shù)據(jù)存儲(chǔ)及String類型的實(shí)現(xiàn)

    這篇文章主要介紹了Redis的數(shù)據(jù)存儲(chǔ)及String類型的實(shí)現(xiàn),redis作為k-v數(shù)據(jù)存儲(chǔ),因查找和操作的時(shí)間復(fù)雜度都是O(1)和豐富的數(shù)據(jù)類型及數(shù)據(jù)結(jié)構(gòu)的優(yōu)化,了解了這些數(shù)據(jù)類型和結(jié)構(gòu)更有利于我們平時(shí)對(duì)于redis的使用,需要的朋友可以參考下
    2022-10-10
  • Redis實(shí)現(xiàn)分布式隊(duì)列淺析

    Redis實(shí)現(xiàn)分布式隊(duì)列淺析

    Redis將數(shù)據(jù)存儲(chǔ)在內(nèi)存中,使得讀寫速度非???,經(jīng)常被用來做緩存系統(tǒng),這里我們將redis用來做一個(gè)分布式的消息隊(duì)列。這篇文章主要介紹了使用redis來作為消息隊(duì)列,并且進(jìn)行分布式主從配置,有需要的朋友可以參考借鑒,下面來一起看看吧。
    2016-11-11

最新評(píng)論

建瓯市| 读书| 娄底市| 阳原县| 竹山县| 共和县| 柘荣县| 阳朔县| 江达县| 包头市| 望城县| 池州市| 广德县| 合肥市| 洛宁县| 平湖市| 上饶县| 黑水县| 横山县| 吉木萨尔县| 肥乡县| 盱眙县| 来安县| 侯马市| 财经| 龙胜| 南溪县| 汉寿县| 连云港市| 皮山县| 中山市| 东丰县| 乌拉特后旗| 高要市| 临汾市| 沁阳市| 曲水县| 荆门市| 绥江县| 延庆县| 蓬莱市|