分布式應用進行邏輯處理時經常會遇到併發問題。對於單程序的併發場景,我們可以使用語言或者類庫提供的鎖,而對於分布式場景,我們可以使用分布式鎖。
分布式鎖的實現方法也有很多,memcached分布式鎖、zookeeper分布式鎖等等,當然,redis分布式鎖也是很有代表性的分布式鎖的實現方式。
例子:某個操作需要修改使用者的狀態,首先需要讀取出使用者的狀態,在記憶體中進行修改後再把它存回去。這樣的操作如果同時進行了,就會出現併發問題,因為讀取和儲存狀態這兩個操作不是原子的。
ps:原子操作指不會被執行緒排程機制打斷的操作;這種操作一旦開始,就一直執行到結束,中間不會有任何的context switch 執行緒切換。
這個時候就要使用到分布式鎖來限制程式的併發執行,redis分布式鎖使用非常廣泛。
分布式鎖本質上要實現的目標就是在redis裡面佔乙個座位,當別的程序也要來坐這個位置時,發現座位已經被佔了,就只能等待或稍後再檢視。
佔座位(也就是加鎖)一般用setnx(set if not exists)指令,並且只允許被乙個客戶端占領,先來先占領,用完了,再使用del指令釋放。
//但是如果我們加鎖後,乙個得到鎖的程序在執行過程中掛掉或者是我們忘記了釋放鎖,那麼這塊資源會被永久地鎖住,造成死鎖,鎖永遠得不到釋放。這裡的冒號:就是乙個普通的字元,沒特別含義,它可以是任意其它字元,不要誤解
> setnx lock:codehole true
ok...
dosomething critical ...
>del lock:codehole
(integer) 1...
於是我們在拿到鎖之後,可以給鎖expire命令 再增加乙個過期時間,比如說5s,那麼及時中途出現異常亦可以保證5s後鎖會自動釋放。
> setnx lock:codehole true但是這樣也還是有可能出現問題的。原因就在於setnx和expire這兩條指令是非原子性的指令。ok> expire lock:codehole 5...
dosomething critical ...
>del lock:codehole
(integer) 1
我們可以設想以下的場景:
節點1中線程a執行了 setnx 指令,獲得了鎖但是還沒有執行 expire 指令,這個時候突然節點1的機器宕機了。
這樣一來,這把鎖就沒有了過期時間,變得永不過期,依舊會出現死鎖。
為了解決這個問題,redis在2.6.12以上的版本中增加了set指令以及其可選引數,取代了setnx指令,使得setnx和expire指令可以一起執行。
> set lock:codehole true ex 5nxredis的分布式鎖不能解決超時問題,如果在加鎖和釋放鎖之間的邏輯執行的太長,超出了鎖的超時限制,就會出現問題。ok...
dosomething critical ...
> del lock:codehole
因為這個時候鎖過期了,第二個執行緒重新持有了這把鎖,但是緊接著第乙個執行緒執行完之後,會將這個鎖給釋放掉。
這會導致乙個後果:第三個執行緒會在第二個執行緒的執行過程之間拿到鎖。
為了避免這個問題,redis 分布式鎖不要用於較長時間的任務。
如果真的偶爾出現了,資料出現的小波錯亂可能需要人工介入解決。
我們可以讓獲得鎖的執行緒開啟乙個守護執行緒,用來給快要過期的鎖續航。
過去了29s,執行緒a還沒有執行完畢,這個時候守護執行緒會執行 expire 指令。為這把鎖續命20s,守護執行緒在29s後,每20s執行一次。
執行緒a執行完之後,則關閉守護執行緒。
OssImport系列之三 分布式部署
分布式部署目前只支援linux,windows暫不支援。ossimport bin console.jar console模組jar包 master.jar master模組jar包 tracker.jar tracker模組jar包 worker.jar worker模組jar包 conf job...
Redis(五)分布式鎖
1.分布式鎖是什麼 分布式鎖是控制分布式系統或不同系統之間共同訪問共享資源的一種鎖實現,如果不同的系統或同一系統的不同主機之間共享了某個資源時,往往通過互斥來防止彼此干擾。2.分布式設計目的 可以保證在分布式部署的應用集群中,同乙個方法在同一操作只能被一台機器上的乙個執行緒執行。3.設計要求 1 這...
分布式計算(三)分布式的昨天
當今的我們已經處於計算機比較發達的時代,計算機的很多技術已經發展很久,很多我們現在使用的都是在一定基礎結構之上的研究,就好像我們學會了hadoop,webservices.學會了大資料計算,就是掌握了分布式技術嗎?感覺心慌 疑惑。這些疑惑不知道從什麼時候開始的,所以要想弄清是怎麼回事,還是回到遙遠的...