zookeeper,已经被很多人所熟知,主要应用场景有(数据订阅/发布 ,负载均衡, 命名服务, 分布式协调/通知,集群管理,Master选举,分布式锁,分布式队列)。

C接口的描述  主要参考 Haippy 的文章 :Zookeeper C API 指南 (感谢大神)

但是网上的C++版 示例代码少之又少,作为一个小白,自己摸索,给大家参考。

Master选举的需求主要如下:

1.多台机器同时进行选举,产生唯一的一台机器作为Master,其它的机器作为slave。

2.当Master宕机后,需要在所有存活的slave中再次选举一个成为新的Master。

3.当新的master宕机后,继续选举,如此反复。

这样保证了在大多数分布式系统中Master不会宕机。在这里我们默认zookeeper是高可用的。(即不考虑zookeeper失效。)

思路主要如下:

1.每个进程都会去创建一个临时文件(名为master,该文件里面的值为master的ip地址),zookeeper将会保证那么多的进程只有一个进程能够创建成功。收到ZOK,其它的都会收到ZNODEEXISTS(已存在)。

2.没有创建成功的节点slave节点将会去监视这个已经创建成功的“文件”(master) ,当该文件发生变化时,slave将会触发相对应的函数。

临时文件:为ZOO_EPHEMERAL类型,正如 EPHEMERAL(短暂的)本意,当创建这个文件的进程挂了,zookeeper会自动检测到(正是利用这个特性)。

变化: 这个变化有很多种可能,如该文件的内容变了,该文件下的子文件增加或减少了,(在zookeeper中文件既是文件又是一个文件夹),也可能是该文件被删除了。

值的一提的是,如Haippy所述,zookeeper watch函数是 “一次性”的,简单的说  小明 调用了watch观察 自己家的门。 此时,小红打开了门,watch函数立刻告诉了小明,小明就过去把门关了。这个时候如果小明没有再次调用watch函数,小红再偷偷的开门,小明是不知道的,讲了那么啰嗦其实就是一句话“每次触发watch函数后,请别忘记再次调用watch函数”(当然还是要看具体的场景)。

