Golang基于Mysql分布式锁实现集群主备
背景
集群中如果需要主备,可以基于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分布式锁实现集群主备的更多相关文章
- KingbaseES R3 集群主备切换信号量(semctl)错误故障分析案例
案例说明: 某项目KingbaseES R3 一主一备流复制集群在主备切换测试中出现故障,导致主备无法正常切换:由于bm要求,数据库相关日志无法从主机中获取,只能在现场进行分析:通过对比主备切换时的时 ...
- Redis集群主备模式部署
网上有非常多用Ruby安装Redis-cluster的文章.可是在实际环境下不想安装Ruby,所以本文主要介绍了用Redis命令部署Redis集群.而且为集群中每个master实例添加一个slave实 ...
- Centos7.6部署k8s v1.16.4高可用集群(主备模式)
一.部署环境 主机列表: 主机名 Centos版本 ip docker version flannel version Keepalived version 主机配置 备注 master01 7.6. ...
- 利用redis 分布式锁 解决集群环境下多次定时任务执行
定时任务: @Scheduled(cron= "0 39 3 * * *") public void getAllUnSignData(){ //检查任务锁,若其它节点的相同定时任 ...
- Mysql基于Mysql Cluster+MysqlRouter的集群部署方案
http://note.youdao.com/noteshare?id=a61c4a6ff2b76e5305430eb66eb116e2&sub=4B4B6E8D0E2849F9B0DFB67 ...
- (转)基于keepalived搭建MySQL的高可用集群
基于keepalived搭建MySQL的高可用集群 原文:http://www.cnblogs.com/ivictor/p/5522383.html MySQL的高可用方案一般有如下几种: keep ...
- 【原】基于 HAproxy 1.6.3 Keeplived 在 Centos 7 中实现mysql mariadb galera cluster 集群分发读写 —— 上篇
前言 有一段时间没有写blogs,乘着周末开始整理下haproxy + keeplived 实现 mysql mariadb galera cluster 集群访问环境的搭建工作. 本文集中讲hapr ...
- 1 构建Mysql+heartbeat+DRBD+LVS集群应用系统系列之DRBD的搭建
preface 近来公司利润上升,购买了10几台服务器,趁此机会,把mysql的主从同步的架构进一步扩展,为了适应日益增长的流量.针对mysql架构的扩展,先是咨询前辈,后和同事探讨,准备采用Mysq ...
- 【分布式锁的演化】“超卖场景”,MySQL分布式锁篇
前言 之前的文章中通过电商场景中秒杀的例子和大家分享了单体架构中锁的使用方式,但是现在很多应用系统都是相当庞大的,很多应用系统都是微服务的架构体系,那么在这种跨jvm的场景下,我们又该如何去解决并发. ...
- Ubuntu16.04.1上搭建分布式的Redis集群
为什么要集群: 通常为了,提高网站的响应速度,总是把一些经常用到的数据放到内存中,而不是放到数据库中,Redis是一个很好的Cache工具,当然了还有Memcached,这里只讲Redis.在我们的电 ...
随机推荐
- 在 UOS 统信运行 dotnet 程序提示没有通过系统安全验证无法运行
本文记录 dotnet 应用程序在 UOS 统信系统上运行时,提示 没有通过系统安全验证,无法运行 的问题 这个问题是因为没有开启 UOS 统信的开发者模式,直接将自己构建完成的包放上去跑导致的问题 ...
- JWT 构建Rails API 授权登录
目录 安装jwt组件 创建base_controller.rb控制器 配置路由 用户登陆-api接口 验证用户token信息-api接口(*) 参考下面的连接 使用Rails构建JSON-API ht ...
- Nginx教程+笔记
Nginx 学习视频: 2020最新 Nginx教程全面讲解(Nginx快速上手) https://www.bilibili.com/video/BV1W54y1z7GM?t=553&p=14 ...
- Docker 必知必会2----跟我一步步来执行基本操作
通过前文(https://www.cnblogs.com/jilodream/p/18177695)的了解,我们已经大致明白了什么是docker,为什么要用docker,以及docker的基本设计思路 ...
- Splashtop 免费60天 大赠送
这两天又是双11,又是 EDG 夺冠,可谓喜事连连.热闹不断.我们也给大家准备了一份长达两个月的免费福利,快乐加倍嗷. 福利详情: 1.分享这篇文章(不要设置分组可见). 2.发送您的 Splasht ...
- C语言:通讯录程序设计(多功能)
回顾我的代码shi 通讯录程序设计 主函数 遇到的困难 补充标注说明(一定要看) 效果展示截图 结语 程序源代码 通讯录程序设计 作者前言:该通讯录作品是我大一的C语言结课作业,代码像shi山一样,之 ...
- es命令大全,elasticsearch命令详解
参考链接 Relational DB Elasticsearch 数据库(database) 索引(indices) 表(tables) types 行(rows) documents 字段(colu ...
- Python:Python字符串中的r、u和转义字符
Python中字符串前面我们经常看到加r(R)或u/(U)的前缀,而这两个符号是什么意思呢? 1.r(R) r意为raw,表示不包含转义字符的原生字符串.常见的转义字符包括下列几种: 转义字符 描述 ...
- opensips开启lua支持
操作系统 :CentOS 7.6_x64 opensips版本 :2.4.9 lua版本:5.1 今天整理下CentOS7环境下opensips2.4.9的lua模块笔记及使用示例,并提供运行效果截图 ...
- linux用户管理:创建用户,删除用户,管理用户,用户配置
目录 一.关于用户 二.用户的三种类型 三.与用户有关的配置文件详解 四.创建用户 五.设置用户密码 六.删除用户 七.用户密码时效管理 八.查看用户相关信息的命令 九.修改用户基本信息 十.管理用户 ...