CentOS环境利用mariadb(mysql)数据库使用golang实现分布式系统的Leader选举

一、准备工作

1.下载安装vmware,步骤省略。

2.下载CentOS系统ios包:http://isoredirect.centos.org/centos/7/isos/x86_64/CentOS-7-x86_64-Everything-1611.iso

3.下载安装Xshell5,步骤省略。

4.下载安装git,步骤省略。

5.mariadb用于golang的api:https://github.com/go-sql-driver/mysql

6.vmware中依次点击“创建新的虚拟机”->“典型”->“安装程序光盘映像文件”选择上面下载的ios文件,然后一路下一步即可快速安装CentOS系统。

至于为什么安装CentOS,其实其他linux版本也可以。安装完成的CentOS系统如下图:

二、安装配置mariadb数据库

选择mariadb数据库的原因是,CentOS 7 版本将MySQL数据库软件从默认的程序列表中移除,用mariadb代替了。好在MariaDB的完全兼容MySQL的API和命令行,不影响我们使用。

点击屏幕左上角的Applications,打开Terminal。

首先切换到root权限:

输入su,回车,看到Password:后输入密码,注意密码不会显示出来,输入完毕直接回车就好。

然后输入命令安装mariadb数据库:

yum install mariadb mariadb-server

所有的提示输入y回车,如下图所示。

最后出现Complete!说明安装成功,我们将mariadb加入开机启动项并启动。

mariadb加入开机启动项:

systemctl enable mariadb.service

mariadb启动:

systemctl start mariadb.service

接下来进行MariaDB的相关简单配置,输入命令:

mysql_secure_installation

屏幕显示:Enter current password for root (enter for none),初始密码为空,我们直接回车即可。

接下来的提示依次是:设置密码(若Y设置密码,需要输入两次密码)、是否删除匿名用户、是否禁止root远程登录、是否删除test数据库、是否重新加载权限表。

我将密码设置成19930309,后四个选项分别输入n、n、n、y。

然后我们配置MariaDB的字符集,依次修改以下几个文件,可能用到的命令有以下几个。

(1)打开文件:vi 文件名.后缀名

(2)编辑文件:打开文件后按键盘“i”

(3)退出编辑:ESC

(4)保存修改并关闭文件:输入:wq回车

(5)撤销修改:输入:undo回车

在/etc/my.cnf文件的[mysqld]标签下添加

init_connect=‘SET collation_connection = utf8_unicode_ci‘
init_connect=‘SET NAMES utf8‘
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake

在/etc/my.cnf.d/client.cnf文件的[client]标签中添加

default-character-set=utf8

在/etc/my.cnf.d/mysql-clients.cnf文件的[mysql]标签中添加

default-character-set=utf8

配置完成后,输入命令重启mariadb:

systemctl restart mariadb

进入mariadb:

mysql -u root -p

提示输入密码,输入我上一部设置的密码19930309,注意不会显示,输入完直接回车就好。

查看一下我们设置好的字符集,输入:

show variables like "%character%";show variables like "%collation%";

这里为了使用方便,我将输入命令的位置由虚拟机的terminal换成了Xshell,与terminal里输入并无差别,Xshell的使用方法在我另一篇博客里有提及(http://www.cnblogs.com/renjiashuo/p/7247388.html),这里不做赘述。

显示为

字符集配置完成。

输入一下命令查看一下目前已有的数据库:

show databases;

可以看到我们现在有4个database。

三、使用数据库与golang实现分布式系统的leader选举

在Xshell中输入命令使用test表:

use test

下面在Xshell输入一个命令给数据库授予外网访问权限:

grant all privileges on *.* to [email protected]‘%‘ identified by ‘19930309‘;

其中,root为我们设置的数据库用户名,19930309为我的数据库密码。

创建一个数据表用于当前leader的记录与更新:

CREATE TABLE service_election (
  anchor tinyint(3) unsigned NOT NULL,
  service_id varchar(128) NOT NULL,
  last_seen_active timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (anchor)
) ENGINE=InnoDB

  

可以输入以下命令查看此test数据库下包含的所有表:

show tables;

下面查看一下我们创建的数据库表:

SHOW FULL COLUMNS from service_election;

可以看到表已经创建成功了,如下图所示。

数据库完成后,我们开始编写golang程序。

首先使用git获取golang对mysql的api,下面是git命令:

查看golang的位置:

which go

设置GOROOT:

export GOROOT=/c/Go

我将golang程序放到了d盘的golang文件夹下,那么设置一下GOPATH:

export GOPATH=/d/golang/

获取zookeeper对go的api:

go get github.com/go-sql-driver/mysql

下面在d盘golang文件夹下新建两个go项目,分别写入如下代码来模拟Leader选举的过程:

package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"time"
)

