Java分布式鎖實現詳解

?????? 在進行大型網站技術架構設計以及業務實現的過程中,多少都會遇到需要使用分布式鎖的情況。那么問題也就接踵而至,哪種分布式鎖更適合我們的項目?

下面就這個問題,我做了一些分析:

分布式鎖現狀:

?????? 目前幾乎很多大型網站及應用都是分布式部署的,分布式場景中的數據一致性問題一直是一個比較重要的話題。

??????? 分布式的CAP理論告訴我們“任何一個分布式系統都無法同時滿足一致性(Consistency)、可用性(Availability)和分區容錯性(Partition

tolerance),最多只能同時滿足兩項。”所以,很多系統在設計之初就要對這三者做出取舍。在互聯網領域的絕大多數的場景中,都需要犧牲強一致性來換取系統的高可用性,系統往往只需要保證“最終一致性”,只要這個最終時間是在用戶可以接受的范圍內即可。

??????? 在很多場景中,我們為了保證數據的最終一致性,需要很多的技術方案來支持,比如分布式事務、分布式鎖等。有的時候,我們需要保證一個方法在同一時間內只能被同一個線程執行。在單機環境中,Java中其實提供了很多并發處理相關的API,但是這些API在分布式場景中就無能為力了。也就是說單純的Java Api并不能提供分布式鎖的能力。所以針對分布式鎖的實現目前有多種方案。

分布式鎖實現方案:

分布式鎖的實現,目前比較常用的有以下3種方案:

?1. 基于數據庫實現分布式鎖

?2. 基于緩存(redis,memcached,tair)實現分布式鎖

?3. 基于Zookeeper實現分布式鎖

在實際落地的時候 會選擇實現多個引擎(zk+redis/tair) 方便不同業務使用

分布式鎖定義:

?????? 分布式鎖是控制分布式系統之間同步訪問共享資源的一種方式。在分布式系統中,常常需要協調他們的動作。如果不同的系統或是同一個系統的不同主機之間共享了一個或一組資源,那么訪問這些資源的時候,往往需要互斥來防止彼此干擾來保證一致性,在這種情況下,便需要使用到分布式鎖。

分布式鎖的思考:

?????? 在分析這幾種實現方案之前我們先來想一下,我們需要的分布式鎖應該是怎么樣的?(這里以方法鎖為例,資源鎖同理)

可以保證在分布式部署的應用集群中,同一個方法在同一時間只能被一臺機器上的一個線程執行。

這把鎖要是一把可重入鎖(避免死鎖)

這把鎖最好是一把阻塞鎖(根據業務需求考慮要不要這條)

有高可用的獲取鎖和釋放鎖功能

獲取鎖和釋放鎖的性能要好

分布式鎖具體實現:

基于數據庫

? ? 簡單的方式就是建立一張鎖表,通過操作該表的數據來實現了。

? ? 這種鎖的設計是用數據庫的樂觀鎖實現的,可以滿足基本的交易的并發以及交易重試的冪等性。? ? ? 大概實現就是,根據鎖字段查找該鎖是否存在,如果存在,則判斷該鎖狀態,根據業務需要是否成功拿鎖;如果不存在,則插入鎖;

當然這種依賴數據庫實現鎖的缺陷有:

1、這把鎖強依賴數據庫的可用性,數據庫是一個單點,一旦數據庫掛掉,會導致業務系統不可用。

2、這把鎖沒有失效時間,并且鎖的數據會一直增長。

3、這把鎖只能是非阻塞的,因為數據的insert操作,一旦插入失敗就會直接報錯。沒有獲得鎖的線程并不會進入排隊隊列,要想再次獲得鎖就要再次觸發獲得鎖操作。

4、這把鎖是非重入的,同一個線程在沒有釋放鎖之前無法再次獲得該鎖。因為數據中數據已經存在了。

5、操作數據庫需要一定的開銷,性能問題需要考慮

其實針對上述我們已經對1和4做了優化:

1.數據庫做主從同步

4.為滿足可重入,設置了線程號

? ? ? ?基于數據庫排他鎖

除了可以通過增刪操作數據表中的記錄以外,其實還可以借助數據中自帶的鎖來實現分布式的鎖。

基于緩存實現分布式鎖

