當前位置:編程學習大全網 - 編程語言 - 大家推崇的Redis分布式鎖真的萬無壹失嗎?

大家推崇的Redis分布式鎖真的萬無壹失嗎?

使用Redis實現分布式鎖的最簡單的解決方案是使用命令SETNX。SETNX(SET if Not eXist)用作:SETNX key value,key key的值僅在key key不存在時設置為value。如果key key存在,那麽set NX什麽也不做。SETNX在設置成功時返回,設置失敗時返回0。當妳想獲取鎖的時候,用SETNX直接獲取鎖,當妳想釋放鎖的時候,用DEL命令刪除對應的鍵。

上述方案有壹個致命的問題,就是壹個線程在獲取鎖後,由於壹些異常因素(比如宕機)無法正常執行解鎖操作,所以鎖永遠不會被釋放。為此,我們可以給這個鎖添加壹個超時。第壹時間我們會想到Redis的EXPIRE key seconds。但是這裏我們不能用EXPIRE來實現分布式鎖,因為它和SETNX是兩個壹起操作,這兩個操作之間可能會發生異常,仍然達不到預期的結果。

對此,正確的姿勢應該是使用“設置鍵值[ex秒] [px百萬] [NX | xx]”命令。

從Redis 2 . 6 . 12版本開始,SET命令的行為可以通過壹系列參數進行修改:EX seconds:將密鑰的到期時間設置為秒。執行SET key value EX seconds的效果等同於執行SETEX key seconds value。PX毫秒:將密鑰的過期時間設置為毫秒。執行set key value px mills的效果等同於執行psetex key mills value。NX:僅在密鑰不存在時設置密鑰。執行SET key value NX與執行SETNX key value效果相同。XX:僅當密鑰已經存在時才設置密鑰。

執行設置鍵值PX?毫秒的後果相當於完成PSETEX鍵的毫秒值。NX:只有當關鍵點不存在時,才停止設置和操縱關鍵點。執行SET key value NX的後果等同於執行SETNX key value。XX:僅當密鑰曾經存在時,才停止設置和操作密鑰。例如,如果我們需要創建壹個分布式鎖,並將過期時間設置為10s,那麽我們可以完成以下訂單:

這裏我們壹眼就能看出問題:GET和DEL是兩個獨立的操作,在GET執行和DEL執行的間隙可能會出現異常。如果我們只保證解鎖的代碼是原子的,就可以解決問題。這裏我們介紹壹種新的方式,即Lua腳本。解鎖的時候,我們還是用DEL命令解鎖。

修改後的方案看起來很完美,但實際上還是會有問題。假設壹個線程A獲取了壹個鎖,並將到期時間設置為10s,然後執行業務邏輯需要15s。此時,線程A獲得的鎖已經被Redis的到期機制自動釋放。在線程A獲得鎖並通過10之後,鎖的更改可能已經被其他線程獲得。當線程A執行業務邏輯並準備解鎖(DEL鍵)時,就有可能刪除其他線程已經獲得的鎖。壹般來說,Redis分布式鎖不是那麽萬無壹失的。

  • 上一篇:信息技術教師個人工作總結5篇
  • 下一篇:如何用VB發電子郵件,請各位高手指教!
  • copyright 2024編程學習大全網