One , brief introduction

Distributed synchronization is Zookeeper One of the functions of , but Zookeeper Distributed synchronization of ( Distributed lock ) Functions are not presented as direct interfaces . Developers need to additionally Zookeeper Node of (node) To realize the interface of distributed lock .

Based on the ZooKeeper Of distributed locks C++ Interface and Implementation , Part of the implementation C++11 characteristic . in addition , This implementation uses encapsulated ZooKeeper Interface , This article only lists these ZooKeeper Encapsulation interface , Not provided ZooKeeper Implementation code of encapsulation interface . Readers can use it according to reason ZooKeeper Native interface , Or self encapsulation ZooKeeper Interface .

Two , be based on ZooKeeper Implementation flow of distributed lock

1, stay ZooKeeper Create a temporary order node under the specified node node_n;

2, Get all child nodes under the specified node (children node);

3, Sort the child nodes from small to large by node auto increment number ;

4, Judgment No 1 Whether the node created in step is the first child of the sort child , If so , Get lock , If not , Then monitor the 1 Delete event of the node smaller than the node created in step ;

5, If the listening event takes effect , Then go back to No 2 Step to judge again , Until the lock is acquired .

Three , Encapsulated ZooKeeper Interface declaration
int32_t Init(const std::string &hosts, const std::string &root_path = "/",
const clientid_t *client_id = NULL);//ZooKeeper Initial interface int32_t
Connect(std::shared_ptr<WatcherFunType> global_watcher_fun, int32_t
recv_timeout_ms, uint32_t conn_timeout_ms = 30000);// connect ZooKeeper service int32_t
Exists(const std::string &path, Stat *stat, std::shared_ptr<WatcherFunType>
watcher_fun);// judge ZooKeeper Whether the node exists , And set monitoring function and monitoring 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);// Create node int32_t Delete(const std::string &path,
int version);// Delete node
These are packaged ZooKeeper Interface , This article will not list the implementation of encapsulation , Readers can try to encapsulate themselves , Or direct use ZooKeeper Native interface .

Four , Interface of distributed lock implementation

The distributed lock interface includes :

1,InitLock, appoint ZooKeeper Service address (IP And port string , Between “:” separate ) And node name , Of the same node name ZooKeeper Mutual exclusion between clients ;

2,Lock, Request mutex , If other ZooKeeper Client has acquired a mutex for the same node name , The thread waits for the mutex , Until the mutex is acquired , Or timeout , There are two versions of this interface , One can set the waiting timeout , Another does not set the wait timeout , Only wait for the mutex to return ;

3,UnLock, Release mutex .

