思路
加鎖時,在指定路徑建立臨時節點(臨時節點避免死鎖),於是只有乙個執行緒能建立成功;
等待時,其他建立節點失敗的執行緒,會watch指定路徑的刪除事件,一旦事件觸發,說明臨時節點被刪除,執行緒可以繼續去獲取鎖;
解鎖時,當前執行緒刪除它建立的節點
**
public
class
zookeeperdistrbutelock
catch
(exception e)
}@override
public
void
waitlock()
}public
void
handledatachange
(string path, object data)
throws exception };
// 註冊事件
zkclient.
subscribedatachanges
(path, izkdatalistener)
;//如果節點存
if(zkclient.
exists
(path)
)catch
(exception e)
}// 刪除監聽
zkclient.
unsubscribedatachanges
(path, izkdatalistener);}
public
void
unlock()
}}
使用時注意,由於countdownlatch和zkclient(如果共享,那麼當乙個執行緒呼叫close方法後,其他執行緒再建立節點時會報錯)在此處不是共享變數,所以每個執行緒使用時都需要new zookeeperdistrbutelock
類的例項
缺點會引起羊群效應,即解鎖後大量等待的執行緒紛湧而至。
思路(類似於公平鎖)
加鎖時,也是在指定路徑建立臨時節點,但此時是帶序號的節點,最終多個執行緒都能建立節點成功,格式為路徑+遞增序號。
但是需要從這麼多節點中選出第乙個,於是對路徑進行排序,只有建立了第乙個節點的執行緒,才能返回true;反之,獲取它前面乙個節點的路徑
等待時,建立失敗的執行緒依次watch它前乙個節點路徑,每個節點都是如此;
解鎖時,當前執行緒刪除它建立的節點
**
public
class
zookeeperdistrbutelock2
}@override
public
boolean
trylock()
//獲取所有臨時節點並排序,臨時節點名稱為自增長的字串如:0000000400
list
childrens =
this
.zkclient.
getchildren
(path2)
; collections.
sort
(childrens);if
(currentpath.
equals
(path2 +
'/'+childrens.
get(0)
))else
return
false;}
@override
public
void
waitlock()
}public
void
handledatachange
(string datapath, object data)
throws exception };
//給排在前面的的節點增加資料刪除的watcher,本質是啟動另外乙個執行緒去監聽前置節點
this
.zkclient.
subscribedatachanges
(beforepath, listener);if
(this
.zkclient.
exists
(beforepath)
)catch
(interruptedexception e)
}this
.zkclient.
unsubscribedatachanges
(beforepath, listener);}
public
void
unlock()
}
優點
後面的節點只會watch前面的節點,當釋放鎖時,不會引起羊群效應
分布式鎖解決方案
分布式鎖三種實現方式 1.基於資料庫實現分布式鎖 2.基於快取 redis等 實現分布式鎖 3.基於zookeeper實現分布式鎖 1.悲觀鎖 利用select where for update 排他鎖 注意 其他附加功能與實現一基本一致,這裡需要注意的是 where name lock name欄...
ZK分布式鎖
分布式鎖是控制分布式系統之間同步訪問共享資源的一種方式。如果不同的系統或者是同乙個系統的不同主機之間共享了乙個或者一組資源,那麼訪問這些資源的時候,往往需要一些互斥手段來防止彼此之間的干擾,以保證一致性,在這種情況下,就需要分布式鎖了 zookeeper中有一種節點叫做順序節點,假如我們在 lock...
zk分布式鎖
zk 分布式鎖,其實可以做的比較簡單,就是某個節點嘗試建立臨時 znode,此時建立成功了就獲取了這個鎖 這個時候別的客戶端來建立鎖會失敗,只能註冊個 監聽這個鎖。釋放鎖就是刪除這個 znode,一旦釋放掉就會通知客戶端,然後有乙個等待著的客戶端就可以再次重新加鎖。zookeepersession ...