步骤:
1.准备3台主机并同步好时间。
2.在主机1启动zookeeper服务,创建节点/services
3.在主机2运行应用程序,连接主机1的zookeeper
4.主机2往zookeeper的/services节点注册临时节点,节点名=IP:端口 节点数据=注册时间us
5.主机2监听/services节点
6.分别在主机1,主机3启动运行应用程序;分别向zookeeper注册临时节点。并监听/services节点。
7.以先启动的应用程序为主机,及节点数据小的为主机。
8.三台主机运行起来后,只有一台为主机,其余为备机。

zkCli.h

#ifndef _ZKCLIENT_H_
#define _ZKCLIENT_H_#ifdef _WIN32#include "zk\include\zookeeper.h"#include "zk\include\zookeeper.jute.h"#include "zk\include\zookeeper_log.h"#include "zk\include\zookeeper_version.h"
#else#include <zookeeper/zookeeper.h>#include <sys/types.h>#include <ifaddrs.h>#include <arpa/inet.h>#include <sys/socket.h>#include <netdb.h>#include <stdlib.h>#include <unistd.h>#include <net/if.h>#include <errno.h>#include <string.h>#include <pthread.h>
#endif#define INFO(fmt, args...) printf("[%s:%d %s][INFO]");printf(fmt, ##args);typedef void(*FUN)(const char*, const char*);class ZkCli
{private:zhandle_t *m_ZkHandle;pthread_mutex_t m_mutex;pthread_cond_t m_cond;bool m_Connected;char m_servAddr[64];char m_zkAddr[64];char m_path[64];FUN m_func;
public:ZkCli();~ZkCli();bool zkInit(const char* zkaddr, const char* path);int Create(const char* path);int Set(const char* path, const char* data, int size);void Register(const char* listenIp, const unsigned short listenPort, FUN func);void getLocalIp(char *localIp, int len);private:int64_t getTimeStampUs();void setConnected(bool stat);void ServiceWatch(const char* path);private:/*typedef void (*watcher_fn)(zhandle_t *zh, int type, int state, const char *path, void *watcherCtx);*/static void init_watcher(zhandle_t *zh, int type, int stat, const char* path, void* watcherCtx);static void require_wachter(zhandle_t *zh, int type, int stat, const char* path, void* watcherCtx);
};#endif

zkCli.cpp

