利用redis实现选举

通常情况下, 选举会使用etcd专门的数据库。但是如果已经有redis服务器下,为了减少依赖,也可以使用redis实现。

定义结构, 存放一些配置东西
type Election struct {
    // 连接 redis 客户端, 其他能实现锁的公共存储也行
    Connect   *services.Redis
    runUid    string // 进程唯一id
    key       string // 队列名称
    isRunNode bool
    lockTime  int
    awakens   []interface{}
}
定义监控循环
func (k *Election) Run() {
    // 标识当前节点抢到执行权利
    for !k.check() {
        time.Sleep(time.Duration(k.lockTime) * time.Second)
    }
    // 执行节点才可以走下去,循环闭包函数执行它
    for _, awaken := range k.awakens {
        switch awaken.(type) {
        case func():
            awaken.(func())()
        default:
            log.Warning("选举后才启动的参数, 请传入闭包")
        }
    }
}
抢夺锁和保持心跳
func (k *Election) check() bool {
    if k.isRunNode {
        return true
    }

    // 沉默节点, 尝试检查runNode是否死机, 抢夺执行权利
    ctx := context.Background()
    ok := k.Connect.Client.SetNX(ctx, k.key, k.runUid, time.Duration(k.lockTime+10)*time.Second)

    if ok.Val() {
        k.isRunNode = true
        // 设置一个保持心跳的循环
        go func() {
            ex := time.Duration(k.lockTime) * time.Second
            for range time.Tick(ex) {
                k.Connect.Client.Expire(context.Background(), k.key, time.Duration(k.lockTime+10)*time.Second)
            }
        }()
        machine, _ := os.Hostname()
        log.Info(machine + " 通过了选举")
        return true
    } else {
        k.isRunNode = false
        return false
    }
}
启动
e := Election{/* TODO 设置 awakens = func ... */}
e.Run()
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!