企业级MySQL集群具备高可用、可扩展、易管理、低成本的特点。下面将介绍企业环境中经常应用的一个解决方案,即MySQL的双主互备架构,主要设计思路是通过MySQL Replication技术将两台MySQL Server互相将对方作为自己的Master,自己又同时作为对方的Slave来进行复制。这样就实现了高可用构架中的数据同步功能,同时,将采用KeepAlived来实现Mysql的自动failover。在这个构架中,虽然两台MySQL Server互为主从,但同一时刻只有一个MySQL Server可读写,另一个MySQL Server只能进行读操作,这样可保证数据的一致性。整个架构下图所示。
MySQL主主互备模式配置环境
主机名 操作系统版本 MySQL版本 主机IP MySQL VIP
DB1(Master) CentOS release 6.7 mysql-5.6.17 192.168.1.85
DB2(Slave) CentOS release 6.7 mysql-5.6.17 192.168.1.89
第一步要做的工作是在这两天机器上都安装mysql,在做主从复制的时候mysql的版本尽量保持一致。即使不一样一定要以主服务的版本为最高的版本,从服务器的版本不能高于主服务器的版本。
Mysql的安装与配置
Mysql5.6版本之后,编译mysql方式变为cmake
安装cmake:
#yum install cmake
#cd mysql-5.6.17
#cmake \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DMYSQL_DATADIR=/usr/local/mysql/data \
-DSYSCONFDIR=/etc \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DWITH_READLINE=1 \
-DMYSQL_UNIX_ADDR=/var/lib/mysql/mysql.sock \
-DMYSQL_TCP_PORT=3306 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci
make && make install
如果没有就创建用户就创建如下用户:
#groupadd mysql
#useradd -g mysql mysql
修改/usr/local/mysql权限:
#chown -R mysql:mysql /usr/local/mysql
#cd /usr/local/mysql
进入安装路径,执行初始化配置脚本,创建系统自带的数据库和表
#scripts/mysql_install_db --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data --user=mysql
注:在启动MySQL服务时,会按照一定次序搜索my.cnf,先在/etc目录下找,找不到则会搜索"$basedir/my.cnf",在本例中就是 /usr/local/mysql/my.cnf,这是新版MySQL的配置文件的默认位置!如果发现/etc下存在my.cof文件,直接删掉,这样启动mysql时才会去/usr/local/mysql/my.cnf目录下下去找自己安装的文件
启动MySQL
添加服务,拷贝服务脚本到init.d目录,并设置开机启动
#cd /usr/local/mysql
#cp support-files/mysql.server /etc/init.d/mysql
#chkconfig mysql on
#service mysql start --启动MySQL
配置mysql主从服务器
1.1修改MySQL配置文件
在默认情况下MySQL的配置文件是/etc/my.cnf。但我们需要修改的路径是自己安装MySQL的路径。首先修改DB1主机的配置文件,在/usr/local/mysql/my.cnf文件中的“[mysqld]”段添加如下内容:
server-id = 1
log-bin=mysql-bin
relay-log = mysql-relay-bin
replicate-wild-ignore-table=mysql.%
replicate-wild-ignore-table=test.%
replicate-wild-ignore-table=information_schema.%
然后修改DB2主机的配置文件,在/usr/local/mysql/my.cnf文件中的“[mysqld]”段添加如下内容:
server-id = 2
log-bin=mysql-bin(如果只有一主一从,在从库上是不需要开启binlog日志的,后面是为了演示互为主从这才加上去的)
relay-log = mysql-relay-bin
replicate-wild-ignore-table=mysql.%
replicate-wild-ignore-table=test.%
replicate-wild-ignore-table=information_schema.%
其中,server-id是节点标识,主、从节点不能相同,必须全局唯一。log-bin表示开启MySQL的binlog日志功能。“mysql-bin”表示日志文件的命名格式,会生成文件名为mysql-bin.000001、mysql-bin.000002等的日志文件。relay-log用来定义relay-log日志文件的命名格式。replicate-wild-ignore-table是个复制过滤选项,可以过滤掉不需要复制的数据库或表,例如“mysql.%“表示不复制mysql库下的所有对象,其他依此类推。与此对应的是replicate_wild_do_table选项,用来指定需要复制的数据库或表。
这里需要注意的是,不要在主库上使用binlog-do-db或binlog-ignore-db选项,也不要在从库上使用replicate-do-db或replicate-ignore-db选项,因为这样可能产生跨库更新失败的问题。推荐在从库上使用replicate_wild_do_table和replicate-wild-ignore-table两个选项来解决复制过滤问题
1.2手动同步数据库
如果DB1上已经有mysql数据,那么在执行主主互备之前,需要将DB1和DB2上两个mysql的数据保持同步,首先在DB1上备份mysql数据,执行如下SQL语句:
mysql>FLUSH TABLES WITH READ LOCK; (解锁:unlock tables;)
Query OK, 0 rows affected (0.00 sec)
不要退出这个终端,否则这个锁就失效了。在不退出终端的情况下,再开启一个终端直接打包压缩数据文件或使用mysqldump工具来导出数据。这里通过打包mysql文件来完成数据的备份,操作过程如下:
[root@DB1 ~]# cd /usr/local
[root@DB1 lib]# tar zcvf mysql.tar.gz mysql
[root@DB1 lib]# scp mysql.tar.gz DB2:/usr/local/
将数据传输到DB2后,依次重启DB1和DB2上面的mysql。
1.3 创建复制用户并授权
首先在DB1的mysql库中创建复制用户,操作过程如图所示。
mysql> grant replication slave on *.* to 'repl_user'@'192.168.1.89' identified by 'repl_passwd';
然后在DB2的mysql库中将DB1设为自己的主服务器,操作如下所示。
change master to master_host='192.168.1.85',master_user='repl_user',master_password='repl_passwd',master_log_file='mysql-bin.000001',master_log_pos=431;
这里需要注意master_log_file和master_log_pos两个选项,这两个选项的值刚好是在DB1上通过SQL语句“show master status”查询到的结果。
接着就可以在DB2上启动slave服务了,可执行如下SQL命令:
mysql> start slave;
下面查看DB2上slave的运行状态,如图所示。
通过查看slave的运行状态发现,一切运行正常,这里需要重点关注的是Slave_IO_Running和Slave_SQL_Running,这两个就是在Slave节点上运行的主从复制线程,正常情况下这两个值都应该为Yes。另外还需要注意的是Slave_IO_State、Master_Host、Master_Log_File、Read_Master_Log_Pos、Relay_Log_File、Relay_Log_Pos和Relay_Master_Log_File几个选项,从中可以查看出mysql复制的运行原理及执行规律。最后还有一个Replicate_Wild_Ignore_Table选项,这个是之前在my.cnf中添加过的,通过此选项的输出值可以知道过滤掉了哪些数据库。
到这里位置,从DB1到DB2的mysql主从复制已经完成了。接下来开始配置从DB2到DB1的mysql主从复制,这个配置过程与上面的完全一样,首先在DB2的mysql库中创建复制用户,操作如图
grant replication slave on *.* to 'repl_user'@'192.168.1.85' identified by 'repl_passwd';
然后在DB1的mysql库中将DB2设为自己的主服务器,操作如下
change master to master_host='192.168.1.89',master_user='repl_user',master_password='repl_passwd',master_log_file='mysql-bin.000001',master_log_pos=862;
接着就可以在DB1上启动slave服务了,可执行如下SQL命令:
mysql> start slave;
从图上中可以看出Slave_IO_Running和Slave_SQL_Running都是Yes状态,表明DB1上复制服务运行正常。至此,mysql双主模式的主从复制已经配置完毕了
2、配置KeepAlived实现MySQL双主高可用
在进行高可用配置之前,首先需要在DB1和DB2服务器上安装KeepAlived软件。关于KeepAlived会在后面做详细介绍,这里主要关注下KeepAlived的安装和配置,安装过程如下:
[root@keepalived-master app]#tar zxvf keepalived-1.2.12.tar.gz
[root@keepalived-master app]#cd keepalived-1.2.12
[root@keepalived-master keepalived-1.2.12]#./configure --sysconf=/etc \
> --with-kernel-dir=/usr/src/kernels/2.6.32-431.5.1.el6.x86_64
[root@keepalived-master keepalived-1.2.12]#make
[root@keepalived-master keepalived-1.2.12]#make install
[root@keepalived-master keepalived-1.2.12]#ln -s /usr/local/sbin/keepalived /sbin/
[root@keepalived-master keepalived-1.2.12]# chkconfig --add keepalived
[root@keepalived-master keepalived-1.2.12]# chkconfig --level 35 keepalived on
安装完成后,进入keepalived的配置过程。
下面是DB1服务器上/etc/keepalived/keepalived.conf文件的内容。
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL
}
vrrp_script check_mysqld {
script "/etc/keepalived/mysqlcheck/check_slave.pl 127.0.0.1" #检测mysql复制状态的脚本
interval 2
}
vrrp_instance VI_1 {
state BACKUP #在DB1和DB2上均配置为BACKUP
interface eth0
virtual_router_id 80
priority 100
advert_int 2
nopreempt #不抢占模式,只在优先级高的机器上设置即可,优先级低的机器不设置
authentication { #效验DB1和DB2需一致
auth_type PASS
auth_pass qweasdzxc
}
track_script {
check_mysqld
}
virtual_ipaddress {
192.168.1.84/24 dev eth0 #mysql的对外服务IP,即VIP
}
}
其中,/etc/keepalived/mysqlcheck/check_slave.pl文件的内容为:
#!/usr/bin/perl -w
use DBI;
use DBD::mysql;
# CONFIG VARIABLES
$SBM = 120;
$db = "mysql";
$host = $ARGV[0];
$port = 3306;
$user = "root";
$pw = "xxxxxx";
# SQL query
$query = "show slave status";
$dbh = DBI->connect("DBI:mysql:$db:$host:$port", $user, $pw, { RaiseError => 0,PrintError => 0 });
if (!defined($dbh)) {
exit 1;
}
$sqlQuery = $dbh->prepare($query);
$sqlQuery->execute;
$Slave_IO_Running = "";
$Slave_SQL_Running = "";
$Seconds_Behind_Master = "";
while (my $ref = $sqlQuery->fetchrow_hashref()) {
$Slave_IO_Running = $ref->{'Slave_IO_Running'};
$Slave_SQL_Running = $ref->{'Slave_SQL_Running'};
$Seconds_Behind_Master = $ref->{'Seconds_Behind_Master'};
}
$sqlQuery->finish;
$dbh->disconnect();
if ( $Slave_IO_Running eq "No" || $Slave_SQL_Running eq "No" ) {
exit 1;
} else {
if ( $Seconds_Behind_Master > $SBM ) {
exit 1;
} else {
exit 0;
}
}
这是个用perl写的检测mysql复制状态的脚本,ixdba是本例中的一个数据库名,读者只需修改文件中数据库名、数据库的端口、用户名和密码即可直接使用,但在使用前要保证此脚本有可执行权限。
接着将keepalived.conf文件和check_slave.pl文件复制到DB2服务器上对应的位置,然后将DB2上keepalived.conf文件中priority值修改为90,同时去掉nopreempt选项。
在完成所有配置后,分别在DB1和DB2上启动keepalived服务,在正常情况下VIP地址应该运行在DB1服务器上。
启动之前,先检测是脚本是否可以正常运行
yum install perl-DBD-MySQL
然后再启动keepalinved
3、测试MySQL主从同步功能
为了验证mysql的复制功能,可以编写一个简单的程序进行测试,也可以通过远程客户端登录进行测试。这里通过一个远程mysql客户端,然后利用mysql的VIP地址登录,看是否能登录,并在登录后进行读、写操作,看看DB1和DB2之间是否能够实现数据同步。由于是远程登录测试,因此DB1和DB2两台MySQL服务器都要事先做好授权,允许从远程登录。
授权:grant all privileges on *.* to 'root'@'192.168.1.82' identified by 'root';
1) 在远程客户端通过VIP登录测试
2) 数据复制功能测试
4、测试KeepAlived实现MySQL故障转移
为了测试KeepAlived实现的故障转移功能,需要模拟一些故障,比如,可以通过断开DB1主机的网络、关闭DB1主机、关闭DB1上mysql服务等各种操作实现,这里在DB1服务器上关闭mysql的日志接收功能,以此来模拟DB1上mysql的故障。由于在DB1和DB2服务器上都添加了监控mysql运行状态的脚本check_slave.pl,因此当关闭DB1的mysql日志接收功能后,KeepAlived会立刻检测到,接着执行切换操作。