首页 > 数据库 >Golang基于Mysql分布式锁实现集群主备

Golang基于Mysql分布式锁实现集群主备

时间:2023-02-26 00:33:47浏览次数:37  
标签:return nil err ret Golang Master Mysql 主备 gorm

背景

集群中如果需要主备,可以基于Redis、zk的分布式锁等实现,本文将介绍如何利用Mysql分布式锁进行实现。

原理

  • 数据库中包含数据字段(此处为Master的主机名)、版本号和上一次更新时间。
  • Master不断上传自己的心跳,即刷新数据库中的"更新时间"。
  • 上一次更新时间超过了一定时间,则认为Master已Down,则可以抢Master。
  • 抢Master和更新心跳时,版本号+1,要判断版本号是否与上一次读取的数据相同。如果相同,则修改成功。如果不相同,则说明Master已经被其他主机抢走。

数据库建表

  • master存放主机名
CREATE TABLE `host_master` (
  `id` int NOT NULL AUTO_INCREMENT,
  `master` varchar(64) NOT NULL COMMENT '主机名',
  `version` int COMMENT '版本号',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '保存数据时间,自动生成',
  PRIMARY KEY (`id`)
)
 ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into host_master(master,version) value('',0);    //插入一条空数据

Golang实现集群主备

package main

import (
    "errors"
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
    "os"
    "time"
)
var (
    DB *gorm.DB
    curHost = "2"
    healthTime float64    = 10    //上传心跳的周期
    healthTimeout float64 = 30    //健康检查过期时间
)
type HostMaster struct {
    ID         int64     `gorm:"column:id"`
    Master     string    `gorm:"column:master"`      //  主机名
    Version    int64     `gorm:"column:version"`     //  版本号
    UpdateTime *time.Time `gorm:"column:update_time"` //  保存数据时间,自动生成
}
//初始化数据库
func InitDB()error{
    var err error
    DB, err = gorm.Open("mysql", "root:123456@(192.168.191.128:3306)/test?charset=utf8&parseTime=True&loc=Local")
    if err != nil {
        return err
    }
    DB.SingularTable(true)
    return nil
}
//获取Master的信息
func GetMasterInfo()(HostMaster,error){
    var hostMasters []HostMaster
    ret := DB.Find(&hostMasters)
    if ret.Error!=nil{
        return HostMaster{},ret.Error
    }
    if ret.RowsAffected==0 || ret.RowsAffected>1{
        return HostMaster{},errors.New(fmt.Sprintf("HostMaster表中的条目为%d",ret.RowsAffected))
    }
    return hostMasters[0],nil
}
//抢Master与更新心跳
func GrabMaster()error{
    //获取Master的信息
    hostMaster,err := GetMasterInfo()
    if err!=nil{
        return err
    }
    //当前主机为Master则更新心跳.或Master已down则抢Master
    if hostMaster.Master==curHost || time.Now().Sub(*hostMaster.UpdateTime).Seconds()>healthTimeout{
        ret := DB.Model(&HostMaster{}).Where("version = ?",hostMaster.Version).Updates(map[string]interface{}{"master":curHost,"version":hostMaster.Version+1})
        if ret.Error!=nil{
            return errors.New("修改失败: "+ret.Error.Error())
        }
        if ret.RowsAffected==0{
            return nil
        }else{
            if hostMaster.Master==curHost{
                fmt.Println(curHost+"更新了心跳")
            }else{
                fmt.Println(curHost+"抢Master成功")
            }
        }
    }
    return nil
}
func main() {
    //初始化数据库
    err := InitDB()
    if err!=nil{
        fmt.Println(err)
        os.Exit(1)
    }
    //周期性更新心跳和抢Master
    go func(){
        for{
            err := GrabMaster()
            if err!=nil{
                fmt.Println(err)
            }
            time.Sleep(10*time.Second)
        }
    }()
    select {}
}




郭少

标签:return,nil,err,ret,Golang,Master,Mysql,主备,gorm
From: https://www.cnblogs.com/NetRookieX/p/17155778.html

相关文章

  • 7.mysql索引失效
       失效的七字口诀:模型数空运最快模:模糊查询以%开始索引失效;型:数据类型转换函数:函数的索引空:索引列为空不走索引,运:对索引列进行加减乘除会失效最:不按聚合索......
  • pymysql操作
    1、首相导入模块pymysql importpymysql2、创建连接 conn=pymysql.connect( host='远程数据库IP地址', port=远程数据库端口, user='数据库账号', password......
  • 为什么在连接mysql时,设置 SetConnMaxIdleTime 没有作用
    目录测试1go1.15.15go1.17.12测试2go1.15.15go1.17.12参考在使用golang连接mysql时,为了节省连接资源,在连接使用过后,希望在指定长度时间不再使用后,自动关闭连接。这......
  • mysql描述关键字
    SHOWCOLUMNS要求给出一个表名(这个例子中的FROMtab_1),它对每个字段返回一行,行中包含字段名、数据类型、是否允许NULL、键信息、默认值以及其他信息。   另外可以......
  • 908~909Maven工程环境修改,Maven的Java工程取mysql数据库数据
    Maven工程环境修改<plugins><plugin><!--https://mvnrepository.com/artifact/org.apache.tomcat.maven/tomcat7-maven-plugin-->......
  • MySQL学习笔记-数据控制语言
    SQL-数据控制语言(DCL)DCL语句用于管理数据库用户,控制数据库的访问权限一.管理用户1.查询用户#访问mysql数据库usemysql;#查询user表select*fromuser;主......
  • PyMySQL删除
    title:PyMySQL删除author:杨晓东permalink:PyMySQL删除date:2021-10-0211:27:04categories:-投篮tags:-demoPyMySQLMySQL数据库_删除"""1、删除操作......
  • MYSQL的索引、并发控制、各种事务介绍以及日志管理
    今天分享的是mysql数据库中的索引、并发控制、各种事务介绍以及日志管理,在学习过程中对这些内容的理解INDEX索引索引介绍索引:是排序的快速查找的特殊数据结构,定义作为查找......
  • 三天吃透MySQL八股文(2023最新整理)
    本文已经收录到Github仓库,该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校......
  • golang中的close函数
    close函数是用于关闭通道的。官方解释(摘自close函数源代码注释):Theclosebuilt-infunctionclosesachannel,whichmustbeeitherbidirectionalorsend-only.Itsho......