redis會發生死鎖問題嗎

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)?&amp;&amp;?Long.parseLong(currentValue)?<p>調用:<br></p><pre class="brush:php;toolbar:false">?//加鎖 ????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相關知識,請訪問Redis使用教程欄目!

? 版權聲明
THE END
喜歡就支持一下吧
點贊15 分享