#include "zkCli.h"
#include <sys/time.h>
#include <unordered_map>ZkCli::ZkCli()
: m_ZkHandle(NULL),
m_Connected(false)
{pthread_mutex_init(&m_mutex, NULL);pthread_cond_init(&m_cond, NULL);
}ZkCli::~ZkCli()
{pthread_mutex_destroy(&m_mutex);pthread_cond_destroy(&m_cond);zookeeper_close(m_ZkHandle);
}int64_t ZkCli::getTimeStampUs()
{struct timeval stamp;gettimeofday(&stamp, NULL);return (int64_t)(stamp.tv_sec * 1000000 + stamp.tv_usec);
}void ZkCli::setConnected(bool stat)
{if (stat){pthread_cond_signal(&m_cond);}m_Connected = stat;
}void ZkCli::init_watcher(zhandle_t *zh, int type, int stat, const char* path, void* watcherCtx)
{ZkCli* pCli = (ZkCli*)watcherCtx;if (type == ZOO_SESSION_EVENT){if (stat == ZOO_CONNECTING_STATE){pCli->setConnected(false);}else if (stat == ZOO_CONNECTED_STATE){pCli->setConnected(true);}else if (stat == ZOO_NOTCONNECTED_STATE){pCli->setConnected(false);}}
}void ZkCli::require_wachter(zhandle_t* zh, int type, int stat, const char* path, void* watherCtx)
{printf("require_wachter() : type=%d, stat=%d, path=%s\n", type, stat, path);ZkCli* pZkCli = (ZkCli*)watherCtx;pZkCli->ServiceWatch(path);
}void ZkCli::getLocalIp(char* localIp, int len)
{struct ifaddrs *ifaddr;if (getifaddrs(&ifaddr) == -1){printf("getifaddr failed, errno=%d, errmsg=%s\n", errno, strerror(errno));exit(EXIT_FAILURE);}char host[NI_MAXHOST];for (struct ifaddrs *ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {if (ifa->ifa_addr == NULL)continue;int family = ifa->ifa_addr->sa_family;if (!ifa->ifa_flags & IFF_BROADCAST){continue;}if (family == AF_INET || family == AF_INET6){int s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);if (s != 0){printf("getnameinfo() failed: %s\n", gai_strerror(s));break;}if (strcmp(host, "127.0.0.1")){strncpy(localIp, host, len);break;}}}freeifaddrs(ifaddr);
}bool ZkCli::zkInit(const char* zkAddr, const char* path)
{zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);m_ZkHandle = zookeeper_init(zkAddr, init_watcher, 3000, NULL, this, 0);if (!m_ZkHandle){INFO("zookeeper_init failed, zkAddr:%s, errno=%d, errmsg=%s\n", zkAddr, errno, strerror(errno));return false;}strncpy(m_zkAddr, zkAddr, sizeof(m_zkAddr));struct timeval now;gettimeofday(&now, NULL);pthread_mutex_lock(&m_mutex);struct timespec waitTime;waitTime.tv_sec = now.tv_sec + 5;waitTime.tv_nsec = now.tv_usec * 1000;pthread_cond_timedwait(&m_cond, &m_mutex, &waitTime);pthread_mutex_unlock(&m_mutex);strncpy(m_path, path, sizeof(m_path));int ret = Create(path);if (ret != ZOK && ret != ZNODEEXISTS){printf("create root path failed, path=%s\n", path);return false;}ServiceWatch(path);return true;
}int ZkCli::Create(const char* path)
{char path_buffer[256] = { 0 };int ret = zoo_create(m_ZkHandle, path, "", -1, &ZOO_OPEN_ACL_UNSAFE, 0, path_buffer, sizeof(path_buffer)-1);if (ret == ZOK){printf("create node %s succeed!\n", path);}else{printf("create node %s, ret=%d\n", path, ret);}return ret;
}int ZkCli::Set(const char* path, const char* data, int size)
{char path_buffer[256] = { 0 };int ret = zoo_create(m_ZkHandle, path, data, size, &ZOO_OPEN_ACL_UNSAFE, ZOO_EPHEMERAL, path_buffer, sizeof(path_buffer)-1);if (ret == ZOK){printf("set [%s]=[%s] succeed!\n", path_buffer, data);}else{printf("set [%s]=[%s] failed, ret=%d\n", path, data, ret);}return ret;
}void ZkCli::ServiceWatch(const char* path)
{/*ZOOAPI int zoo_wget_children(zhandle_t *zh, const char *path,watcher_fn watcher,void* watcherCtx,struct String_vector *strings);*/String_vector strvect;int rc = zoo_wget_children(m_ZkHandle, path, require_wachter, this, &strvect);if (rc != ZOK){printf("zoo_wget_children faield, path:%s, rc=%d\n", path, rc);return;}std::string master_server;uint64_t min_starttimeus = 0;for (int i = 0; i < strvect.count; i++){printf("str[%d]:%s\n", i, strvect.data[i]);char nodepath[64] = { 0 };snprintf(nodepath, sizeof(nodepath)-1, "%s/%s", path, strvect.data[i]);char buffer[256] = { 0 };int buffer_len = sizeof(buffer);if (ZOK == zoo_get(m_ZkHandle, nodepath, 0, buffer, &buffer_len, NULL)){uint64_t startTimeus = atoll(buffer);if (min_starttimeus == 0){min_starttimeus = startTimeus;master_server = strvect.data[i];}else if (min_starttimeus > startTimeus){min_starttimeus = startTimeus;master_server = strvect.data[i];}printf("%s=%ld\n", nodepath, startTimeus);}}printf("master server=%s, timeus=%ld\n", master_server.c_str(), min_starttimeus);if (strcmp(m_servAddr, master_server.c_str()) == 0){printf("should switch to master!\n");if (m_func){m_func("","");}}else{printf("should switch to slave!\n");}
}void ZkCli::Register(const char* listenIp, const unsigned short listenPort, FUN func)
{snprintf(m_servAddr, sizeof(m_servAddr)-1, "%s:%d", listenIp, listenPort);m_func = func;int64_t TimeStampUs = getTimeStampUs();char TimeStampStr[32] = { 0 };snprintf(TimeStampStr, sizeof(TimeStampStr)-1, "%ld", TimeStampUs);char ServicePath[128] = { 0 };snprintf(ServicePath, sizeof(ServicePath)-1, "%s/%s", m_path, m_servAddr);Set(ServicePath, TimeStampStr, strlen(TimeStampStr));
}

