Zookeeper是一个高性能,分布式的,开源分布式应用协调服务。它提供了简单原始的功能,分布式应用可以基于它实现更高级 的服务,比如同步,配置管理,集群管理,名空间。
集群搭建
zookeeper集群组建需最少提供3台服务器,其中一台充当leader,负责写和数据同步,剩下的为follower,提供读服务。
数据存储
zookeeper数据以key,value方式存储,key表现为分层的文件系统目录树结构。
节点类型
zookeeper有四种类型节点
1. PERSISTENT 永久性节点,创建后一直存在
2. EPHEMERAL 临时节点,客户端创建后,若退出,则移除。可用于检测服务器是否存在
3. SEQUENTIAL 序列节点,与1,2配合使用,创建节点序号会不断增长,可用于实现主备切换。最先注册的节点序号值最小,后注册的节点序号会增加,选择序号值最小的节点作为主机。
接口
zookeeper提供了java,C两种语言的绑定。C接口提供了单线程和多线程版本,添加_THREADED调用多线程版本库。
C版本主备切换实现:
#include#include #include #include #include void WatchEvent( zhandle_t *zh,int type,int state,const char *path,void *ctx ); void GetNodeId( const char *buf ); void CheckLeader(); zhandle_t *zh = NULL; char myid[10] = {}; char buf[210] = {}; /// 系统入口 int main(int argc,char **argv) { zoo_set_debug_level( ZOO_LOG_LEVEL_ERROR ); // API具有重连机制 zh = zookeeper_init( "127.0.0.1:2181,127.0.0.1:2182", // 集群服务以,分隔 WatchEvent, 10000, 0, NULL, 0 ); // 注册节点 char buf[100]; int rc = zoo_create( zh, "/servers/member", // 节点前缀,成功后member-00000000001 "0", 1, &ZOO_OPEN_ACL_UNSAFE, ZOO_SEQUENCE|ZOO_EPHEMERAL, buf, sizeof(buf) - 1 ); if( rc != ZOK ) { printf( "zoo:create %d\n",rc ); return 1; } // 获取节点ID GetNodeId( buf ); CheckLeader(); // 监控主备节点 struct String_vector strings; rc = zoo_wget_children( zh, "/servers", // 父目录 WatchEvent, NULL, &strings ); while(1) sleep(1); return 0; } // 获取节点序号 void GetNodeId( const char *buf ) { const char *p = buf; int i = strlen(buf) - 1; for( ; i>=0; i-- ) { if(*(p+i) == '/') break; } strcpy( myid,p+i+1 ); return; } // 回调函数 void WatchEvent( zhandle_t *zh,int type,int state,const char *path,void *ctx ) { if( type == ZOO_SESSION_EVENT ) // 连接事件 { printf( "Connect Status:%d\n",state ); } else if( type == ZOO_CHILD_EVENT ) // 子节点事件 { // 节点变化,重新检测主备状态 CheckLeader(); // 重新监听 struct String_vector strings; zoo_wget_children( zh, "/servers", WatchEvent, ctx, &strings ); } } /// 检测主备机 void CheckLeader() { struct String_vector strings; int rc = zoo_get_children( zh,"/servers",0,&strings ); if( rc != ZOK ) { printf( "zoo:children %d\n",rc ); return; } // 只有主机 if( strings.count == 1 ) { printf("I'm Master\n"); return; } bool flag = true; // 比较最小的ID for( int i=0; i 0 ) { flag = false; } } if( !flag ) { printf("I'm Slave\n"); } }
编译:
g++ -g -o test2 test2.cpp \
-L/usr/local/lib -lzookeeper_mt \
-I/home/zookeeper/include \
-D_THREADED