Redis爲單進程單線程模式,採用隊列模式將併發訪問變爲串行訪問。Redis自己沒有鎖的概念,Redis對於多個客戶端鏈接並不存在競爭,可是在Jedis客戶端對Redis進行併發訪問時會發生鏈接超時、數據轉換錯誤、阻塞、客戶端關閉鏈接等問題,這些問題均是因爲客戶端鏈接混亂形成。對此有2種解決方法:html
1.客戶端角度,爲保證每一個客戶端間正常有序與Redis進行通訊,對鏈接進行池化,同時對客戶端讀寫Redis操做採用內部鎖synchronized。 redis
2.服務器角度,利用setnx實現鎖。服務器
注:對於第一種,須要應用程序本身處理資源的同步,可使用的方法比較通俗,可使用synchronized也可使用lock;第二種須要用到Redis的setnx命令,可是須要注意一些問題。併發
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通常不能設置爲過時時間