Makefile

CC=g++ -g
SRC=$(wildcard *.cpp)
OBJ=${SRC:%.cpp=%.o}FLAG=-DTHREADED
LIB=-lpthread -lzookeeper_mtTARGET=zk_clientall:${TARGET}${TARGET}:${OBJ}${CC} -o ${TARGET} ${OBJ} ${LIB}%.o:%.cpp${CC} ${FLAG} -c $? -o $@

运行结果:
62:

[root@localhost zk_client]# ./zk_client
create node /services, ret=-110
master server=, timeus=0
should switch to slave!
zookeeper connected!
require_wachter() : type=4, stat=3, path=/services
set [/services/192.168.1.62:9044]=[1632473624547276] succeed!
str[0]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473624547276
master server=192.168.1.62:9044, timeus=1632473624547276
should switch to master!
enter switch func
require_wachter() : type=4, stat=3, path=/services
str[0]:192.168.1.86:9044
/services/192.168.1.86:9044=1632473592590648
str[1]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473624547276
master server=192.168.1.86:9044, timeus=1632473592590648
should switch to slave!
require_wachter() : type=4, stat=3, path=/services
str[0]:192.168.1.86:9044
/services/192.168.1.86:9044=1632473592590648
str[1]:192.168.1.85:9044
/services/192.168.1.85:9044=1632473596504658
str[2]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473624547276
master server=192.168.1.86:9044, timeus=1632473592590648
should switch to slave!

86:

[root@localhost zk_client]# ./zk_client
create node /services, ret=-110
str[0]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473624547276
master server=192.168.1.62:9044, timeus=1632473624547276
should switch to slave!
zookeeper connected!
require_wachter() : type=4, stat=3, path=/services
set [/services/192.168.1.86:9044]=[1632473592590648] succeed!
str[0]:192.168.1.86:9044
/services/192.168.1.86:9044=1632473592590648
str[1]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473624547276
master server=192.168.1.86:9044, timeus=1632473592590648
should switch to master!
enter switch func
require_wachter() : type=4, stat=3, path=/services
str[0]:192.168.1.86:9044
/services/192.168.1.86:9044=1632473592590648
str[1]:192.168.1.85:9044
/services/192.168.1.85:9044=1632473596504658
str[2]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473624547276
master server=192.168.1.86:9044, timeus=1632473592590648
should switch to master!
enter switch func

85:

[root@localhost zk_client]# ./zk_client
create node /services, ret=-110
str[0]:192.168.1.86:9044
/services/192.168.1.86:9044=1632473592590648
str[1]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473624547276
master server=192.168.1.86:9044, timeus=1632473592590648
should switch to slave!
zookeeper connected!
require_wachter() : type=4, stat=3, path=/services
set [/services/192.168.1.85:9044]=[1632473596504658] succeed!
str[0]:192.168.1.86:9044
/services/192.168.1.86:9044=1632473592590648
str[1]:192.168.1.85:9044
/services/192.168.1.85:9044=1632473596504658
str[2]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473624547276
master server=192.168.1.86:9044, timeus=1632473592590648
should switch to slave!

86为主机。

关闭62后:

85切换为主机

require_wachter() : type=4, stat=3, path=/services
str[0]:192.168.1.85:9044
/services/192.168.1.85:9044=1632473768385849
str[1]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473810040201
master server=192.168.1.85:9044, timeus=1632473768385849
should switch to master!
enter switch func

