有關Redisson做爲實現分佈式鎖,總的分3大模塊來說。java
一、Redisson實現分佈式鎖原理 二、Redisson實現分佈式鎖的源碼解析 三、Redisson實現分佈式鎖的項目代碼(能夠用於實際項目中)
本文只介紹Redisson如何實現分佈式鎖的原理。其它的會在接下來的博客講,最後有關Redisson實現分佈式鎖的項目代碼
的博客中會放上項目源碼到GitHub上。redis
當咱們在設計分佈式鎖的時候,咱們應該考慮分佈式鎖至少要知足的一些條件,同時考慮如何高效的設計分佈式鎖,這裏我認爲如下幾點是必需要考慮的。數據庫
在分佈式高併發的條件下,咱們最須要保證,同一時刻只能有一個線程得到鎖,這是最基本的一點。服務器
在分佈式高併發的條件下,好比有個線程得到鎖的同時,尚未來得及去釋放鎖,就由於系統故障或者其它緣由使它沒法執行釋放鎖的命令,致使其它線程都沒法得到鎖,形成死鎖。併發
因此分佈式很是有必要設置鎖的有效時間
,確保系統出現故障後,在必定時間內可以主動去釋放鎖,避免形成死鎖的狀況。異步
對於訪問量大的共享資源,須要考慮減小鎖等待的時間,避免致使大量線程阻塞。分佈式
因此在鎖的設計時,須要考慮兩點。高併發
一、鎖的顆粒度要儘可能小
。好比你要經過鎖來減庫存,那這個鎖的名稱你能夠設置成是商品的ID,而不是任取名稱。這樣這個鎖只對當前商品有效,鎖的顆粒度小。性能
二、鎖的範圍儘可能要小
。好比只要鎖2行代碼就能夠解決問題的,那就不要去鎖10行代碼了。ui
咱們知道ReentrantLock是可重入鎖,那它的特色就是:同一個線程能夠重複拿到同一個資源的鎖。重入鎖很是有利於資源的高效利用。關於這點以後會作演示。
針對以上Redisson都能很好的知足,下面就來分析下它。
爲了更好的理解分佈式鎖的原理,我這邊本身畫張圖經過這張圖來分析。
線程去獲取鎖,獲取成功: 執行lua腳本,保存數據到redis數據庫。
線程去獲取鎖,獲取失敗: 一直經過while循環嘗試獲取鎖,獲取成功後,執行lua腳本,保存數據到redis數據庫。
這個比較難理解,找了些許資料感受也並無解釋的很清楚。這裏我本身的理解就是:
在一個分佈式環境下,假如一個線程得到鎖後,忽然服務器宕機了,那麼這個時候在必定時間後這個鎖會自動釋放,你也能夠設置鎖的有效時間(不設置默認30秒),這樣的目的主要是防止死鎖的發生。
但在實際開發中會有下面一種狀況:
//設置鎖1秒過去 redissonLock.lock("redisson", 1); /** * 業務邏輯須要諮詢2秒 */ redissonLock.release("redisson"); /** * 線程1 進來得到鎖後,線程一切正常並無宕機,但它的業務邏輯須要執行2秒,這就會有個問題,在 線程1 執行1秒後,這個鎖就自動過時了, * 那麼這個時候 線程2 進來了。那麼就存在 線程1和線程2 同時在這段業務邏輯裏執行代碼,這固然是不合理的。 * 並且若是是這種狀況,那麼在解鎖時系統會拋異常,由於解鎖和加鎖已經不是同一線程了,具體後面代碼演示。 */
因此這個時候看門狗
就出現了,它的做用就是 線程1 業務尚未執行完,時間就過了,線程1 還想持有鎖的話,就會啓動一個watch dog後臺線程,不斷的延長鎖key的生存時間。
注意
正常這個看門狗線程是不啓動的,還有就是這個看門狗啓動後對總體性能也會有必定影響,因此不建議開啓看門狗。
這個不用多說,主要是若是你的業務邏輯複雜的話,經過封裝在lua腳本中發送給redis,並且redis是單線程的,這樣就保證這段複雜業務邏輯執行的原子性。
Redisson能夠實現可重入加鎖機制的緣由,我以爲跟兩點有關:
一、Redis存儲鎖的數據類型是 Hash類型 二、Hash數據類型的key值包含了當前線程信息。
下面是redis存儲的數據
這裏表面數據類型是Hash類型,Hash類型至關於咱們java的 <key,<key1,value>>
類型,這裏key是指 'redisson'
它的有效期還有9秒,咱們再來看裏們的key1值爲078e44a3-5f95-4e24-b6aa-80684655a15a:45
它的組成是:
guid + 當前線程的ID。後面的value是就和可重入加鎖有關。
舉圖說明
上面這圖的意思就是可重入鎖的機制,它最大的優勢就是相同線程不須要在等待鎖,而是能夠直接進行相應操做。
Redis分佈式鎖會有個缺陷,就是在Redis哨兵模式下:
客戶端1
對某個master節點
寫入了redisson鎖,此時會異步複製給對應的 slave節點。可是這個過程當中一旦發生 master節點宕機,主備切換,slave節點從變爲了 master節點。
這時客戶端2
來嘗試加鎖的時候,在新的master節點上也能加鎖,此時就會致使多個客戶端對同一個分佈式鎖完成了加鎖。
這時系統在業務語義上必定會出現問題,致使各類髒數據的產生。
缺陷
在哨兵模式或者主從模式下,若是 master實例宕機的時候,可能致使多個客戶端同時完成加鎖。
說明
這篇博客主要是根據本身的開發經驗,同時也在網上找了許多資料後整理的,若是哪裏有寫的不對,但願多多指點。萬分感激!
只要本身變優秀了,其餘的事情纔會跟着好起來(中將5)