背景

集群中如果需要主备,可以基于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 {}
}

郭少

Golang基于Mysql分布式锁实现集群主备的更多相关文章

  1. KingbaseES R3 集群主备切换信号量(semctl)错误故障分析案例

    案例说明: 某项目KingbaseES R3 一主一备流复制集群在主备切换测试中出现故障,导致主备无法正常切换:由于bm要求,数据库相关日志无法从主机中获取,只能在现场进行分析:通过对比主备切换时的时 ...

  2. Redis集群主备模式部署

    网上有非常多用Ruby安装Redis-cluster的文章.可是在实际环境下不想安装Ruby,所以本文主要介绍了用Redis命令部署Redis集群.而且为集群中每个master实例添加一个slave实 ...

  3. Centos7.6部署k8s v1.16.4高可用集群(主备模式)

    一.部署环境 主机列表: 主机名 Centos版本 ip docker version flannel version Keepalived version 主机配置 备注 master01 7.6. ...

  4. 利用redis 分布式锁 解决集群环境下多次定时任务执行

    定时任务: @Scheduled(cron= "0 39 3 * * *") public void getAllUnSignData(){ //检查任务锁,若其它节点的相同定时任 ...

  5. Mysql基于Mysql Cluster+MysqlRouter的集群部署方案

    http://note.youdao.com/noteshare?id=a61c4a6ff2b76e5305430eb66eb116e2&sub=4B4B6E8D0E2849F9B0DFB67 ...

  6. (转)基于keepalived搭建MySQL的高可用集群

    基于keepalived搭建MySQL的高可用集群  原文:http://www.cnblogs.com/ivictor/p/5522383.html MySQL的高可用方案一般有如下几种: keep ...

  7. 【原】基于 HAproxy 1.6.3 Keeplived 在 Centos 7 中实现mysql mariadb galera cluster 集群分发读写 —— 上篇

    前言 有一段时间没有写blogs,乘着周末开始整理下haproxy + keeplived 实现 mysql mariadb galera cluster 集群访问环境的搭建工作. 本文集中讲hapr ...

  8. 1 构建Mysql+heartbeat+DRBD+LVS集群应用系统系列之DRBD的搭建

    preface 近来公司利润上升,购买了10几台服务器,趁此机会,把mysql的主从同步的架构进一步扩展,为了适应日益增长的流量.针对mysql架构的扩展,先是咨询前辈,后和同事探讨,准备采用Mysq ...

  9. 【分布式锁的演化】“超卖场景”,MySQL分布式锁篇

    前言 之前的文章中通过电商场景中秒杀的例子和大家分享了单体架构中锁的使用方式,但是现在很多应用系统都是相当庞大的,很多应用系统都是微服务的架构体系,那么在这种跨jvm的场景下,我们又该如何去解决并发. ...

  10. Ubuntu16.04.1上搭建分布式的Redis集群

    为什么要集群: 通常为了,提高网站的响应速度,总是把一些经常用到的数据放到内存中,而不是放到数据库中,Redis是一个很好的Cache工具,当然了还有Memcached,这里只讲Redis.在我们的电 ...

随机推荐

  1. IIncrementalGenerator 增量 Source Generator 生成代码入门 读取 csproj 项目文件的属性配置

    本文告诉大家如何在使用 IIncrementalGenerator 进行增量的 Source Generator 生成代码时,读取项目里的项目文件属性,从而实现为项目定制的逻辑.或者是读取 NuGet ...

  2. WPF 下拉框选项做鼠标 Hover 预览效果

    本文来告诉大家如何在 WPF 中,在 下拉框 ComboBox 里面,鼠标移动到 ComboBoxItem 上时,自动触发对应的事件,用来预览此选项值.例如我在实现一个颜色下拉框,此时我可以通过点击下 ...

  3. webpack调优技巧

    webpack优化主要有三个方面:1.提高构建速度,2.减少打包体积,3.优化用户体验 提高构建速度: 启用多线程 thread-loader 使用thread-loader插件可以启用多线程进行构建 ...

  4. SpringBoot实现WebSocket发送接收消息 + Vue实现SocketJs接收发送消息

    SpringBoot实现WebSocket发送接收消息 + Vue实现SocketJs接收发送消息 参考: 1.https://www.mchweb.net/index.php/dev/887.htm ...

  5. linux文本三剑客之grep及正则表达式详解

    linux文本三剑客之grep及正则表达式详解 目录 linux文本三剑客之grep及正则表达式详解 1. grep命令详解 2. 正则表达式 2.1 基本正则表达式 2.2 扩展正则表达式 1. g ...

  6. C语言:汉诺塔问题(Hanoi Tower)------递归算法

    汉诺塔问题是一个经典的问题.汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说.大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘.大梵天命令婆 ...

  7. C语言:ACLLIB图形库——如何搭建环境(附三个文件代码)

    看一下我配置完的运行结果: 1)首先创建一个项目. 2)选择win项目和C语言 3)然后找到你保存项目的文件夹里面拷贝两个.c和.h文件,两个文件代码我附在最后. 4)现在还不能用,找到项目属性 5) ...

  8. docker之docker-compose

    docker-compose就是个二进制的工具,它可以单机编排,批量管理多个容器 [root@mcwk8s01 harbor]# file /usr/local/bin/docker-compose ...

  9. snmpwalk命令详解

    snmp安装 yum -y install net-snmp-libs net-snmp net-snmp-utils 系统镜像里面就有这些包.可yum安装 snmpwalk集合 snmpwalk + ...

  10. JavaScript的数学计算库:decimal.js

    An arbitrary-precision Decimal type for JavaScript. 功能 整数和浮点数 简单但功能齐全的 API 复制 JavaScript 和对象的许多方法Num ...