天天看點

ZooKeeper場景實踐:(7) 分布式鎖

分布式鎖是控制分布式系統之間同步通路共享資源的一種方式,需要互斥來防止彼此幹擾來保證一緻性。利用zookeeper的強一緻性可以完成鎖服務。zookeeper的官方文檔是列舉了兩種鎖,獨占鎖和共享鎖。獨占鎖保證任何時候都隻有一個程序能或者資源的讀寫權限。共享鎖可以同時有多個讀,但是同一時刻最多隻能有一個寫,讀和寫是互斥的。

我們準備來實作互斥的鎖,按照官網的思路,給定一個鎖的路徑,如/lock,所有要申請這個鎖的程序都在/lock目錄下建立一個/lock/lock-的臨時序列節點,并監控/lock的子節點變化事件。當子節點發送變化時用get_children()擷取子節點的清單,如果發現程序發現自己擁有最小的一個序号,則獲得鎖。處理業務完畢後需要釋放鎖,此時隻需要删除該臨時節點即可。簡單來說就是永遠是擁有最小序号的程序獲得鎖。

使用鎖有兩個基本的函數,就是<code>lock</code>或<code>unlock</code>.定義為

<code>lock *lock(zhandle_t *zkhandle,const char *path)</code>

lock函數有兩個參數,一個是zookeeper_init傳回的句柄zkhandle,另一個是鎖的路徑,如果成功則傳回一個lock的結構體指針,并同時獲得鎖,否則傳回null。

<code>int unlock(zhandle_t *zkhandle,lock * *lock)</code>

unlock函數也有兩個參數,一個是zookeeper_init傳回的句柄zkhandle,另一個是lock函數傳回的結構體指針的指針。

接下來在看具體的實作。

<code>create_lock</code>:負責鎖的初始化,主要功能是負責建立{path}的節點已經{path}/lock-的臨時序列節點。{path}如果存在則不再建立。

<code>try_lock</code>:嘗試加鎖,這個函數不會等待,失敗和成功都立即傳回。其主要功能是擷取{path}的子節點清單,并檢視自己是否是擁有最小序列号的節點,如果是則傳回1,否則傳回0;

<code>lock</code>函數初始化鎖後,會持續的嘗試加鎖,直到成功。雖然我是這樣實作的,但是過于簡單粗暴(哈哈)。如果拿不到鎖的話,持續就會阻塞在<code>lock</code>函數。

<code>unlock</code>函數就非常簡單了,就是将<code>create_lock</code>中建立的臨時序列節點删除就可以了。

接下來在看下模拟程式的功能。

模拟程式有3個選項。其中

<code>-s</code>:為zookeeper的伺服器的ip:port.

<code>-p</code>: 為鎖的路徑。

分别同時運作多個mylock程式,就可以看到各個程式之間是如何擷取鎖的了。

最後是完整的代碼: