為什麼使用鎖
鎖的出現是為了解決資源爭用問題,在單程序環境下的資源爭奪可以使用jdk裡的鎖實現.
為什麼使用分布式鎖?
顧名思義,分布式鎖是為了分布式環境下的資源爭用問題.
zookeeper是如何實現分布式鎖的?
基於zookeeper的分布式鎖都是依賴於zk節點路徑唯一的機制來實現的.
什麼意思呢?
就是在zk中,在分布式鎖的場景下對於同乙個路徑,只能有乙個客戶端能建立成功,其它的都建立失敗
.(這個不難理解,在平時系統中也沒見過有哪2個檔案位址完全相同)
下面就說一下zk分布式鎖2種實現,沒錯 本篇就是幹的不能再幹的乾貨!!!
第一種實現是利用的zk的臨時節點, 在爭搶鎖的時候,所有的客戶端都嘗試建立乙個臨時節點(代表鎖住的資源),只有乙個客戶端會建立成功,建立成功的客戶端得到鎖,其它的客戶端則監聽(利用zk的watch)該節點的狀態改變並且進入阻塞,節點改變後 zk server 會通知剩下的客戶端,剩下的客戶端停止阻塞並且重新爭搶鎖.
zk中有持久節點和臨時節點,為什麼使用臨時節點呢?
如果使用的是持久節點,則這個節點在客戶端下線後,依舊會一直存在,不會自動刪除,導致其它客戶端一直無法爭搶到鎖
.如果使用的是臨時節點的話,在客戶端下線後zk會刪除與其相關的臨時節點,這樣其它客戶端就能重新爭搶鎖
.
@override
public
void
lock()
}@override
public
boolean
trylock()
catch
(zknodeexist***ception e)
return
true;}
/** * 爭搶不到鎖的話,等待鎖的釋放
*/private
void
waitforlock()
@override
public
void
handledatachange
(string datapath, object data)
throws exception };
// 監聽
client.
subscribedatachanges
(lockpath, listener)
;// 判斷鎖節點是否存在,存在的話表明有別人if(
this
.client.
exists
(lockpath)
)catch
(interruptedexception e)
}// 取消監聽訊息
client.
unsubscribedatachanges
(lockpath, listener)
;}
實現簡單,但是會有羊群效應
,節點的刪除都會通知所有的客戶端,並且所有的客戶端會取消監聽 + 重新一起爭奪鎖 + 爭奪失敗 + 再次開啟監聽
,如此迴圈,資源耗費多,並且這種耗費是可以避免的,那麼如何避免呢?就是下面第二種的改進版分布式鎖
.
這一種分布式鎖的實現是利用zk的臨時順序節點,每乙個客戶端在爭奪鎖的時候都由zk分配乙個順序號(sequence),客戶端則按照這個順序去獲取鎖.
lock跟前面的一樣,不過lockpath(鎖住的資源)是乙個持久節點,客戶端在該持久節點下面建立臨時順序節點,獲取到順序號後,根據自己是否是最小的順序號來獲取鎖,順序號最小則獲取鎖,序號不為最小則監聽(watch)前乙個順序號,當前乙個順序號被刪除的時候表明鎖被釋放了,則會通知下乙個客戶端.
下面貼出跟第一種實現不同的**
/**
* 嘗試加鎖
* * @return
*/@override
public
boolean
trylock()
// 獲得所有的子節點
list
children =
this
.client.
getchildren
(lockpath)
;// 排序list
collections.
sort
(children)
;// 判斷當前節點是否是最小的,如果是最小的節點,則表明此這個client可以獲取鎖
if(currentpath.
equals
(lockpath +
"/"+ children.
get(0)
))else
return
false;}
private
void
waitforlock()
@override
public
void
handledatachange
(string datapath, object data)
throws exception };
// 監聽前乙個臨時節點
client.
subscribedatachanges
(this
.beforepath, listener)
;// 前乙個節點還存在,則阻塞自己if(
this
.client.
exists
(this
.beforepath)
)catch
(interruptedexception e)
}// 醒來後,表明前乙個臨時節點已經被刪除,此時客戶端可以獲取鎖 && 取消watcher監聽
client.
unsubscribedatachanges
(this
.beforepath, listener)
;}
實現比第一種複雜一點,但是更加的合理,少做了很多不必要的操作,只喚醒了後面乙個客戶端.
由於zk自身的設計,zk不適合高併發寫,需要在使用zk分布式鎖前先做一定過濾操作,先過濾掉部分請求,再進行鎖爭奪.
分布式鎖當然不止zk的實現,各個實現都有其適用的場景,在分布式系統中,沒有最完美的方案,只有最合適的方案,往往都是取捨問題.
zookeeper分布式鎖
方案1 演算法思路 利用名稱唯一性,加鎖操作時,只需要所有客戶端一起建立 test lock節點,只有乙個建立成功,成功者獲得鎖。解鎖時,只需刪除 test lock節點,其餘客戶端再次進入競爭建立節點,直到所有客戶端都獲得鎖。特點 這種方案的正確性和可靠性是zookeeper機制保證的,實現簡單。...
zookeeper分布式鎖
zookeeper節點有4個型別 1.持久型 2.瞬時型 3.持久自動排序型 4.瞬時自動排序型 分布式鎖利用的就是zookeeper中瞬時自動排序型節點特性。一 瞬時自動排序節點 瞬時特點為,當客戶端斷開連線的時候,該節點自動消除。自動排序則為,如果節點名字重複,則自動在該節點名字後新增數字,該數...
zookeeper 分布式鎖
分布式鎖肯定是用在分布式環境下。在分布式環境下,使用分布式鎖的目的也是保證同一時刻只有乙個執行緒來修改共享變數,修改共享快取 前景 jdk提供的鎖只能保證執行緒間的安全性,但分布式環境下,各節點之間的執行緒同步執行卻得不到保障,分布式鎖由此誕生。實現方式有以下幾種 基於資料庫實現分布式鎖 基於快取 ...