大家應該都知道redis做分布式鎖無非就是incr命令或者是setnx命令,這裡我們採用setnx命令。
操作:setnx key 如果操作成功則代表拿到鎖,如果沒有操作成功則代表沒有拿到鎖。
缺點:如果這個人拿到鎖後宕機了怎麼辦,那麼這個鎖就再也不能釋放了。
改進:給這個鎖增加乙個過期時間,這樣如果有效期過了,那麼這個鎖就會自動釋放了。
通過上面所說我們應該對redis分布式進行改進。
操作: 使用setnx 命令,之後,在expireat key 30000 這條命令設定key的有效期為30秒。
這裡我們可能會發現,如果要是剛setnx結束之後,要是宕機了。怎麼辦?那麼我們為了保證原子性,所以jedis提供了乙個原子操作,set(key,value,nx,30,時間單位)這樣便解決了。
缺點:如果這個鎖的時間不夠用怎麼辦,那麼就會導致這個功能鎖不住。假設:a拿到鎖了,但是a還沒有執行結束,b又拿到鎖了,那麼a執行結束的時候是不是會把b的這個鎖給刪除掉。這樣就導致了鎖不住的效果。
改進:我們可以學習樂觀所,給鎖的value值是乙個唯一的編號,或者版本號,我們每次對鎖進行操作的時候,就會去驗證這個版本號,還是不是自己的版本號。如果不是了就不允許操作了。
通過上面的總結這第三版想必也很簡單了。知識多了乙個唯一值而已。但是加了唯一值還是改變不了鎖不住的結果,只是解決了幫其他的執行緒解鎖的問題,那麼要怎麼樣才能鎖得住呢?當時我想到的是給他 時間久一點,後來發現其實再久,也一樣會出現鎖不住的時候,而且太久了如果宕機了,就會有很長時間機器無法工作,很容易造成執行緒堆積。
由上面我們發現一般簡單實用redis做鎖其實是有很多漏洞和bug的,但是有沒有能夠解決這些的呢?當然是有的。
模仿aqs鎖, lock方法執行完之後,執行下面**是被鎖的,unlock執行完,釋放鎖。其他執行緒等待,而不是直接返回錯誤結果。
最終版還是打算先上**再說,為了方便我把所有的實現都寫在了乙個類裡面。
@autowired
private redistemplate redistemplate;
@autowired
private redisutils redisutils;
@autowired
(required =
false
)private threadpooltaskscheduler threadpooltaskscheduler;
public
final string lock_prefix =
"redis_lock"
;private
final long lock_expire =30*
1000l;
private
final long over_time =
10l;
private map
?>
> futuremap =
newconcurrenthashmap
<
>()
;private jedis jedis;
public
lock()
private reentrantlock reentrantlock;
/** * 給執行緒枷鎖
** @param key
*/public
void
lock
(string key)},
newtrigger()
});return;}
}}/** * setnx
** @param key
* @return
*/public
boolean
setlock
(string key)
else}}
return
false;}
});}
/** * 刪除鎖
** @param key
*/public
void
unlock
(string key)
}/**
* 判斷key是否存在
** @param key 鍵
* @return true 存在 false不存在
*/public
boolean
haskey
(string key)
catch
(exception e)
}public set
scan
(string key)
else
}return keys;})
;}
分析:
判斷是否獲取到鎖,獲取到鎖,繼續執行,沒有獲取到鎖,自旋繼續獲取。
獲取到鎖後排程乙個任務。每10秒執行一次,並且如果發現所沒有釋放延長10秒。
釋放鎖,刪除掉redis中的key,並結束掉對應的鎖的任務。
加鎖執行原理:
解鎖操作原理:
解鎖操作就比較簡單了。但是得為了不出必要的麻煩,最好是給停止鎖延時任務,和刪除所 這兩部新增程序鎖,可以使用synchronized,也可以使用aqs lock鎖。
這裡redis非公平鎖詳解算是結束了,後期可能會更新使用redis,實現公平鎖,謝謝大家的支援,如果有需要的小夥伴可以直接拿走,希望能給大家帶來幫助。
Redis分布式非公平鎖的使用
目錄 看了很多部落格,和資料,這裡只針對redis做分布式鎖做一下深入 希望對你們有obwmx幫助。網上提供了很多分布式鎖的操作,這裡逐一舉例然後評論優缺點及改進方案,希望這樣子能讓當家更好的理解redis分布式鎖。大家應該都知道redis做分布式鎖無非就是incr命令或者是setnx命令,這裡我們...
Redis分布式鎖詳解
在網際網路分布式服務部署中,通常會遇到多個程序操作同乙個資源的情況,例如秒殺等,此文章主要介紹使用redis實現分布式鎖。redis為單程序單執行緒模式,採用佇列模式將併發訪問變為序列訪問。通常使用setnx 即set not exiest 來實現鎖,以下通過循序漸進的方式引入最終實現。方案一1.c...
redis實現分布式鎖詳解
解決問題 應對高併發業務場景 為什麼可以實現?首先redis是單執行緒的,這裡的單執行緒指的是網路請求模組使用了乙個執行緒 所以不需考慮併發安全性 即乙個執行緒處理所有網路請求,其他模組仍用了多個執行緒。實現原理 伺服器一的請求會先獲取到鎖,接下來如果來相同的請求,此時會返回獲取鎖失敗的狀態。直至本...