继承CZookeeperHelper即可快速实现主备切换:

https://github.com/eyjian/libmooon/blob/master/include/mooon/net/zookeeper_helper.h

zookeeper的ZOO_EPHEMERAL节点(如果ZOO_EPHEMERAL满足不了需求,可以考虑和ZOO_SEQUENCE结合使用),在会话关闭或过期时,会自动删除,利用这一特性可以实现两个或多节点间的主备切换。

实现方法:
1)在进程启动时调用zookeeper_init()初始化:
bool X::init_zookeeper()
{
    // 第一次调用时_clientid总是为NULL,
    // 状态为ZOO_EXPIRED_SESSION_STATE时,需要重新调用zookeeper_init,
    // 这个时候可传入的_clientid为前一次zookeeper_init()产生的_clientid

// 请注意zookeeper_init()是一个异步调用,返回非NULL并不表示会话建立成功,
    // 只有当zk_watcher中的type为ZOO_SESSION_EVENT和state为ZOO_CONNECTED_STATE时,
    // 才真正表示会话建立成功。
    _zhandle = zookeeper_init(zk_hosts, zk_watcher, 5000, _clientid, this, 0);
    if (NULL == _zhandle)
    {
        MYLOG_ERROR("init zookeeper failed: %s\n", zerror(errno));
        return false;
    }

MYLOG_INFO("init zookeeper(%s) successfully\n", zk_hosts);
    return true;
}

2)进入工作之前,先尝试切换成主,只有成功切换成主后才进入work
bool X::run()
{
    while (true)
    {
        int num_items = 0;
        // 备机最简单的方法是每隔一定时间,如1秒就尝试转成master,
        // 如果不使用轮询,则可以采用监视_zk_path的方式
        mooon::sys::CUtils::millisleep(1000);

// 如果不是master,则尝试转成master,如果转成不成功则继续下一次尝试
        if (!is_master() && !change_to_master())
            continue;

do_work();
    }
}

bool X::is_master() const
{
    return _is_master;
}

bool X::change_to_master()
{
    static uint64_t log_counter = 0; // 打log计数器,备状态时的日志输出

// ZOO_EPHEMERAL|ZOO_SEQUENCE
    // _myip为本地IP地址,可以通过它来判断当前谁是master
    // _zk_path值示例:/master/test,注意需要先保证/master已存在
    int errcode = zoo_create(_zhandle, _zk_path.c_str(), _myip.c_str(), _myip.size()+1, &ZOO_OPEN_ACL_UNSAFE, ZOO_EPHEMERAL, NULL, 0);

// (-4)connection loss,比如为zookeeper_init()指定了无效的hosts(一个有效的host也没有)
    if (errcode != ZOK)
    {
        _is_master = false;

// 减少为备状态时的日志输出
        if (0 == log_counter++ % 600)
        {
            MYLOG_DEBUG("become master[%s] failed: (%d)%s\n", _zk_path.c_str(), errcode, zerror(errcode));
        }

return false;
    }
    else
    {
        _is_master = true;
        log_counter = 0;
        MYLOG_INFO("becase master[%s]\n", _zk_path.c_str());

// sleep一下,以便让原master正在进行的完成
        mooon::sys::CUtils::millisleep(2000);
        return true;
    }
}

3)当zookeeper会话成功建立或过期时均会触发zk_watcher,可通过type和state来区分
void zk_watcher(zhandle_t *zh, int type, int state, const char *path, void *context)
{
    X* x = static_cast<X*>(context);
    MYLOG_DEBUG("zh=%p, type=%d, state=%d, context=%p, path=%s\n", zh, type, state, context, path);

// zookeeper_init成功时type为ZOO_SESSION_EVENT,state为ZOO_CONNECTED_STATE
    if ((ZOO_SESSION_EVENT == type) && (ZOO_CONNECTED_STATE == state))
    {
        x->on_zookeeper_connected(path);
    }
    else if ((ZOO_SESSION_EVENT == type) && (ZOO_EXPIRED_SESSION_STATE == state))
    {
        // 需要重新调用zookeeper_init(),简单点可以退出当前进程重启
        x->on_zookeeper_expired();
    }
}

附: zookeeper日志
默认情况下zookeeper日志是输出到stderr,但可以通过zoo_set_log_stream()来定向到自己的日志输出中,还可以使用zoo_set_debug_level()来控制zookeeper的日志级别。