func main() {
	// 连接数据库
	db, err := sql.Open("mysql", "root:[email protected](192.168.40.128:3306)/test?charset=utf8")
	checkErr(err)
	// 如果用于记录leader的数据库表中没有数据,则插入数据,将本进程设为leader
	rows, err := db.Query("SELECT * FROM service_election for update")
	checkErr(err)
	if rows == nil{
		_, err = db.Exec("replace into service_election (anchor, service_id, last_seen_active) values (1, ‘user1‘, now())")
		checkErr(err)
	}
	db.Query("commit");

	// 轮询
	for {
		// 加锁
		rows, err := db.Query("SELECT * FROM service_election where anchor = ‘1‘ for update")
		checkErr(err)
		for rows.Next() {
			var anchor int
			var service_id string
			var last_seen_active string
			rows.Columns()
			err = rows.Scan(&anchor, &service_id, &last_seen_active)
			checkErr(err)
			//fmt.Println(last_seen_active)
			local, _ := time.LoadLocation("Local")
			tm2, _ := time.ParseInLocation("2006-01-02 15:04:05", last_seen_active, local)
			//fmt.Println(tm2.Unix())
			//fmt.Println(tm2)
			now := time.Now()
			//fmt.Println(now.Unix())
			// 每5秒更新一下时间戳,若发现时间戳超过10秒没被更新,则竞选leader
			if service_id == "user1" && now.Unix()-tm2.Unix() > 5 {
				// 插入数据
				_, err = db.Exec("update service_election set service_id = ‘user1‘,last_seen_active = now() where anchor = ‘1‘")
				checkErr(err)
			}else if now.Unix()-tm2.Unix() > 10 {
				// 插入数据
				_, err = db.Exec("update service_election set service_id = ‘user1‘,last_seen_active = now() where anchor = ‘1‘")
				checkErr(err)
			}
			// 解锁
			db.Query("commit");
		}
		// 查询本进程是否为leader
		rows, err = db.Query("SELECT * FROM service_election")
		checkErr(err)
		for rows.Next() {
			var anchor int
			var service_id string
			var last_seen_active string
			rows.Columns()
			err = rows.Scan(&anchor, &service_id, &last_seen_active)
			checkErr(err)
			if service_id == "user1" {
				fmt.Println("I am the master.")
			} else {
				fmt.Println("I am the slave.")
			}
		}
		time.Sleep(time.Second * 5)
	}
	db.Close()
}

func checkErr(err error) {
	if err != nil {
		panic(err)
	}
}

  

package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"time"
)

func main() {
	// 连接数据库
	db, err := sql.Open("mysql", "root:[email protected](192.168.40.128:3306)/test?charset=utf8")
	checkErr(err)
	// 如果用于记录leader的数据库表中没有数据,则插入数据,将本进程设为leader
	rows, err := db.Query("SELECT * FROM service_election for update")
	checkErr(err)
	if rows == nil{
		_, err = db.Exec("replace into service_election (anchor, service_id, last_seen_active) values (1, ‘user2‘, now())")
		checkErr(err)
	}
	db.Query("commit");

	// 轮询
	for {
		// 加锁
		rows, err := db.Query("SELECT * FROM service_election where anchor = ‘1‘ for update")
		checkErr(err)
		for rows.Next() {
			var anchor int
			var service_id string
			var last_seen_active string
			rows.Columns()
			err = rows.Scan(&anchor, &service_id, &last_seen_active)
			checkErr(err)
			//fmt.Println(last_seen_active)
			local, _ := time.LoadLocation("Local")
			tm2, _ := time.ParseInLocation("2006-01-02 15:04:05", last_seen_active, local)
			//fmt.Println(tm2.Unix())
			//fmt.Println(tm2)
			now := time.Now()
			//fmt.Println(now.Unix())
			// 每5秒更新一下时间戳,若发现时间戳超过10秒没被更新,则竞选leader
			if service_id == "user2" && now.Unix()-tm2.Unix() > 5 {
				// 插入数据
				_, err = db.Exec("update service_election set service_id = ‘user2‘,last_seen_active = now() where anchor = ‘1‘")
				checkErr(err)
			}else if now.Unix()-tm2.Unix() > 10 {
				// 插入数据
				_, err = db.Exec("update service_election set service_id = ‘user2‘,last_seen_active = now() where anchor = ‘1‘")
				checkErr(err)
			}
			// 解锁
			db.Query("commit");
		}
		// 查询本进程是否为leader
		rows, err = db.Query("SELECT * FROM service_election")
		checkErr(err)
		for rows.Next() {
			var anchor int
			var service_id string
			var last_seen_active string
			rows.Columns()
			err = rows.Scan(&anchor, &service_id, &last_seen_active)
			checkErr(err)
			if service_id == "user2" {
				fmt.Println("I am the master.")
			} else {
				fmt.Println("I am the slave.")
			}
		}
		time.Sleep(time.Second * 5)
	}
	db.Close()
}

func checkErr(err error) {
	if err != nil {
		panic(err)
	}
}

  

两个程序代码的差别仅仅在于,数据库表的service_id项一个设置成了user1,另一个设置成了uesr2。在实际应用中,我们可以将这项设置成各自物理机的ip。

