這個玩意兒問的太多,現在很多面試官已經避開了這個面試題
我這里也不講太多,而是在實現上做一些總結和分析
看看有沒有幫助
1. 什么是分布式鎖?
鎖大家已經很清楚了,就是避免線程競爭出現問題,那分布式鎖,自然在分布式環境下避免線程或進程競爭出現問題了。
一句話回答: 分布式下,對共享資源進行互斥訪問的一種處理機制。
列幾個應用場景(工作中實際用到的):
1. 定時任務
定時任務寫在服務里時,同時啟動了多個服務,這個時候就需要用到分布式鎖,保證只有一個服務去執行定時任務。(即便定時任務有冪等性,但是也要考慮并發帶來的問題)
2. 三方認證信息維護
我們要接入第三方系統(例如:微信公眾平臺),通過Token進行訪問,Token失效時,需要去更新Token,這個時候只允許一個服務去更新,其他服務使用舊的token訪問(微信拿到新token時,舊的token還有5分鐘有效期),其他第三方系統我們也是用到了分布式鎖處理。
上面兩個例子,公司至今還有系統在使用,大部分定時任務已經移植到了統一調度中心,三方信息維護目前還在應用,至于網上經常看到的秒殺,搶購的案例,我是不贊同用分布式鎖的,分布式鎖也要解決單點問題,其次分布式鎖性能也較低。
2. redis如何實現分布式鎖?【極速回答版】
這個面試題我真的不想說了,不知道問了多少次,這里我簡單快速的回顧一下,不像網上的長篇大論去討論,而是說一些關鍵注意事項,這些事項說完,面試基本沒有問題,沒有誰面試真的讓你去代碼實現分布式鎖。
1. 原子性
設置獲取鎖的命令一定要原子性,不能分多個命令進行,如果確實需要多個命令,則使用Lua腳本去完成。
2. 持有線程
因為要保證鎖的安全性,要求記錄持有鎖的線程,允許重入和解鎖,也避免其他線程未持有鎖釋放該鎖。
3. 鎖釋放
如果獲取鎖的服務自身掛掉,也要保證鎖能夠釋放掉,這個時候通常用超時(key有效期)來處理。
4. 超時檢查
如果應用沒有掛,結果鎖超時釋放了,這也是一個問題,這個時候就可以通過檢查持鎖線程狀態的方式去解決,另起檢查線程(我是不理解了,另起檢查線程,萬一它也掛了呢,所以多此一舉嘛,也可以自身檢查后延長時間,這個就更不靠譜了,自己執行任務都超時了,還來得及延長鎖么)
5. 單點性
如果Redis服務自身掛了,也要考慮鎖是否還能被使用,這個時候就需要集群處理了。
通過上面幾點看,自身去實現一個分布式鎖,太繁瑣,所以Redis官方給了建議,使用Redlock(也有一些其它的框架實現Redis分布式鎖);那么新的面試題又來了,Redlock的實現原理。
這里先不去對比其他方式實現分布式鎖(例如zookeeper和數據庫等)
3. Redlock實現原理?問題分析
Redlock的實現原理如下:
-
獲取當前時間戳
-
嘗試在多個Redis節點上獲取鎖,每個節點使用相同的
key
和value
,并設置一個過期時間。 -
統計成功獲取鎖的節點數量,根據1的時間計算獲取鎖花費的時間,判斷鎖是否過期
-
如果大多數節點獲取鎖成功,并在有效期內,則獲取成功
-
如果獲取鎖失敗,則在所有成功獲取鎖的節點上釋放鎖。
Redlock也存在一些問題,例如:
1. 時鐘偏移
-
如果每個節點時間戳不一樣,過期時間可能計算錯誤
2. 鎖提前釋放
-
和第一道題的一樣,如果還沒有釋放鎖,鎖已經過期了,導致其他客戶端可以獲取鎖
3. 分布式系列問題,用例子說明
-
1
2
3
4
5
臺服務,A線程在1
2
3
設置鍵成功,A持有鎖,B線程在4
5
設置鍵,此時3
掛了,重啟后丟失A創建的鍵,B線程又設置鍵成功了,那就AB均獲取到鎖了,可以通過持久化解決。 -
1
2
3
4
5
臺服務,A線程在1
2
設置鍵成功,B線程在3
4
設置鍵成功,C線程在5
設置鍵成功,導致都獲取不到鎖,只能都釋放重新來了,很難完全解決。
4. 性能問題
-
節點越多,獲取鎖的時間就越長,情況也會越復雜
所以Redlock
也不能很好的解決分布式鎖的系列問題, 這個時候又來個Redlock++
,它可以解決一部分問題,更復雜了,沒有必要再深入了,通常情況下,使用分布式鎖也得取舍,因為它本身為了解決互斥問題,卻帶來了更多的問題,要么直接使用開源的分布式鎖框架,要么直接改變業務方式。