Zookeeper

 

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 <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zookeeper.h>

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<strings.count; i++ )
    {
        if( strcmp( myid,strings.data[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

 

 

你可能感兴趣的:(c,主备切换,zoookeeper)