Redis分佈式鎖(併發競爭)

Redis的併發競爭問題如何解決?

Redis爲單進程單線程模式,採用隊列模式將併發訪問變爲串行訪問。Redis自己沒有鎖的概念,Redis對於多個客戶端鏈接並不存在競爭,可是在Jedis客戶端對Redis進行併發訪問時會發生鏈接超時、數據轉換錯誤、阻塞、客戶端關閉鏈接等問題,這些問題均是因爲客戶端鏈接混亂形成。對此有2種解決方法:html

 1.客戶端角度,爲保證每一個客戶端間正常有序與Redis進行通訊,對鏈接進行池化,同時對客戶端讀寫Redis操做採用內部鎖synchronized。  redis

    2.服務器角度,利用setnx實現鎖。服務器

 注:對於第一種,須要應用程序本身處理資源的同步,可使用的方法比較通俗,可使用synchronized也可使用lock;第二種須要用到Redis的setnx命令,可是須要注意一些問題。併發



關於redis鎖的可靠性:

1.互斥性。在任意時刻,只有一個客戶端能持有鎖。分佈式

2.不會發生死鎖。即便有一個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保證後續其餘客戶端能加鎖。post

3.具備容錯性。只要大部分的Redis節點正常運行,客戶端就能夠加鎖和解鎖。spa

4.解鈴還須繫鈴人。加鎖和解鎖必須是同一個客戶端,客戶端本身不能把別人加的鎖給解了。線程

setnx key value key不存在就設置code

public class RedisTool {
 
    private static final String LOCK_SUCCESS = "OK";
    private static final String SET_IF_NOT_EXIST = "NX";
    private static final String SET_WITH_EXPIRE_TIME = "PX";
 
    /**
     * 嘗試獲取分佈式鎖
     * @param jedis Redis客戶端
     * @param lockKey 鎖
     * @param requestId 請求標識
     * @param expireTime 超期時間
     * @return 是否獲取成功
     */
    public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
 
        String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
 
        if (LOCK_SUCCESS.equals(result)) {
            return true;
        }
        return false;
 
    }
 
}

http://www.javashuo.com/article/p-xmztjgny-kx.htmlhtm

主要就是要設置過時時間,防止崩潰了能夠本身解鎖

value要設置爲惟一標識,以方便同一個客戶端來解鎖,因此value通常不能設置爲過時時間

http://www.javashuo.com/article/p-ejxnzdni-ht.html

相關文章
相關標籤/搜索