可以使用緩存來代替數據庫來實現分布式鎖,這個可以提供更好的性能,同時,很多緩存服務都是集群部署的,可以避免單點問題。并且很多緩存服務都提供了可以用來實現分布式鎖的方法,比如Tair的put方法,redis的setnx方法等。并且,這些緩存服務也都提供了對數據的過期自動刪除的支持,可以直接設置超時時間來控制鎖的釋放。

使用緩存實現分布式鎖的優點

性能好,實現起來較為方便。

使用緩存實現分布式鎖的缺點

通過超時時間來控制鎖的失效時間并不是十分的靠譜。

基于Zookeeper實現分布式鎖

基于zookeeper臨時有序節點可以實現的分布式鎖。

大致思想即為:每個客戶端對某個方法加鎖時,在zookeeper上的與該方法對應的指定節點的目錄下,生成一個唯一的瞬時有序節點。

判斷是否獲取鎖的方式很簡單,只需要判斷有序節點中序號最小的一個。

當釋放鎖的時候,只需將這個瞬時節點刪除即可。同時,其可以避免服務宕機導致的鎖無法釋放,而產生的死鎖問題。

來看下Zookeeper能不能解決前面提到的問題。

鎖無法釋放?使用Zookeeper可以有效的解決鎖無法釋放的問題,因為在創建鎖的時候,客戶端會在ZK中創建一個臨時節點,一旦客戶端獲取到鎖之后突然掛掉(Session連接斷開),那么這個臨時節點就會自動刪除掉。其他客戶端就可以再次獲得鎖。

非阻塞鎖?使用Zookeeper可以實現阻塞的鎖,客戶端可以通過在ZK中創建順序節點,并且在節點上綁定監聽器,一旦節點有變化,Zookeeper會通知客戶端,客戶端可以檢查自己創建的節點是不是當前所有節點中序號最小的,如果是,那么自己就獲取到鎖,便可以執行業務邏輯了。

不可重入?使用Zookeeper也可以有效的解決不可重入的問題,客戶端在創建節點的時候,把當前客戶端的主機信息和線程信息直接寫入到節點中,下次想要獲取鎖的時候和當前最小的節點中的數據比對一下就可以了。如果和自己的信息一樣,那么自己直接獲取到鎖,如果不一樣就再創建一個臨時的順序節點,參與排隊。

單點問題?使用Zookeeper可以有效的解決單點問題,ZK是集群部署的,只要集群中有半數以上的機器存活,就可以對外提供服務。

可以直接使用zookeeper第三方庫??Curator?客戶端,這個客戶端中封裝了一個可重入的鎖服務。

比較三種分布式鎖

分布式鎖zk、數據庫、以及Redis三者都能實現,同樣是分布式鎖,三者的區別何在?

從理解的難易程度角度(從低到高):數據庫 > 緩存 > Zookeeper

從實現的復雜性角度(從低到高):Zookeeper >= 緩存 > 數據庫

從性能角度(從高到低):緩存 > Zookeeper >= 數據庫

從可靠性角度(從高到低):Zookeeper > 緩存 > 數據庫

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,208評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,746評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,666評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,477評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,960評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,200評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,726評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,617評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,807評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,049評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,425評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,674評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,432評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,769評論 2 372

推薦閱讀更多精彩內容

  • 關于Mongodb的全面總結 MongoDB的內部構造《MongoDB The Definitive Guide》...
    中v中閱讀 31,985評論 2 89
  • 最近工作中遇到需要使用分布式鎖的場景,對于用戶的主動還款和到期扣款操作我們可能有部分邏輯是一樣的,但是主動還款是用...
    bigfish1129閱讀 624評論 1 7
  • 2017年8月31日文章推薦 2017年8月30日文章推薦 2017年8月29日文章推薦 2017年8月28日文章...
    青春實驗室閱讀 212評論 0 0
  • 第一百零一封信 未寄出,折疊成心的形狀夾在書里 最后一頁,要留一片秋葉 輕輕的合上,進入冬眠。 秋天,寄不了相思 ...
    倩何人換取閱讀 189評論 0 1
  • 這是一個兩分鐘的世界,只有一分鐘給人們展示你是誰,另一分鐘讓他們喜歡你。 ——英國形象設計師...
    江南禮儀形象閱讀 218評論 0 0