基于zookeeper的主备切换方法的更多相关文章

  1. Zookeeper C++编程实战之主备切换

    默认zookeeper日志输出到stderr,可以调用zoo_set_log_stream(FILE*)设置输出到文件中还可以调用zoo_set_debug_level(ZooLogLevel)控制日 ...

  2. Spark系列(五)Master主备切换机制

    Spark Master主备切换主要有两种机制,之中是基于文件系统,一种是基于Zookeeper.基于文件系统的主备切换机制需要在Active Master挂掉后手动切换到Standby Master ...

  3. 大话Spark(7)-源码之Master主备切换

    Master作为Spark Standalone模式中的核心,如果Master出现异常,则整个集群的运行情况和资源都无法进行管理,整个集群将处于无法工作的状态. Spark在设计的时候考虑到了这种情况 ...

  4. 在Windows Azure上配置VM主备切换(1)——Linux篇

    对任何一个上线系统来说,高可用设计是不可或缺的一个环节,这样才可以确保应用可以持续.稳定的运行,而不是频繁的掉线.停机.高可用设计的核心思路很简单,就是消除一切单点故障,将单点链路或者节点升级为多点. ...

  5. (摘)DataGuard物理standby管理 - 主备切换

    DataGuard物理standby管理 - 主备切换 Dataguard的切换分为两种,switchover和failover. switchover一般用于数据库或硬件升级,这时只需要较短时间中断 ...

  6. MySQL 复制 - 性能与扩展性的基石 4:主备切换

    一旦使用 MySQL 的复制功能,就很大可能会碰到主备切换的情况.也许是为了迭代升级服务器,或者是主库出现问题时,将一台备库转换成主库,或者只是希望重新分配容量.不过出于什么原因,都需要将新主库的信息 ...

  7. f5主备切换演练

    1.准备工作: 1)保证主备机同步 2)备份主备机配置 2.切换:所有操作均在主机 方法1:shutdown主机上联的核心交换机的端口: 此方法在主备切换过程中会丢1个包 方法2:命令行下reboot ...

  8. Postgres主备切换

    主备查询 主备不会自动切换(即需要实现线上环境主数据库宕掉之后,从数据库能够自动切换为主数据库,需要借用第三方软件,例如heartbeat等) (1)如何查看是primary还是standby 方法1 ...

  9. 小记--------spark的Master主备切换机制原理分析及源码分析

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABfEAAAJwCAYAAAAp7ysfAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjw

随机推荐

  1. 本地Facts

    我们可以通过Facts来获取目标主机的系统信息,当这些信息还不能满足我们的功能需要时,可以通过编写自定义的Facts模块来实现.当然,还有一个更简单的实现方法,就是通过本地Facts来实现.只需在目标 ...

  2. Haskell语言学习笔记(22)MaybeT

    Monad Transformers Monad 转换器用于将两个不同的Monad合成为一个Monad.Monad 转换器本身也是一个 Monad. MaybeT MaybeT 这个 Monad 转换 ...

  3. Java静态初始化,实例初始化以及构造方法

    首先有三个概念需要了解: 一.静态初始化:是指执行静态初始化块里面的内容. 二.实例初始化:是指执行实例初始化块里面的内容. 三.构造方法:一个名称跟类的名称一样的方法,特殊在于不带返回值. 我们先来 ...

  4. 扩展C#与元编程(二)

    如果你对Windows Workflow Foundation(WF)一无所知,当看到扩展C#与元编程(一)中由MW编译器生成的FirstLook.mw.cs时,也许这么在想:我KAO,这是C#版的汇 ...

  5. 疯狂JAVA——第三章 数据类型和运算符

    3.1注释 1.单行注释 2.多行注释 3.文档注释——文档注释以斜线后紧跟两个星号(/**)开始,以星号后紧跟一个斜线结束(*/),中间部分都是文档注释,会被提取到API文档中. API文档类似于产 ...

  6. innerText 与textContent区别

    两者都是可以过滤html元素 innerText 获取内容 换行会有L类似特殊符号 textContent 没有

  7. Hive—简单窗口分析函数

    hive 窗口分析函数 : jdbc:hive2:> select * from t_access; +----------------+---------------------------- ...

  8. VS文件发布不了,这样设置可以解决

    在VS里面新增一些文件的时候,往往发布的时候会发布不了,比如:(*.rdlc,*.p12).在项目里面,这些项目已经包含在项目里了,但是发布后,会发现这些文件并没有被发布出来 解决办法:邮件选择文件, ...

  9. django通过url传递参数(编辑操作页面)

    在做到编辑部分时,想到的办法是在编辑上跳转到页面时给他一个包含唯一标识id的url,然后通过这个url中的id去查询出该条数据,将数据内容显示在编辑页面.   1.编辑按钮 <button on ...

  10. x86汇编知识点汇总

    目录: 1.进制转换 2.原码.反码.补码 3.寄存器 4.存储器的段结构 5.堆栈 6.传送类指令 7.算术运算类指令(不含乘除) 8.位操作类指令 9.标志位操作指令 10.标识符.常量与变量 1 ...