分别运行两个程序,可以看到一个程序不断输出“I am the master.”,另一个程序不断输出“I am the slave.”,如果关闭master程序,则大约10秒后,slave程序开始输出master,之后再打开之前关闭的程序,它已经成为了新的slave。如图所示。

自此,CentOS环境利用mariadb(mysql)数据库使用golang实现分布式系统的Leader选举实现完毕。

四、参考网络资源

http://www.cnblogs.com/starof/p/4680083.html

http://www.linuxidc.com/Linux/2016-03/128880.htm

http://blog.csdn.net/a19352226/article/details/50814900

http://code.openark.org/blog/mysql/leader-election-using-mysql

时间: 2024-10-05 09:45:37

CentOS环境利用mariadb(mysql)数据库使用golang实现分布式系统的Leader选举的相关文章

CentOS 7.4安装 MySQL数据库

CentOS 7 版本将MySQL数据库软件从默认的程序列表中移除,用MariaDB代替了,MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可.开发这个分支的原因之一是:甲骨文公司收购了MySQL后,有将MySQL闭源的潜在风险,因此社区采用分支的方式来避开这个风险.MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品. 方法一:通过yum来进行mysql的安装 由于我安装的CentOS7.4默认安装了Maria

CentOS 6.5 安装MySQL数据库

CentOS 6.5 安装MySQL数据库 [[email protected]~]# yum -y install mysql-server //安装命令 [[email protected]~]# service mysqld start //连接之前先启动服务 [[email protected]~]# chkconfig mysqld on //开机启动设置,也可以手动开启 [[email protected]~]# mysql -u root Welcome to the MySQL

Linux CentOS 6.5 操作环境下修改mysql数据库密码

修改的用户都以root为列.一.拥有原来的myql的root的密码: 方法一:在mysql系统外,使用mysqladmin# mysqladmin -u root -p password "test123"Enter password: [输入原来的密码] 方法二:通过登录mysql系统,# mysql -uroot -pEnter password: [输入原来的密码]mysql>use mysql;mysql> update user set password=pass

Mac之OS系统下搭建JavaEE环境 <五> 之Mysql数据库的安装及配置

这里将推荐两款 集成的Mysql环境 十分轻便好用,MAMP 和 XAMPP MAMP XAMPP 1.MAMP下载 官网: https://www.mamp.info/en/ 下载安装即可使用 MAMP PRO的 序列号:MP-DED4-0A88-3A11-F9FDE 2.Mysql启动 十分简单 .配置你需要的端口 和 密码 即可. 3.XAMPP下载 官网:https://www.apachefriends.org/index.html 由于最新版本的XAMPP都是 配置的 MariaDB

centos环境下如何导出数据库

MySQL数据库的导入导出可以用数据库备份工具mysqldump mysqldump工具是mysql自带的一个非常方便的一款小工具,存在mysql安装目录的/usr/local/mysql/bin (CentOS)是下. mysqldump 和 mysql一样,都是应用程序,你在mysql下是执行不了的.切记 ,输入 mysqldump –help 可查看相关信息.mysqldump可以任何目录下直接执行. 一.导出 用 mysqldump 备份数据库 1 mysqldump -u用户 -p密码

linux环境下安装mysql数据库遇到的问题

总结一句话: 安装完mysql数据库记得授权远程登录. 坑的现象: ERROR 1045 (28000): Access denied for user 'guoxp'@'localhost' (using password: YES) 解决方案如下: 执行前查看状态: MariaDB [mysql]>  select Host,User,Password from user ; +-----------------------+-------+-------------------------

【DNS服务补录】+【mariadb,mysql数据库】

DNS服务补录,1)关于:副DNS服务器的配置/etc/resolv.conf 中的servername指向自己.slavesvim /etc/named.rfc1912.zones[添加更改为]zone "HXL.com" IN {    type slave;    masters { 172.25.254.206 ;};    file"slaves/HXL.com.zone";    allow-update { none; };};在主DNS服务器的vim

Eclipse下配置j2ee开发环境及与MySQL数据库的连接

Eclipse下配置j2ee开发环境 a.配置tomcat  windows->perferences->server->server runtime environments->Add…… b.installes JREs,然后点击Add 默认的standard VM就可以,点击next,然后点击directory 选择本机jdk安装的路径,finish. 与MySQL数据库的连接 与数据库连接要做的事情就是要用jdbc 首先要下载jdbc,在官网上下载,在将其mysql-con

【xampp】windows下XAMPP集成环境中,MySQL数据库的使用

在已经安装了XAMPP之后,会在你安装的目录下面出现"XAMPP"文件夹,这个文件夹就是整个XAMPP集成环境的目录. 我们先进入这个目录,然后会看到带有XAMPP标志的xampp-control.exe执行文件. 双击打开xampp-control.exe,会出现以下界面,点击开启Apache和MySQL,这样我们就开启服务了,之后我们可以通过图形界面或者DOS界面使用MySQL数据库,首先介绍DOS界面使用. 使用XAMPP下的DOS界面,用命令操作MySQL,我们可以在开启服务后