一種redis命令搞定基於redis的分散式鎖
基於redis的分散式鎖專案肯定經常用到,主要是為了避免重複處理,或者由於併發帶來的髒資料或者錯誤的處理。
使用鎖就必須注意一下幾點:
1、互斥,同一時間不能有多個client能獲取到鎖
2、不能發生死鎖,不能因為有鎖的client因為崩潰或者解鎖命令請求失敗導致無法釋放鎖
3、自己只能解自己上的鎖,不能刪除別人的鎖
下面介紹一下程式碼為什麼這麼寫
1、為什麼不用setnx和expire兩個命令來實現加鎖,因為如果再執行setnx後加過期時間崩潰了,就無法解鎖。
2、為什麼需要使用隨機字串來做lockvalue,主要是為了防止不同client的鎖都是一樣的,防止client誤刪
3、為什麼還需要Lua指令碼程式碼來實現刪除鎖,縱然我們在刪除之前比對了鎖,但是get和del之間不是原子性的,所以也防止刪除別人的鎖,用lua指令碼程式碼實現原子操作
下面是一個不侵佔業務的通過redis分散式鎖來執行的方法程式碼,當然這裡只是參考,一種解決問題的方案,至於業務實現怎麼寫,大家可以隨便發揮。
/**
* 分散式鎖
*
* @param r 繼承於Redis
* @param lockKey 分散式鎖的key
* @param voidMethod 獲得到鎖後需要執行的方法
* @param expireSeconds 鎖定時間 單位/s(需要評估方法執行時間)
* @param retrySeconds 重試間隔 單位/s
* @throws ServiceException
*/
public <R extends Redis> void lock(R r, String lockKey, VoidMethodInterface voidMethod, int expireSeconds, int retrySeconds) throws ServiceException {
long begin = 0L;
long retryMills = retrySeconds * 1000;
//獲取隨機字串,避免lockValue相同
String lockValue = UUID.randomUUID().toString();
while (begin <= retryMills) {
String response = r.set(lockKey, lockValue, "nx", "ex", expireSeconds);
if (response != null) {
logger.debug("lock method exec begin");
try {
voidMethod.exec();
} catch (Exception e) {
logger.error("method exec failed ,msg:%s", e.getMessage());
} finally {
String value = r.get(lockKey);
//當快取裡還有該key對應的值時,才去刪除鎖,避免執行時間過長導致鎖被釋放
if (!StringUtils.isEmpty(value) && lockValue.equals(value)) {
// 避免若在此時,這把鎖突然不是這個客戶端的,則會誤解鎖
String script = "if redis.call(`get`, KEYS[1]) == ARGV[1] then return redis.call(`del`, KEYS[1]) else return 0 end";
r.eval(script, Collections.singletonList(lockKey), Collections.singletonList(lockValue));
}
}
logger.debug("lock method exec success");
return;
} else {
long waitMills = random.nextInt(WAIT_INTERVAL_MIN_MILLS, WAIT_INTERVAL_MAX_MILLS);
try {
Thread.sleep(waitMills);
} catch (InterruptedException ex) {
throw new UnexpectedStateException(ex);
}
begin = begin + waitMills;
logger.debug("等待獲取鎖,當前等待時間:%sms", begin);
}
}
logger.error("等待獲取鎖超時");
}
相關文章
- 基於 Redis 分散式鎖Redis分散式
- 基於 Redis 的分散式鎖Redis分散式
- 基於redis的分散式鎖Redis分散式
- 基於redis做分散式鎖Redis分散式
- 基於Redis實現一個分散式鎖Redis分散式
- [翻譯]基於redis的分散式鎖Redis分散式
- 基於redis的分散式鎖實現Redis分散式
- 基於redis實現分散式鎖Redis分散式
- 基於 Redis 的分散式鎖到底安全嗎?Redis分散式
- Redis 分散式鎖(一)Redis分散式
- 分散式鎖與實現(一)基於Redis實現!分散式Redis
- 基於 Redis 實現簡單的分散式鎖Redis分散式
- 基於redis分散式鎖實現“秒殺”Redis分散式
- 基於Redis的分散式鎖的簡單實現Redis分散式
- 教你一招:基於Redis實現一個分散式鎖Redis分散式
- 基於Redis分散式鎖的正確開啟方式Redis分散式
- [轉載]基於Redis的分散式鎖到底安全嗎?Redis分散式
- java 實現開箱即用基於 redis 的分散式鎖JavaRedis分散式
- 基於redis和zookeeper的分散式鎖實現方式Redis分散式
- 分散式鎖-Redis分散式Redis
- redis 分散式鎖Redis分散式
- Redis分散式鎖Redis分散式
- 手把手教你實現一個基於Redis的分散式鎖Redis分散式
- 關於分散式鎖原理的一些學習與思考-redis分散式鎖,zookeeper分散式鎖分散式Redis
- 分散式鎖實現(一):Redis分散式Redis
- 詳解 Redis 分散式鎖的 5 種方案Redis分散式
- Redis實現分散式鎖的幾種方案Redis分散式
- 十九、Redis分散式鎖、Zookeeper分散式鎖Redis分散式
- Golang 基於單節點 Redis 實現的分散式鎖GolangRedis分散式
- Redis分散式鎖解析Redis分散式
- redis系列:分散式鎖Redis分散式
- 【Redis】利用 Redis 實現分散式鎖Redis分散式
- 從零到一帶你手寫基於Redis的分散式鎖框架Redis分散式框架
- 實現一個redis的分散式鎖Redis分散式
- 實現一個 Redis 分散式鎖Redis分散式
- redis分散式鎖-可重入鎖Redis分散式
- Redis分散式鎖加鎖案例Redis分散式
- 基於AOP和Redis實現的簡易版分散式鎖Redis分散式