Mysql數據庫如何實現分佈式鎖

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

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

分佈式鎖簡述

鎖的引入和侷限性

鎖是一種控制共享資源爭搶的機制,採用互斥方式防止多線程(或多進程)間造成的衝突。鎖是一種獲取保護資源的憑證,就像公園門票,只有持有門票纔有資格入園;鎖是使得對同一類共享資源的訪問串行化。沒有獲得鎖只能排隊等待,直到其他線程釋放掉鎖。這裏需要對“同一類共享資源”正確理解,比如訂單系統中的同一種商品庫存,退款系統中同一個用戶。

在多線程中,Java 已經提供了很好原生鎖(包括synchronized,lock),前面的其他文章中也已經講到了內置鎖和顯示鎖的理解和使用,在此不再贅述。但是(是不是已經料到了我要說但是了呢?),在分佈式系統中,因爲要跨進程或者跨服務器 ,這種場景下JDK原生鎖已經無法滿足我們的需求,需要一種能夠分佈式系統中保護共享資源的方式,分佈式鎖在這種情況下產生了。

很多事情往往都是如此,爲了解決一個問題,引入了新方案,而新方案卻會帶來其他的問題,又需要用更多的時間去解決新方案帶來的問題。沒有一個完美的方案,因此對方案的取捨,就是具體場景中應該重點關注哪些問題,忽略哪些問題的選擇。

分佈式鎖的三要素

分佈式鎖是一個在分佈式環境中很重要的原語,它表明不同進程間採用互斥的方式操作共享資源。如何才稱得上分佈式鎖呢?分佈式鎖需要滿足三個基本的條件:

外部存儲

顧名思義,分佈式鎖是在分佈式部署環境中給多個主機提供鎖服務。Java具有天生的多線程優勢,在同一個進程的線程中可以通過互斥鎖住共享資源來保證多線程之間干擾,鎖的載體是堆中共享變量,使用JDK原生鎖synchronized和lock可以很方便的解決,但是將問題擴展到分佈式環境中,就超出了JDK原生鎖作用範疇。需要另外的存儲載體,可以是共享內存或者磁盤文件。考慮到分佈式鎖的高可用性,避免單點問題,因此共享內存中數據是需要持久化的,這點內容會在下文中的分佈式鎖的高可用中涉及到。

基於數據庫實現分佈式鎖

要實現分佈式鎖,最簡單的方式可能就是直接創建一張鎖表,然後通過操作該表中的數據來實現了。

當我們要鎖住某個方法或資源時,我們就在該表中增加一條記錄,想要釋放鎖的時候就刪除這條記錄。

創建這樣一張數據庫表:

當我們想要鎖住某個方法時,執行以下SQL:

因爲我們對method_name做了唯一性約束,這裏如果有多個請求同時提交到數據庫的話,數據庫會保證只有一個操作可以成功,那麼我們就可以認爲操作成功的那個線程獲得了該方法的鎖,可以執行方法體內容。

當方法執行完畢之後,想要釋放鎖的話,需要執行以下Sql:

上面這種簡單的實現有以下幾個問題:

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

2、這把鎖沒有失效時間,一旦解鎖操作失敗,就會導致鎖記錄一直在數據庫中,其他線程無法再獲得到鎖。

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

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

當然,我們也可以有其他方式解決上面的問題。

數據庫是單點?搞兩個數據庫,數據之前雙向同步。一旦掛掉快速切換到備庫上。

沒有失效時間?只要做一個定時任務,每隔一定時間把數據庫中的超時數據清理一遍。

非阻塞的?搞一個while循環,直到insert成功再返回成功。

非重入的?在數據庫表中加個字段,記錄當前獲得鎖的機器的主機信息和線程信息,那麼下次再獲取鎖的時候先查詢數據庫,如果當前機器的主機信息和線程信息在數據庫可以查到的話,直接把鎖分配給他就可以了。

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

總結

以 上就是我對這篇文章及其優化總結,分享給大家,希望大家有所收穫,覺得收穫的話可以點個關注收藏轉發一波喔,謝謝大佬們支持!

  • 1、多寫多敲代碼,好的代碼與紮實的基礎知識一定是實踐出來的

  • 2、可以去百度搜索騰訊課堂圖靈學院的視頻來學習一下java架構實戰案例,還挺不錯的。

  • 最後,每一位讀到這裏的網友,感謝你們能耐心地看完。希望在成爲一名更優秀的Java程序員的道路上,我們可以一起學習、一起進步!都能贏取白富美,走向架構師的人生巔峯!

  • 3丶想了解學習以上課程內容可加羣:722040762 驗證碼:博客(06 必過)歡迎大家的加入喲!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章