zookeeper c api主备切换例子相关推荐

  1. Namenode主备切换或报 IPC Server handler 23 on 8020

    转自:http://blog.csdn.net/u014033218/article/details/75570313 可能是以下原因,未测试: NameNode 高可用整体架构概述 在 Hadoop ...

  2. MySQL 集群(三):MySQL + Mycat 实现读写分离,主备切换集群

    MySQL 集群(三):MySQL + Mycat 实现读写分离,主从切换集群 下载 Mycat Mycat 主要文件 端口 Mycat 命令 配置文件 server.xml schema.xml 配 ...

  3. vrrp路由器三种状态_VRRP路由器切换方法、路由器、VRRP主备切换系统及存储介质与流程...

    本发明涉及虚拟路由冗余协议(VRRP)技术领域,尤其涉及一种VRRP路由器切换方法.路由器.VRRP主备切换系统及存储介质. 背景技术: 虚拟路由冗余协议(Virtual Router Redunda ...

  4. nginx+tomcat实现主备切换

    一.准备工作 1.nginx安装 1.1.准备工作 选首先安装这几个软件:GCC,PCRE(Perl Compatible Regular Expression),zlib,OpenSSL. Ngin ...

  5. 在三台Redis节点上部署哨兵集群以及主备切换、故障恢复的容灾演练中哨兵各自的日志信息、状态查看分析

    1. 创建哨兵的配置文件 先在 /etc 目录创建一个sentinel目录作为哨兵的配置信息存放目录,并将Redis安装目录的sentinel.conf文件(我这边路径是 /usr/local/red ...

  6. oracle adg切换原理,oracle11g ADG主备切换

    oracle11g ADG主备切换 1.主库 SQL> select name,open_mode,switchover_status from v$database; NAME OPEN_MO ...

  7. Spark之Master主备切换机制原理

    Spark之Master主备切换机制原理

  8. 《MySQL——基于位点orGTID的主备切换协议》

    一主多从的设置,用于读写分离,主库负责所有的写入和一部分读,其他读请求则由从库分担. 一主多从架构下,主库故障后的主备切换问题.相比于一主一备,多了从库指向新主库的过程. 基于位点的主备切换同步 把节 ...

  9. 《MySQL——主备切换流程与主备延迟》

    目录 主备切换 主备延迟的原因 可靠性优先策略的主备切换流程 可用性优先策略的主备切换流程 主备切换 主备切换分为主动运维与被动操作. 软件升级.主库所在机器按计划下线为主动运维. 主库所在机器掉电为 ...

最新文章

  1. jQuery.click()与onClick
  2. Java中int转Double再转换成百分数并应用在求同比昨日增长率
  3. HttpClient 学习整理
  4. flex java类转成_Flex 与 java 通讯 【转】
  5. Java 8系列之重新认识HashMap(转载自美团点评技术团队)
  6. 微信小程序------MD5加密(支持中文和不支持中文)和网络请求(get和post)
  7. layui轮播图切换会有跳动_Layui中轮播图切换函数说明
  8. JEECG Excel 介绍篇
  9. linux apache支持ipv6,如何在Nginx和Apache中启用IPv6?
  10. 江湖传说——阿里巴巴土话102句完整版
  11. c语言小游戏跳一跳代码及注释,c语言小游戏程序之弹跳小球的实现代码
  12. 听说你也想修改IP归属地?
  13. 用生成对抗网络给雪人上色,探索人工智能时代的美学
  14. OKR-Periods of Words
  15. 招银网络 Java后端面经
  16. 防火墙服务器搭建与应用(1.0)
  17. docker占用磁盘空间太大的解决办法
  18. 机器学习笔记(三)—— 二向箔(从PCA到SVD)
  19. 初学者第一个JavaWeb项目实战【附源码】
  20. pandas数据上采样

热门文章

  1. 基于Adobe LCDS产品的数据访问解决方案Part3
  2. 用python写 祝你生日快乐英文_祝你生日快乐的英文怎么写
  3. stata实操|从国泰安到stata数据集以及初步的数据处理
  4. win7系统计算机在哪里打开,win7摄像头怎么打开 win7系统摄像头在哪
  5. vim 光标快速移动技巧总结(vim高级操作的基础)from csdner 亓磊
  6. 壁布接缝压条_教你2招搞定墙布毛边翘边
  7. 一款很实用的欠压过压保护电路
  8. 生物信息学在线服务器,生物信息学杂志
  9. x1计算机价格,除了不靠谱的售价,X1 Carbon 是一台完美的 ThinkPad
  10. 网页文字复制的几种方法