在分布式應用中經常出現併發的問題,比如對使用者的狀態做乙個修改 ,那麼就涉及到先取出資料再進行修改,但是這樣常常會引發問題,因為讀和寫是兩個操作,不是原子性(不可分割的)的操作。當同時進行該操作時往往會引發併發問題。
這時就要用到分布式鎖。
在reids中的分布式鎖實際上就相當於乙個佔坑,當坑上有人的時候別人必須再外面等待,同時只允許乙個人佔坑。而在redis中提供了乙個setnx的指令來對key進行加鎖:
setnx mylock true
...do something... //做一些業務邏輯
del mylock //釋放鎖
好像這樣就完事大吉了。不,這有問題。如果我在做一些業務邏輯的時候出了問題執行不到del指令釋放鎖的時候豈不是進入了死迴圈,鎖得不到釋放,別人得不到鎖。
這就尷尬了,但是我們不是有乙個設定過期時間的指令嗎?對啊 就是expire指令:
setnx mylock true
expire mylock 5 //設定過期時間為5s
...do something... //做一些業務邏輯
del mylock //釋放鎖
這樣不就解決了嗎?別高興的太早了,萬一我在setnx和expire之間出了問題呢,那還是一樣的啊,問題依舊,依然出現了死鎖。那我們可不可以用事務來解決呢?答案是不行的,因為事務是要不都執行要不都不執行,而我們需要的是if/else的操作,expire指令是依賴於setnx指令的結果的,如果setnx沒有搶到鎖,那麼expire是不用執行的。
現在我們來分析一下為什麼會出現這樣的問題,其實就是因為setnx和expire是兩個操作不是原子性的,所以這樣是會出現問題的。那麼我們可不可以把這兩個指令合併一下呢?答案是可以的。redis為我們提供了set指令:
set mylock true ex 5 nx //setnx和expire的結合
...do something... //做一些業務邏輯
del mylock //釋放鎖
這個set指令就是分布式鎖的奧義所在。
但是上面的操作還是存在問題的,因為設定了過期時間。萬一我的業務邏輯執行時長超過過期時間的化,那麼我就釋放掉了鎖,我都沒執行完呢就沒了,難受啊。這就是超時問題。所以分布式鎖還是不要用來去執行時間比較長的任務。
redis分布式鎖
redis分布式鎖 直接上 我寫了四個redis分布式鎖的方法,大家可以提個意見 第一種方法 redis分布式鎖 param timeout public void lock long timeout thread.sleep 100 catch exception e override publi...
Redis分布式鎖
分布式鎖一般有三種實現方式 1.資料庫樂觀鎖 2.基於redis的分布式鎖 3.基於zookeeper的分布式鎖.首先,為了確保分布式鎖可用,我們至少要確保鎖的實現同時滿足以下四個條件 互斥性。在任意時刻,只有乙個客戶端能持有鎖。不會發生死鎖。即使有乙個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保...
redis分布式鎖
使用redis的setnx命令實現分布式鎖 redis為單程序單執行緒模式,採用佇列模式將併發訪問變成序列訪問,且多個客戶端對redis的連線並不存在競爭關係。redis的setnx命令可以方便的實現分布式鎖。setnx key value 將key的值設為value,當且僅當key不存在。如給定的...