下面贴上代码(所有的解释都写在代码注释中): 编译命令为   g++ election.cpp -o election -lzookeeper_mt -std=c++11  (不是-lzookeeper_st 否则一点反应都没)

 /*
* =============================================================================
*
* Filename: election.cpp
*
* Description: elect master test by zookeeper
*
* Created: 02/15/2013 08:48:49 PM
*
* Author: zhejiangxiaomai, 358088534@qq.com
* Company: ECNU
*
* =============================================================================
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zookeeper/zookeeper.h>
#include <zookeeper/zookeeper_log.h>
#include <iostream>
using namespace std; int status = -;
// 1 : master 0 :slave
zhandle_t* init(const char* host, int timeout);
void init_1(zhandle_t* zh, int type, int state, const char* path, void* watcherCtx);
void getResult(int rc, const char *name, const void *data);
void go_to_election(zhandle_t* zh, int type, int state, const char* path, void* ip);
void get_master(int rc, const char *value, int value_len, const struct Stat *stat, const void *data);
void watch_master(zhandle_t* zh, const char* ip); int main(int argc, const char *argv[])
{
const char* host = "127.0.0.1:2181";
int timeout = ;
zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);
const char* ip = argv[];
//初始化连接句柄
zhandle_t* zh = init(host, timeout);
//参加选举
go_to_election(zh,,,"/master",(void *) ip);
//按下空格即可清除句柄,退出程序
getchar();
zookeeper_close(zh);
return ;
}
//创建连接zookeeper的句柄
zhandle_t* init(const char* host, int timeout){
zhandle_t* zkhandle = zookeeper_init(host,init_1,timeout, , NULL, );
if (zkhandle == NULL) {
fprintf(stderr, "Error when connecting to zookeeper servers...\n");
exit(EXIT_FAILURE);
}
return zkhandle;
}
//做为创建句柄的watch函数(一般输出句柄的信息,但是我没有处理)
void init_1(zhandle_t* zh, int type, int state, const char* path, void* watcherCtx)
{
std::cout<<"init handler"<<endl;
}
//参选函数
void go_to_election(zhandle_t* zh, int type, int state, const char* path, void* ip)
{
//创建一个/master文件,值为char* 类型的IP,长度为15,
//该文件为类型为ZOO_EPHEMERAL,当创建完成后会调用getResult函数
int ret = zoo_acreate(zh, "/master", (char*)ip, ,
&ZOO_OPEN_ACL_UNSAFE, ZOO_EPHEMERAL,
getResult, "election");
if (ret) {
fprintf(stderr, "Error %d for %s\n", ret, "election");
exit(EXIT_FAILURE);
}
//此处sleep一秒,没有这个步骤程序就没有效果,
//我认为是create没有那么快,没有创建完成的watch就没有意义。
sleep();
if(status == )
{
//如果是slave就观察master
watch_master(zh, (const char*)ip);
}
}
//判断创建结果,结果保存在rc中,并改变状态。
//在此看起来其他参数没有用到,但是这是七种回调函数的一种格式,需要遵守。
void getResult(int rc, const char *name, const void *data)
{
switch(rc){
case ZOK:
std::cout<<"Become master"<<endl;
status = ;
break;
case ZNODEEXISTS:
std::cout<<"Become slave, keep watch"<<endl;
status = ;
break;
}
}
//在此仅仅是将master文件的值输出.
void get_master(int rc, const char *value, int value_len,
const struct Stat *stat, const void *data){
std::cout<<(char *)data<<(char*)value<<endl;
} void watch_master(zhandle_t* zh, const char* ip){
//获取/master文件的值 通过回调函数 get_master. 当该文件发生改变时带着自己的ip地址重新去注册
int ret = zoo_awget(zh, "/master",go_to_election,(void *)ip ,
get_master,"get master ip :");
if (ret) {
fprintf(stderr, "Error %d for %s\n", ret, "re");
exit(EXIT_FAILURE);
}
}

实现结果图:(master从0.1 变为了0.2 变为了0.3)

使用zookeeper实现分布式master选举(c 接口版本)的更多相关文章

  1. Zookeeper实现Master选举(哨兵机制)

    master选举使用场景及结构 现在很多时候我们的服务需要7*24小时工作,假如一台机器挂了,我们希望能有其它机器顶替它继续工作.此类问题现在多采用master-salve模式,也就是常说的主从模式, ...

  2. zookeeper java代码实现master 选举

    1,master选举使用场景及结构 现在很多时候我们的服务需要7*24小时工作,假如一台机器挂了,我们希望能有其它机器顶替它继续工作.此类问题现在多采用master-salve模式,也就是常说的主从模 ...

  3. zookeeper典型应用场景之一:master选举

    对于zookeeper这种东西,仅仅知道怎么安装是远远不够的,至少要对其几个典型的应用场景进行了解,才能比较全面的知道zk究竟能干啥,怎么玩儿,以后的日子里才能知道这货如何能为我所用.于是,有了如下的 ...

  4. ZooKeeper场景实践:(6)集群监控和Master选举

    1. 集群机器监控 这通经常使用于那种对集群中机器状态,机器在线率有较高要求的场景,可以高速对集群中机器变化作出响应.这种场景中,往往有一个监控系统,实时检測集群机器是否存活. 利用ZooKeeper ...

  5. org.apache.curator:master选举和分布式锁

    1. master选举(LeaderSelector) 1)LeaderSelector构造函数 在leaderPath上建立分布式锁:mutex = new InterProcessMutex(cl ...

  6. Zookeeper实现master选举

    使用场景         有一个向外提供的服务,服务必须7*24小时提供服务,不能有单点故障.所以采用集群的方式,采用master.slave的结构.一台主机多台备机.主机向外提供服务,备机负责监听主 ...

  7. Zookeeper系列五:Master选举、ZK高级特性:基本模型

    一.Master选举 1. master选举原理: 有多个master,每次只能有一个master负责主要的工作,其他的master作为备份,同时对负责工作的master进行监听,一旦负责工作的mas ...

  8. zookeeper【4】master选举

    考虑7*24小时向外提供服务的系统,不能有单点故障,于是我们使用集群,采用的是Master+Slave.集群中有一台主机和多台备机,由主机向外提 供服务,备机监听主机状态,一旦主机宕机,备机必需迅速接 ...

  9. ZooKeeper 典型应用场景-Master选举

    master选举 1.使用场景及结构 现在很多时候我们的服务需要7*24小时工作,假如一台机器挂了,我们希望能有其它机器顶替它继续工作.此类问题现在多采用master-salve模式,也就是常说的主从 ...

随机推荐

  1. 浏览器使用ActiveX控件

    在IE中使用ActiveX控件,需要使用HTML中的标志是<OBJECT>,该标记几个重要的参数特性有:1.ID:为控件提供一个标识名称,为HTML代码提供一种访问该控件的入口.2.CLA ...

  2. Web service是什么?(转)

    我认为,下一代互联网软件将建立在Web service(也就是"云")的基础上. 我把学习笔记和学习心得,放到网志上,欢迎指正. 今天先写一个最基本的问题,Web service到 ...

  3. Winform下实现图片切换特效的方法

    本文实例讲述了Winform下实现图片切换特效的方法,是应用程序开发中非常实用的一个功能.分享给大家供大家参考之用.具体方法如下: 本实例源自网络,功能较为齐全.丰富!主要功能代码如下: using ...

  4. JSON特殊字符处理

    JSON 是适用于 Ajax 应用程序的一种有效格式,原因是它使 JavaScript 对象和字符串值之间得以快速转换.由于 Ajax 应用程序非常适合将纯文本发送给服务器端程序并对应地接收纯文本,相 ...

  5. struts2与cookie实现自动登录和验证码验证

    主要介绍struts2与cookie结合实现自动登录 struts2与cookie结合时要注意采用.action 动作的方式实现cookie的读取 struts2的jar包 链接数据库文件 db.pr ...

  6. 1.4.2 solr字段类型--(1.4.2.7)字段属性使用案例

    1.4.2 solr字段类型 (1.4.2.1) 字段类型定义和字段类型属性. (1.4.2.2) solr附带的字段类型 (1.4.2.3) 使用货币和汇率 (1.4.2.4) 使用Dates(日期 ...

  7. Java Hashtable类

    哈希表(Hashtable)是原来的java.util中的一部分,是一个字典的具体实现. 然而,Java2重新设计的哈希表,以便它也实现了​​Map接口.因此,哈希表现已集成到集合框架.它类似于Has ...

  8. Android 高级UI设计笔记14:Gallery(画廊控件)之 3D图片浏览

    1. 利用Gallery组件实现 3D图片浏览器的功能,如下: 2. 下面是详细的实现过程如下: (1)这里我是测试性代码,我的图片是自己添加到res/drawable/目录下的,如下: 但是开发中不 ...

  9. Redis缓存异常的容错实现方法( .net)

    using DotNet.Log; /// <summary> /// Redis缓存辅助类 /// /// 修改纪录 /// /// 2015-10-26 版本:1.0 SongBiao ...

  10. C#使用简单邮件传输协议(SMTP)发送邮件

    1.首先引入命名空间: using System.Net.Mail; 2.定义邮件配置类: public class EmailServiceConfig { /// <summary> ...