亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

redis發生死鎖問題怎么辦

發布時間:2020-11-13 14:32:09 來源:億速云 閱讀:441 作者:小新 欄目:關系型數據庫

這篇文章主要介紹了redis發生死鎖問題怎么辦,具有一定借鑒價值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。

就分布式鎖而言,一個常用的問題就是如果一個服務setnx成功了,但是在解鎖的時候如果發生了宕機或者一些特殊因素,導致無法解鎖,那么其他服務將陷入死鎖的狀態。所以,我們在用 setnx 的同時想著去用 expire 指令對鎖進行一個過期操作, 從指令可以看出 setnx 和expire指令是分開的,如果在這中間的空隙過程中如果有特殊因素導致指令無法繼續,也會導致死鎖的產生。

解決方法:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
 
@Component
public class RedisLock {
 
    Logger logger = LoggerFactory.getLogger(this.getClass());
 
    @Autowired
    private StringRedisTemplate redisTemplate;
 
    /**
     * 加鎖
     * @param key   
     * @param value 當前時間 + 超時時間
     * @return
     */
    public boolean lock(String key, String value) {
    
        if (redisTemplate.opsForValue().setIfAbsent(key, value)) {     
            // 這個其實就是setnx命令,只不過在java這邊稍有變化,返回的是boolean
            // 設置個過期時間,當然如果在這中間的空隙過程中如果有特殊因素導致指令無法繼續,也會導致死鎖的產生,如果死鎖出現,則后續代碼會處理
            redisTemplate.expire(key, lockTime, TimeUnit.SECONDS);
            return true;
        }
 
        // 避免死鎖,且只讓一個線程拿到鎖
        String currentValue = redisTemplate.opsForValue().get(key);
        // 如果鎖過期了
        if (!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()) {
            //獲取上一個鎖的時間
            String oldValues = redisTemplate.opsForValue().getAndSet(key, value);
 
            /*
               只會讓一個線程拿到鎖
               如果舊的value和currentValue相等,只會有一個線程達成條件,因為第二個線程拿到的oldValue已經和currentValue不一樣了
             */
            if (!StringUtils.isEmpty(oldValues) && oldValues.equals(currentValue)) {
                return true;
            }
        }
        return false;
    }
 
 
    /**
     * 解鎖
     * @param key
     * @param value
     */
    public void unlock(String key, String value) {
        try {
            String currentValue = redisTemplate.opsForValue().get(key);
            if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {
                redisTemplate.opsForValue().getOperations().delete(key);
            }
        } catch (Exception e) {
            logger.error("redis分布式鎖解鎖異常,{}", e);
        }
    }
}

調用:

 //加鎖
    long time = System.currentTimeMillis() + 1000 * lockTime //超時時間:10秒,最好設為常量
 
    boolean isLock = redisLock.lock(...keyName, String.valueOf(time));
    if(!isLock){
        throw new RuntimeException("系統正忙");
    }
    
    // doSomething...
    
    
    //解鎖
    redisLock.unlock(...keyName, String.valueOf(time));

感謝你能夠認真閱讀完這篇文章,希望小編分享redis發生死鎖問題怎么辦內容對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,遇到問題就找億速云,詳細的解決方法等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

西乌| 西乡县| 铜鼓县| 玛多县| 淳化县| 洛浦县| 通城县| 泰顺县| 图们市| 怀远县| 朝阳县| 化隆| 新密市| 额尔古纳市| 鄂州市| 铜梁县| 城市| 吉水县| 六盘水市| 九龙坡区| 依安县| 华容县| 金坛市| 红安县| 宜川县| 府谷县| 曲麻莱县| 都昌县| 米易县| 静宁县| 雷山县| 巴青县| 台湾省| 科技| 天峻县| 永年县| 西城区| 保山市| 穆棱市| 镇原县| 南昌市|