redis分布式鎖

原理

redis為單進(jìn)程單線程模式,采用隊(duì)列模式j(luò)將并發(fā)訪問變成串行訪問,多客戶端對(duì)redis的連接不存在競(jìng)爭(zhēng)關(guān)系,setnx命令來實(shí)現(xiàn)

命令

SETNX

將key
設(shè)置值為value
,如果key
不存在,這種情況下等同[SET](http://www.redis.cn/commands/set.html)命令。 當(dāng)key
存在時(shí),什么也不做。SETNX
是”SET if Not eXists”的簡(jiǎn)寫。
GETSET

自動(dòng)將key對(duì)應(yīng)到value并且返回原來key對(duì)應(yīng)的value。如果key存在但是對(duì)應(yīng)的value不是字符串,就返回錯(cuò)誤。

demo

public class RedisLock {
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     *
     * @param key
     * @param value 當(dāng)前時(shí)間+超時(shí)時(shí)間
     * @return
     */
    public boolean lock(String key,String value){
        if(redisTemplate.opsForValue().setIfAbsent(key,value)){
            return true;
        }

        String currentValue = redisTemplate.opsForValue().get(key);
        //如果鎖過期
        if(!StringUtils.isEmpty(currentValue)
                && Long.parseLong(currentValue) < System.currentTimeMillis()){
            String oldValue = redisTemplate.opsForValue().getAndSet(key,value);
            if(!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)){
                return true;
            }

        }
        return false;
    }

    public void unlock(String key,String value){
        try {
            String currentValue = redisTemplate.opsForValue().get(key);
            if (!StringUtils.isEmpty(currentValue) && value.equals(currentValue)) {
                redisTemplate.opsForValue().getOperations().delete(key);
            }
        }catch (Exception e){
            log.error("【redis分布式鎖】解鎖異常,{}",e);
        }
    }

}

1.解決死鎖的問題

當(dāng)程序中獲取鎖后,后面過程中出現(xiàn)異??赡軙?huì)導(dǎo)致所不能釋放,所以加入下面判斷來解決

 String currentValue = redisTemplate.opsForValue().get(key);
        //如果鎖過期
        if(!StringUtils.isEmpty(currentValue)
                && Long.parseLong(currentValue) < System.currentTimeMillis()){
            String oldValue = redisTemplate.opsForValue().getAndSet(key,value);
            if(!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)){
                return true;
            }

        }

2.確保只有一個(gè)線程獲得鎖

如下判斷來確保,所超時(shí)時(shí),當(dāng)有A,B兩個(gè)線程剛進(jìn)來,只有一個(gè)獲得鎖

if(!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)){
                return true;
            }

釋放鎖,就是刪除key

public void unlock(String key,String value){
        try {
            String currentValue = redisTemplate.opsForValue().get(key);
            if (!StringUtils.isEmpty(currentValue) && value.equals(currentValue)) {
                redisTemplate.opsForValue().getOperations().delete(key);
            }
        }catch (Exception e){
            log.error("【redis分布式鎖】解鎖異常,{}",e);
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 分布式鎖的解決方式 基于數(shù)據(jù)庫(kù)表做樂觀鎖,用于分布式鎖。(適用于小并發(fā)) 使用memcached的add()方法,...
    xiaolyuh閱讀 15,838評(píng)論 6 17
  • SETNX命令簡(jiǎn)介 命令格式 SETNX key value 將 key 的值設(shè)為 value,當(dāng)且僅當(dāng) key ...
    tangstream閱讀 2,018評(píng)論 0 2
  • 在互聯(lián)網(wǎng)分布式服務(wù)部署中,通常會(huì)遇到多個(gè)進(jìn)程操作同一個(gè)資源的情況,例如秒殺等,此文章主要介紹使用Redis實(shí)現(xiàn)分布...
    Superwind20閱讀 674評(píng)論 0 0
  • Java多線程開發(fā)中鎖提供了原子性、可見性。但是在分布式系統(tǒng)中,一個(gè)進(jìn)程下的多個(gè)線程分布到一個(gè)集群中的多臺(tái)機(jī)器上,...
    yingzong閱讀 1,800評(píng)論 1 5
  • 最近在項(xiàng)目中遇到了類似“秒殺”的業(yè)務(wù)場(chǎng)景,在本篇博客中,我將用一個(gè)非常簡(jiǎn)單的demo,闡述實(shí)現(xiàn)所謂“秒殺”的基本思...
    lsfire閱讀 5,761評(píng)論 6 53

友情鏈接更多精彩內(nèi)容