一、什麼是分布式鎖?
要介紹分布式鎖,首先要提到與分布式鎖相對應的是線程鎖、程序鎖。
線程鎖:主要用來給方法、代碼塊加鎖。當某個方法或代碼使用鎖,在同一時刻僅有一個線程執行該方法或該代碼段。線程鎖隻在同一JVM中有效果,因為線程鎖的實作在根本上是依靠線程之間共享記憶體實作的,比如synchronized是共享對象頭,顯示鎖Lock是共享某個變量(state)。
程序鎖:為了控制同一作業系統中多個程序通路某個共享資源,因為程序具有獨立性,各個程序無法通路其他程序的資源,是以無法通過synchronized等線程鎖實作程序鎖。
分布式鎖:當多個程序不在同一個系統中,用分布式鎖控制多個程序對資源的通路。
二、分布式鎖的使用場景。
線程間并發問題和程序間并發問題都是可以通過分布式鎖解決的,但是強烈不建議這樣做!因為采用分布式鎖解決這些小問題是非常消耗資源的!分布式鎖應該用來解決分布式情況下的多程序并發問題才是最合适的。
有這樣一個情境,線程A和線程B都共享某個變量X。
如果是單機情況下(單JVM),線程之間共享記憶體,隻要使用線程鎖就可以解決并發問題。
如果是分布式情況下(多JVM),線程A和線程B很可能不是在同一JVM中,這樣線程鎖就無法起到作用了,這時候就要用到分布式鎖來解決。
三、分布式鎖的實作(Redis)
分布式鎖實作的關鍵是在分布式的應用伺服器外,搭建一個存儲伺服器,存儲鎖資訊,這時候我們很容易就想到了Redis。首先我們要搭建一個Redis伺服器,用Redis伺服器來存儲鎖資訊。
在實作的時候要注意的幾個關鍵點:
1、鎖資訊必須是會過期逾時的,不能讓一個線程長期占有一個鎖而導緻死鎖;
2、同一時刻隻能有一個線程擷取到鎖。
幾個要用到的redis指令:
setnx(key, value):“set if not exits”,若該key-value不存在,則成功加入緩存并且傳回1,否則傳回0。
get(key):獲得key對應的value值,若不存在則傳回nil。
getset(key, value):先擷取key對應的value值,若不存在則傳回nil,然後将舊的value更新為新的value。
expire(key, seconds):設定key-value的有效期為seconds秒。
看一下流程圖:
在這個流程下,不會導緻死鎖。
附帶連結:https://www.cnblogs.com/linjiqin/p/8003838.html
附帶連結:http://ifeve.com/redis-lock/