java爲什麼還需要分佈式鎖?鎖的演進

原文:https://baijiahao.baidu.com/s?id=1655515801283332550&wfr=spider&for=pc

 

 

 

目前的項目單體結構的基本上已經沒有了,大多是分佈式集羣或者是微服務這些。既然是多臺服務器。就免不了資源的共享問題。既然是資源共享就免不了併發的問題。針對這些問題,redis也給出了一個很好的解決方案,那就是分佈式鎖。這篇文章主要是針對爲什麼需要使用分佈式鎖這個話題來展開討論的。不喜勿噴。

前一段時間在羣裏有個兄弟問,既然分佈式鎖能解決大部分生產問題,那麼java爲我們提供的那些鎖有什麼用呢?直接使用分佈式鎖不就結了嘛。針對這個問題我想了很多,一開始是在網上找找看看有沒有類似的回答。後來想了想。想要解決這個問題,還需要從本質上來分析。

OK,開始上車出發。

一、前言

既然是分佈式鎖,這就說明服務器不是一臺,可能是很多臺。我們使用一個案例,來一步一步說明。假設某網站有一個秒殺商品,一看還有100件,於是陝西、江蘇、西藏等地的人都看到了這個活動,於是開始進行瘋狂秒殺。假設這個秒殺商品的數量值保存在一個redis數據庫中。

 

(3)新建config包,創建RedisConfig類

 

(4)新建controller,創建Mycontroller類

 

很簡單的一個整合教程。這個端口是8080,我們複製一份這個項目,把端口改成8090,並且以nginx作負載均衡搭建集羣。現在環境我們已經整理好了。下面我們就開始進行分析。

三、爲什麼需要分佈式鎖**

階段一:採用原生方式

我們使用多個線程訪問8080這個端口。因爲沒有加鎖,此時肯定會出現併發問題。因此我們可能會想到,既然這個goods是一個共享資源,而且是多線程訪問的,就立馬能想到java中的各種鎖了,最有名的就是synchronized。所以我們不如對上面的代碼進行優化。

階段二:使用synchronized加鎖

此時我們對代碼修改一下:

 

看到沒,現在我們使用synchronized關鍵字加上鎖,這樣多個線程併發訪問的時候就不會出現數據不一致等各種問題了。這種方式在單體結構下的確有用。目前的項目單體結構的很少,一般都是集羣方式的。此時的synchronized就不再起作用了。爲什麼synchronized不起作用了呢?

我們採用集羣的方式去訪問秒殺商品(nginx爲我們做了負載均衡)。就會看到數據不一致的現象。也就是說synchronized關鍵字的作用域其實是一個進程,在這個進程下面的所有線程都能夠進行加鎖。但是多進程就不行了。對於秒殺商品來說,這個值是固定的。但是每個地區都可能有一臺服務器。這樣不同地區服務器不一樣,地址不一樣,進程也不一樣。因此synchronized無法保證數據的一致性。

階段三:分佈式鎖

上面synchronized關鍵字無法保證多進程的鎖機制,爲了解決這個問題,我們可以使用redis分佈式鎖。現在我們把代碼再進行修改一下:

 

就是這麼簡單,我們只是加了一句話,然後進行判斷了一下。其實setIfAbsent方法的作用就是redis中的setnx。意思是如果當前key已經存在了,就不做任何操作了,返回false。如果當前key不存在,那我們就可以操作。最後別忘了釋放這個key,這樣別人就可以再進來實時秒殺操作。

當然這裏只是給出一個最基本的案例,其實分佈式鎖實現起來步驟還是比較多的,而且裏面很多坑也沒有給出。我們隨便解決幾個:

階段四:分佈式鎖優化

(1)第一個坑:秒殺商品出現異常,最終無法釋放lock分佈式鎖

 

此時我們加一個try和finally語句就可以了。最終一定要刪除lock。

(2)第二個坑:秒殺商品時間太久,其他用戶等不及

 

給其添加一個過期時間,也就是說如果10毫秒內沒有秒殺成功,就表示秒殺失敗,換下一個用戶。

(3)第三個坑:高併發場景下,秒殺時間太久,鎖永久失效問題

我們剛剛設置的鎖過期時間是10毫秒,如果一個用戶秒殺時間是15毫秒,這也就意味着他可能還沒秒殺成功,就有其他用戶進來了。當這種情況過多時,就可能有大量用戶還沒秒殺成功其他大量用戶就進來了。有可能其他用戶提前刪除了lock,但是當前用戶還沒有秒殺成功。最終造成數據的不一致。看看如何解決:

 

也就是說,我們在刪除lock的時候判斷是不是當前的線程,如果是那就刪除,如果不是那就不刪除,這樣就算別的線程進來也不會亂刪lock,造成混亂。

OK,到目前爲止基本上把分佈式鎖的緣由介紹了一遍。對於分佈式鎖redisson完成的相當出色,下篇文章也將圍着繞Redisson來介紹一下分佈式如何實現,以及其中的原理。

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