细说Zookeeper选举的一个案例(下)

作者:ReganYue

来源:恒生LIGHT云社区

超细!细说Zookeeper选举的一个案例

今天我们来带着大家实现用Zookeeper实现选举的案例,帮助大家更好的学习Zookeeper。

六、判断是否连接Zookeeper

func (electionManager *ElectionManager) isConnected() bool {
    if electionManager.ZKClientConn == nil {
        return false
    } else if electionManager.ZKClientConn.State() != zk.StateConnected {
        return false
    }
    return true
}

在初始化Zookeeper连接时需要判断是否连接了Zookeeper,其实我们可以看连接是否为nil值来判断有没有连接,如果想判断连接是否有问题的话,我们最好用连接的State()方法,如果是zk.StateConnected,就表示连接成功了,如果是其他就表示连接异常,下面列举连接异常和成功的值。

StateUnknown           State = -1
StateDisconnected      State = 0
StateConnecting        State = 1
StateAuthFailed        State = 4
StateConnectedReadOnly State = 5
StateSaslAuthenticated State = 6
StateExpired           State = -112

StateConnected  = State(100)
StateHasSession = State(101)

可以看到,zk.StateConnected也就是100,所以这里可能可以将zk.StateConnected替换为100,我也不知道是否可行,你可以试一试~ StateUnknown也就是-1表示状态是未知的,StateDisconnected也就是0表示状态是未连接,其它我就不细说了。

七、选举的逻辑

func (electionManager *ElectionManager) Run() {
    err := electionManager.electMaster()
    if err != nil {
        fmt.Println(err)
    }
    electionManager.watchMaster()
}

是不是很眼熟,这就是main函数中开辟协程运行的东西——选举。

很简单,直接进行选举选出master,然后对master节点进行监听。

八、选举逻辑

func (electionManager *ElectionManager) electMaster() error {
    err := electionManager.initConnection()
    if err != nil {
        return err
    }
    isExist, _, err := electionManager.ZKClientConn.Exists(electionManager.ZKConfig.RootPath)
    if err != nil {
        return err
    }
    if !isExist {
        path, err := electionManager.ZKClientConn.Create(electionManager.ZKConfig.RootPath,
            nil, 0, zk.WorldACL(zk.PermAll))
        if err != nil {
            return err
        }
        if electionManager.ZKConfig.RootPath != path {
            return errors.New("创建的" + electionManager.ZKConfig.RootPath + " !=" + path)
        }
    }

    masterPath := electionManager.ZKConfig.RootPath + electionManager.ZKConfig.MasterPath
    
    path, err := electionManager.ZKClientConn.Create(masterPath, nil, zk.FlagEphemeral, zk.WorldACL(zk.PermAll))
    if err == nil {
        if path == masterPath {
            fmt.Println("选举master成功")
            electionManager.IsMaster <- true
        } else {
            return errors.New("创建的" + masterPath + "!=" + path)
        }
    } else {
        //创建master节点失败
        fmt.Println("选举master失败!", err)
        electionManager.IsMaster <- false
    }
    return nil
}

要开始选举,必须要先连接Zookeeper,我们编写的initConnection()进行连接zk并可以通过返回值来判断连接是否有问题。

然后判断zk中是否存在根目录,如果没有,就创建根目录,根目录一般数据先不设置,flags是为0,要创建持久化节点,权限不进行控制。

来介绍一下这个Create()叭~

Create()有四个参数,第一个是要创建的路径,第二个参数是节点中的数据内容,第三个参数是节点类型参数,flag=0表示这是一个持久化的节点,第四个参数是权限。有下面这些权限。

PermRead = 1 << iota
PermWrite
PermCreate
PermDelete
PermAdmin
PermAll = 0x1f

使用zk.WorldACL(zk.PermAll)表示该节点没有权限限制

然后再拼接master地址,创建master节点,因为需要创建个临时节点,所以Create()中的第三个参数参数使用zk.FlagEphemeral表示创建临时节点。创建成功,表示选举master成功,哪个客户端节点创建了master,认为是选举哪个节点作为master节点。

创建成功后要给连接的isMaster写入true,不成功则写入false。

九、监听Master节点

func (electionManager *ElectionManager) watchMaster() error {
    for {
    
        children, state, childCh, err := electionManager.ZKClientConn.ChildrenW(electionManager.ZKConfig.RootPath + electionManager.ZKConfig.MasterPath)
        if err != nil {
            fmt.Println("监听失败!", err)
        }
        fmt.Println("监听到子节点", children, state)
        select {
        case childEvent := <-childCh:
            if childEvent.Type == zk.EventNodeDeleted {
                fmt.Println("接收到znode的删除事件", childEvent)
                fmt.Println("开始选举新的master...")
                err = electionManager.electMaster()
                if err != nil {
                    fmt.Println("选举新的master失败", err)
                }
            }
        }

    }
}

需要监听zookeeper根节点下的子节点,因为如果连接断开或对应的子znode被删除,则触发重新选举,所以需要监听目录下所有子节点。

ChildrenW()会返回监听事件,如果监听到子节点被删除,也就是监听到的事件类型是zk.EventNodeDeleted,就重新调用electMaster()进行选举。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值