基於ZooKeeper的分布式鎖實現(C 版本)

2021-08-15 13:03:09 字數 4537 閱讀 1795

一、簡介

分布式同步是zookeeper的功能之一,但zookeeper的分布式同步(分布式鎖)功能並非以直接的介面呈現的。開發者需要額外地基於zookeeper的節點(node)的分布式同步特性來實現分布式鎖的介面。

本文將提供基於基於zookeeper的分布式鎖的c++介面及實現,實現中用到了部分c++11特性。另外,本實現使用的是經過封裝的zookeeper介面,本文只列出這些zookeeper封裝介面,而不提供zookeeper封裝介面的實現**。讀者可以依理使用zookeeper原生介面,或自己封裝zookeeper介面。

二、基於zookeeper分布式鎖的實現流程

1、在zookeeper指定節點下建立臨時順序節點node_n;

2、獲取指定節點下所有子節點(children node);

3、對子節點按節點自增序號從小到大排序;

4、判斷第1步建立的節點是否為排序子節點的第乙個子節點,如是,則獲取鎖,如不是,則監聽比第1步建立的節點小的那個節點的刪除事件;

5、若監聽事件生效,則回到第2步重新進行判斷,直到獲取到鎖。

三、已封裝的zookeeper介面宣告

int32_t init(const std::string &hosts, const std::string &root_path = "/", const clientid_t *client_id = null);//zookeeper始化介面

int32_t connect(std::shared_ptrglobal_watcher_fun, int32_t recv_timeout_ms, uint32_t conn_timeout_ms = 30000);//連線zookeeper服務

int32_t exists(const std::string &path, stat *stat, std::shared_ptrwatcher_fun);//判斷zookeeper節點是否存在,並設定監控函式及就是監控

int32_t create(const std::string &path, const std::string &value, std::string *p_real_path = null, const acl_vector *acl = &zoo_open_acl_unsafe, int flags = 0, bool ephemeral_exist_skip = false);//建立節點

int32_t delete(const std::string &path, int version);//刪除節點

以上是封裝的zookeeper介面,本文將不列出封裝的實現,讀者可以自己嘗試封裝,或直接使用zookeeper原生介面。

四、分布式鎖實現的介面

分布式鎖介面包括:

1、initlock,指定zookeeper服務位址(ip及埠字串,之間以「:」隔開)及節點名,相同節點名的zookeeper客戶端間互斥;

2、lock,請求互斥鎖,如果其他zookeeper客戶端已獲取同一節點名的互斥鎖,則執行緒等待互斥鎖,直到獲取到互斥鎖,或超時,這個介面有兩個版本,乙個可以設定等待超時時間,另乙個不設定等待超時時間,只到等到互斥鎖才會返回;

3、unlock,釋放互斥鎖。

介面**如下:

#ifndef _zookeeper_lock_h_

#define _zookeeper_lock_h_

#include "cppzookeeper.h"

enum en_lockret

;class zookeeperlock

;#endif

五、分布式鎖實現

實現及上面介面標頭檔案的cpp檔案部分:

#include "zookeeperlock.h"

#include #include #include #include #include #define zookeeperlock "/zookeeperlock"

#define lockchildnode "lock_"

zookeeperlock::zookeeperlock()

zookeeperlock::~zookeeperlock()

bool zookeeperlock::initlock(const std::string& host, const std::string& lock_name)

zookeeper::watcherfuntype fnc_zk_watcher = std::bind(&zookeeperlock::zookeeperwatcher, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);

ret = m_zkmanager.connect(std::make_shared(fnc_zk_watcher), 2000, 3000);

if (zok != ret)

if (zok != m_zkmanager.exists(zookeeperlock)) }

if (zok != m_zkmanager.exists(lock_name)) }

m_strlockname = lock_name;

return true;

}en_lockret zookeeperlock::lock(unsigned int millisec)

unsigned int et = gettickcount() + millisec;

unsigned int ct = 0;

bool must_do = false;

do else if (1 == ret)

else if (1 == ret1)

else

}else

ct = gettickcount();

} while (ct < et || must_do);

deletenode();

return lock_ret_timeout;

}en_lockret zookeeperlock::lock(void)

return ret;

}void zookeeperlock::unlock(void)

int zookeeperlock::trylock(void)

for (int32_t i = 0; i < children.getsize(); ++i)

std::sort(vchildren.begin(), vchildren.end());

if (0 == vchildren.size())

std::string firstnode = parent_path + "/" + vchildren[0];

ret = m_selfnode.compare(firstnode);

if (0 == ret)

std::string self_path_child;

std::size_t pos = m_selfnode.rfind('/');

if (std::string::npos != pos)

if (self_path_child.empty())

std::vector::const_iterator itor = std::find(vchildren.begin(), vchildren.end(), self_path_child);

if (vchildren.end() == itor || vchildren.begin() == itor)

m_prenode = *(itor - 1);

return 1;

}int zookeeperlock::waitforlock(const unsigned int millisec)

if (znonode == ret)

std::unique_locklck(m_mtx);

//m_bnotify = false;

m_cv.wait_for(lck, std::chrono::milliseconds(millisec));

if (std::cv_status::timeout == m_cv.wait_for(lck, std::chrono::milliseconds(millisec)))

else /*

if (m_bnotify)

else

*/}bool zookeeperlock::createnode(void)

m_selfnode = self_path.c_str();

return true;

}bool zookeeperlock::deletenode(void)

return true;

}bool zookeeperlock::zookeeperwatcher(zookeeper::zookeepermanager &zk_mamager, int type, int state, const char *path)

} return false;

}unsigned int zookeeperlock::gettickcount(void)

基於ZooKeeper實現分布式鎖

zookeeper 保證了資料的強一致性,zk集群中任意節點 乙個zkserver 上的相同znode下的資料一定是相同的。使用zookeeper可以非常簡單的實現分布式鎖,其基本邏輯如下 客戶端呼叫create 方法建立名為 locknode lock 的節點,需要注意的是,這裡節點的建立型別需要...

基於zookeeper實現分布式鎖

zk有兩種資料節點,一種時持久節點 另一種時瞬時節點,有序,瞬時節點不可再有子節點,會話結束後瞬時節點自動消失 zookeeper的觀察器 可以設定觀察器的三個方法 getdata getchildren exist 資料節點發生變化,傳送給客戶端 觀察器只能監控一次,再監控需要重新設定 zk分布式...

分布式5 zookeeper分布式

一 為什麼需要zookeeper 大部分分布式應用需要乙個主控 協調器或控制器來管理物理分布的子程序 如資源 任務分配等 大部分應用需要開發私有的協調程式,缺乏乙個通用的機制 協調程式的反覆編寫浪費,且難以形成通用 伸縮性好的協調器 zookeeper可以提供通用的分布式鎖服務,用以協調分布式應用,...