The interface code is as follows :
#ifndef _ZOOKEEPER_LOCK_H_ #define _ZOOKEEPER_LOCK_H_ #include
"cppzookeeper.h" enum en_LockRet { LOCK_RET_SUCC = 0, LOCK_RET_TIMEOUT = 1,
LOCK_RET_ERR = 2 }; class ZookeeperLock { public: ZookeeperLock();
~ZookeeperLock(); bool InitLock(const std::string& host, const std::string&
lock_name); en_LockRet Lock(unsigned int millisec); en_LockRet Lock(void); void
UnLock(void); private: int TryLock(void); int WaitForLock(const unsigned int
millisec); bool CreateNode(void); bool DeleteNode(void); bool
ZookeeperWatcher(zookeeper::ZookeeperManager &zk_mamager, int type, int state,
const char *path); unsigned int GetTickCount(void); std::string m_strLockName;
zookeeper::ZookeeperManager m_zkManager; std::string m_selfNode; std::string
m_preNode; std::mutex m_mtx; std::condition_variable m_cv; //bool m_bnotify; };
#endif
Five , Distributed lock implementation

Implement the cpp Document part :
#include "zookeeperlock.h" #include <algorithm> #include <time.h> #include
<chrono> #include <mutex> #include <condition_variable> #define ZOOKEEPERLOCK
"/zookeeperlock" #define LOCKCHILDNODE "lock_" ZookeeperLock::ZookeeperLock() {
//m_bnotify = false; } ZookeeperLock::~ZookeeperLock() { } bool
ZookeeperLock::InitLock(const std::string& host, const std::string& lock_name)
{ if (host.empty() || lock_name.empty()) return false; if ('/' == lock_name[0])
return false; int32_t ret = m_zkManager.Init(host, ZOOKEEPERLOCK); if (ZOK !=
ret) { return false; } 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<zookeeper::WatcherFunType>(fnc_zk_watcher),
2000, 3000); if (ZOK != ret) { return false; } if (ZOK !=
m_zkManager.Exists(ZOOKEEPERLOCK)) { ret = m_zkManager.Create(ZOOKEEPERLOCK,
""); if (ZOK != ret) { return false; } } if (ZOK !=
m_zkManager.Exists(lock_name)) { ret = m_zkManager.Create(lock_name, ""); if
(ZOK != ret) { return false; } } m_strLockName = lock_name; return true; }
en_LockRet ZookeeperLock::Lock(unsigned int millisec) { if
(m_strLockName.empty()) return LOCK_RET_ERR; if (!CreateNode()) { return
LOCK_RET_ERR; } unsigned int et = GetTickCount() + millisec; unsigned int ct =
0; bool must_do = false; do { must_do = false; int ret = TryLock(); if (0 ==
ret) { return LOCK_RET_SUCC; } else if (1 == ret) { int ret1 = WaitForLock(ct
>0 ? (et > ct ? (et - ct) : 1) : millisec); if (0 == ret1) { must_do = true; }
else if (1 == ret1) { DeleteNode(); return LOCK_RET_TIMEOUT; } else {
DeleteNode(); return LOCK_RET_ERR; } } else { DeleteNode(); return
LOCK_RET_ERR; } ct = GetTickCount(); } while (ct < et || must_do);
DeleteNode(); return LOCK_RET_TIMEOUT; } en_LockRet ZookeeperLock::Lock(void) {
en_LockRet ret = LOCK_RET_SUCC; while (LOCK_RET_TIMEOUT == (ret = Lock(2000)))
{ ; } return ret; } void ZookeeperLock::UnLock(void) { bool ret = DeleteNode();
return; } int ZookeeperLock::TryLock(void) { std::string parent_path =
std::string(ZOOKEEPERLOCK) + std::string("/") + m_strLockName;
zookeeper::ScopedStringVector children; std::vector<std::string> vchildren; int
ret = m_zkManager.GetChildren(m_strLockName, children); if (ZOK != ret) {
return 2; } for (int32_t i = 0; i < children.GetSize(); ++i) {
vchildren.push_back(std::string(children.GetData(i))); }
std::sort(vchildren.begin(), vchildren.end()); if (0 == vchildren.size()) {
return 2; } std::string firstnode = parent_path + "/" + vchildren[0]; ret =
m_selfNode.compare(firstnode); if (0 == ret) { return 0; } std::string
self_path_child; std::size_t pos = m_selfNode.rfind('/'); if (std::string::npos
!= pos) { self_path_child = m_selfNode.substr(pos + 1); } if
(self_path_child.empty()) { return 2; }
std::vector<std::string>::const_iterator itor = std::find(vchildren.begin(),
vchildren.end(), self_path_child); if (vchildren.end() == itor ||
vchildren.begin() == itor) { return 2; } m_preNode = *(itor - 1); return 1; }
int ZookeeperLock::WaitForLock(const unsigned int millisec) { std::string
wait_path = m_strLockName + "/" + m_preNode; Stat stat;
zookeeper::WatcherFunType fnc_zk_watcher =
std::bind(&ZookeeperLock::ZookeeperWatcher, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3, std::placeholders::_4); int32_t
ret = m_zkManager.Exists(wait_path, &stat,
std::make_shared<zookeeper::WatcherFunType>(fnc_zk_watcher)); if (ZOK != ret &&
ZNONODE != ret) { return 2; } if (ZNONODE == ret) { return 0; }
std::unique_lock<std::mutex> lck(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))) { return 1; } else { return 0; } /* if
(m_bnotify) { return 0; } else { return 1; }*/ } bool
ZookeeperLock::CreateNode(void) { std::string child_node = m_strLockName + "/"
+ LOCKCHILDNODE; std::string self_path; self_path.resize(128); int32_t ret =
m_zkManager.Create(child_node, "", &self_path, &ZOO_OPEN_ACL_UNSAFE,
ZOO_EPHEMERAL | ZOO_SEQUENCE); if (ZOK != ret) { return false; } m_selfNode =
self_path.c_str(); return true; } bool ZookeeperLock::DeleteNode(void) {
int32_t ret = m_zkManager.Delete(m_selfNode, -1); m_selfNode = ""; m_preNode =
""; if (ZOK != ret) { return false; } return true; } bool
ZookeeperLock::ZookeeperWatcher(zookeeper::ZookeeperManager &zk_mamager, int
type, int state, const char *path) { if (ZOO_DELETED_EVENT == type) {
std::string strpath = path; std::string wait_path = std::string(ZOOKEEPERLOCK)
+ std::string("/") + m_strLockName + std::string("/") + m_preNode; if
(wait_path == strpath) { std::unique_lock<std::mutex> lck(m_mtx); //m_bnotify =
true; m_cv.notify_one(); } } return false; } unsigned int
ZookeeperLock::GetTickCount(void) { struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts); return (ts.tv_sec * 1000 + ts.tv_nsec /
1000000); }

Technology
©2019-2020 Toolsou All rights reserved,
JS How to operate java Realize the function of grabbing red packets C Language programming to find a student's grade The United Nations 《 Glory of Kings 》 Please go to the studio : To save the earth Dialogue between apple and Nissan suspended ,Apple Car How's it going ?CSS architecture design China's longest high speed rail officially opened ! The fastest way to finish the race 30.5 hour First knowledge MySQL Comprehensive review ( dried food )2021 year 1 Monthly programmer salary statistics , average 14915 element How to use it quickly html and css Write static page