最近公司需要配置mysql集群和高可用环境,经过筛选,配置MHA环境更符合公司现有系统要求,下面将完整的配置方法和注意事项分享给大家。
1、 mysql安装
①cmake的安装
cp cmake-2.8.10.2.tar.gz /uar/local
tar -zxvf cmake-2.8.10.2.tar.gz // 解压压缩包
cd cmake-2.8.10.2
./configure
make
make install
②mysql源码安装
采用源码安装方式安装,先将mysql-5.6.16.tar源码拷贝至服务器解压,解压后进入mysql-5.6.16这个目录中
使用cmake源码安装mysql(如果你打算安装到不同的路径,注意修改下面语句中/usr/local/mysql这个路径!)
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql /
-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock /
-DDEFAULT_CHARSET=utf8 /
-DDEFAULT_COLLATION=utf8_general_ci /
-DWITH_MYISAM_STORAGE_ENGINE=1 /
-DWITH_INNOBASE_STORAGE_ENGINE=1 /
-DWITH_ARCHIVE_STORAGE_ENGINE=1 /
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 /
-DWITH_MEMORY_STORAGE_ENGINE=1 /
-DWITH_READLINE=1 /
-DENABLED_LOCAL_INFILE=1 /
-DMYSQL_DATADIR=/mysql/data /
-DMYSQL_USER=mysql /
-DMYSQL_TCP_PORT=3306 /
-DENABLE_DOWNLOADS=1
上面的这些复制完,回车,然后就开始cmake的过程,一般时间不会很长。
cmake结束后开始编译源码,这一步时间会较长,请耐心等待。
make (注:此步骤可以使用make -j多个CPU一起编译,提升速度,单核CPU不要加此参数)
安装编译好的程序
make install
注意:如果需要重装mysql,在/usr/local/src/mysql-5.6.16在执行下make install就可以了,不需要再cmake和make
清除安装临时文件
make clean
③初始化数据目录
cd /usr/local/mysql/scripts/
创建mysql用户,将/mysql /user/local/mysql 目录赋权给mysql
useradd mysql
chown -Rf mysql:mysql /mysql
chown -Rf mysql:mysql /usr/local/mysql
./mysql_install_db --datadir=/mysql/data --basedir=/usr/local/mysql --user=mysql
出现两个OK字样,表示数据目录初始化完毕在/mysql/data下
④mysql注册服务并启动
cd /usr/local/mysql/support-files
cp mysql.server /etc/rc.d/init.d/mysql
cp my-default.cnf /etc/my.cnf
chkconfig --add mysql
chkconfig mysql on
service mysql start
mysql -u mysql -S /usr/local/mysql/mysql.sock
连接需要sock信息,可以-S指定路径或者把socket路径写在my.cnf中,配置相应路径,否则连接报错,建议写在配置文件里
[mysqld]
socket=/usr/local/mysql/mysql.sock
[client]
socket=/usr/local/mysql/mysql.sock
其他my.cnf参数后续添加
2、 mysql主从复制
本实验通过三台服务器搭建主从复制环境
Master 10.39.251.187
Slaver1 10.39.251.188
Slaver2 10.39.251.189
修改主库和从库的参数文件(/etc/my.cnf)
主库:10.39.251.187
#[mysqld]标签下追加
server_id =1
log-bin=/mysql/data/mysql-bin
log-bin-index=/mysql/data/mysql-binlog.index
log_slave_updates=1
sync-binlog = 1
从库1:10.39.251.188 (备主)
#[mysqld]标签下追加
server_id =2
log-bin=/mysql/data/mysql-bin
log-bin-index=/mysql/data/mysql-binlog.index
log_slave_updates=1
sync-binlog = 1
从库2:10.39.251.189
#[mysqld]标签下追加
read_only=1
server_id = 3
登录主服务器创建从服务器的连接账号,分配权限
mysql> GRANT replication slave ON *.* TO 'repluser'@'%' identified by 'oracle';
mysql> flush privileges;
初始化数据:
所有从库:如果从库以前有数据,要干掉原有数据,保持从库是干净的
service mysql stop #停止Mysql服务
cd /mysql/data #进入数据目录
rm -fr 数据库目录 #删除数据库目录
service mysql restart #启动Mysql服务
主库:主库的数据导出,并导入所有从库,保持数据一致
mysqldump -u root -poracle123 m >/tmp/full.sql #主库导出数据
scp /tmp/full.sql root@从库IP:/tmp/ #主库导出的数据通过scp传送到所有从库
所有从库:导入主库传过来的数据
mysql -u root -poracle123 m < /tmp/full.sql #导入主库传递过来的数据
主库:为主库加上只读锁,查看当前Binlog日志情况
mysql> flush tables with read lock; #给主库加上读锁
mysql> show master status;
+------------------+----------+--------------+--------------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+--------------------------+-------------------+
| mysql-bin.000003 | 411 | | mysql,information_schema | |
+------------------+----------+--------------+--------------------------+-------------------+
mysql>unlock tables; #给主库解锁
所有从库向主库做同步操作,开启复制
从库上执行:
change master to master_host='10.39.251.187',
master_port=3306, master_user='repluser',
master_password='oracle', master_log_file='mysql-bin.000003',master_log_pos=411
启动slaver
start slave;
在从库查看:
mysql> show slave status/G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.10.21
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 411
Relay_Log_File: my3306-relay-bin.000002
Relay_Log_Pos: 283
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 0
测试同步:
主库建表插入记录,在从库中查询,很简单一般测试正常,MySQL会自动提交
半同步复制:
MySQL5.5 除了支持内置的异步复制机制,还提供了接口支持半同步复制的机制。
异步复制的缺点:
MySQL复制默认是异步复制,Master将事件写入binlog,但并不知道Slave是否或何时已经接收且已处理。在异步复制的机制的情况下,如果Master宕机,事务在Master上已提交,但很可能这些事务没有传到任何的Slave上。假设有Master->Salve故障转移的机制,此时Slave也可能会丢失事务。
半同步复制的概念:
i.
当Slave主机连接到Master时,能够查看其是否处于半同步复制的机制。
ii.
当Master上开启半同步复制的功能时,至少应该有一个Slave开启其功能。此时,一个线程在Master上提交事务将受到阻塞,直到得知一个已开启半同步复制功能的Slave已收到此事务的所有事件,或等待超时。
iii.
当一个事务的事件都已写入其relay-log中且已刷新到磁盘上,Slave才会告知已收到。
iv.
如果等待超时,也就是Master没被告知已收到,此时Master会自动转换为异步复制的机制。当至少一个半同步的Slave赶上了,Master与其Slave自动转换为半同步复制的机制。
v.
半同步复制的功能要在Master,Slave都开启,半同步复制才会起作用;否则,只开启一边,它依然为异步复制。
半同步复制安装方法:
环境要求:
i.
MySQL5.5或以上版本
ii.
在MySQL上安装插件需要数据库支持动态载入。检查是否支持,用如下检测:
mysql> show global variables like 'have_dynamic_loading';
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| have_dynamic_loading | YES |
+----------------------+-------+
1 row in set (0.00 sec)
iii.半同步复制是基于复制的环境。也就是说配置半同步复制前,已有复制的环境。
安装:
在Master上执行:
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
各个Slave上执行:
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
如果不清楚Plugin的目录,用如下查找:
mysql> show global variables like 'plugin_dir';
+---------------+----------------------------------+
| Variable_name | Value |
+---------------+----------------------------------+
| plugin_dir | /opt/usr/local/mysql/lib/plugin/ |
+---------------+----------------------------------+
检查Plugin是否已正确安装:
mysql> show plugins;
or
mysql> select * from information_schema.plugins;
配置:
在Master上执行:
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
mysql> SET GLOBAL rpl_semi_sync_master_timeout = N;
在Slave上执行:
mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;
说明:http://www.linuxidc.com
如果在一个正在运行的Slave上开启半同步复制的功能,必须先停止Slave I/O,将其启用半同步后,再开启Slave I/O.
mysql> STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;
如果不这样做,Slave还是会以异步的方式进行复制。
正如大家所知,如果不将变量的设置写到配置文件,下次重启数据库,将失效。写入配置文件:
Master上:
[mysqld]
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000 # 1 second
Slave上:
[mysqld]
rpl_semi_sync_slave_enabled=1
3、 MHA安装
MHA特点:
MHA监控复制架构的主服务器,一旦检测到主服务器故障,就会自动进行故障转移。即使有些从服务器没有收到最新的relay log,MHA自动从最新的从服务器上识别差异的relay log并把这些日志应用到其他从服务器上,因此所有的从服务器保持一致性了。MHA通常在几秒内完成故障转移,9-12秒可以检测出主服务器故障,7-10秒内关闭故障的主服务器以避免脑裂,几秒中内应用差异的relay log到新的主服务器上,整个过程可以在10-30s内完成。还可以设置优先级指定其中的一台slave作为master的候选人。由于MHA在slaves之间修复一致性,因此可以将任何slave变成新的master,而不会发生一致性的问题,从而导致复制失败
安装步骤:
检查各服务器防火墙和SELINUX是否关闭
①在master 上创建管理用户并赋权
mysql> CREATE USER 'mha'@'%' IDENTIFIED BY 'mhapwd';
mysql> grant all privileges on *.* to 'mha'@'%' identified by 'mhapwd';
mysql> flush privileges;
②在从库检查是否同步
mysql> select user,host from mysql.user;
③配置mysql 环境变量,各节点都需配置
[root@mysql-01 ~]# echo 'PATH=/usr/local/mysql/bin:$PATH' >>/etc/profile
[root@mysql-01 ~]# source /etc/profile
[root@mysql-01 ~]# which mysql
#建立mysql,mysqlbinlog 软链接
mv /usr/bin/mysql /usr/bin/mysql_bak
ln -s /usr/local/mysql/bin/* /usr/bin/
④配置ssh 免密码登陆,先在各服务器中配置/etc/hosts
在其中一台251.187执行
ssh-keygen -t rsa 一路回车
cd /root/.ssh/
cat id_rsa.pub >> authorized_keys //建立本地信任
scp id_rsa.pub root@10.39.251.188:/root/.ssh/id_rsa187.pub
scp id_rsa.pub root@10.39.251.189:/root/.ssh/id_rsa187.pub
进入251.188与251.189的root家目录
cd /root/.ssh/
cat id_rsa187.pub >> authorized_keys //建立远程信任
chmod 700 ~/.ssh/*
至此,187已可以通过ssh不输入密码登陆到187、188与189,同理在188与189中分别执行第④步操作,使三台服务器可以互相连接无需输入密码(需注意一定不要用复制粘贴的方法拷贝key,会出现问题,如果配置完毕SSH仍有问题可以查看/var/log/secure日志信息)
⑤安装MHA
需要安装一些包做支持,使用yum网络源;如安装遇到问题可以尝试yum update更新yum源或yum clean all清除缓存
在187、188、189中安装node
yum -y install perl-DBD-MySQL ncftp
rpm -ivh mha4mysql-node-0.54-0.el6.noarch.rpm
在189中安装manager
yum install perl
yum install cpan
yum install perl-Config-Tiny
yum install perl-Time-HiRes
yum install perl-Log-Dispatch
yum install perl-Parallel-ForkManager
如果安装perl-Log-Dispatch,perl-Parallel-ForkManager安装包报错:需要先安装epel(可以参考https://fedoraproject.org/wiki/EPEL)
rpm -ivh epel-release-6-8.noarch.rpm
rpm -ivh mha4mysql-manager-0.54-0.el6.noarch.rpm
⑥配置HMA
mkdir -p /etc/masterha
mkdir -p /mha/app1
touch /etc/masterha/app1.cnf
vi /etc/masterha/app1.cnf
插入如下内容:
[server default]
manager_workdir=/mha/app1
manager_log=/mha/app1/manager.log
ssh_user=root
user=root
password=oracle123
repl_user=repluser
repl_password=oracle
ping_interval=3
master_ip_failover_script=/masterha/app1/master_ip_failover
[server1]
hostname=10.39.251.187
port=3306
master_binlog_dir=/mysql/data
candidate_master=1
[server2]
hostname=10.39.251.188
port=3306
master_binlog_dir=/mysql/data
candidate_master=1
[server3]
hostname=10.39.251.189
port=3306
master_binlog_dir=/mysql/data
no_master=1
保存退出
masterha_check_ssh工具验证ssh信任登录是否成功
masterha_check_ssh --conf=/etc/masterha/app1.cnf
如遇到报错:Can't locate MHA/NodeConst.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at /usr/share/perl5/vendor_perl/MHA/ManagerConst.pm line 25
解决:cp -rvp /usr/lib/perl5/vendor_perl/MHA /usr/local/lib64/perl5/
(mha的数据库节点和管理节点均需要执行此步骤)
masterha_check_repl工具验证mysql复制是否成功
masterha_check_repl --conf=/etc/masterha/app1.cnf
⑦创建master_ip_failover脚本
cd /mha/app1
touch master_ip_failover
chmod 755 master_ip_failover
vi master_ip_failover
插入如下内容:
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;
my (
$command, $ssh_user, $orig_master_host, $orig_master_ip,
$orig_master_port, $new_master_host, $new_master_ip, $new_master_port
);
my $vip = '10.39.251.192';#Virtual IP
my $gateway = '10.39.251.255';#Gateway IP
my $interface = 'eth0';
my $key = "1";
my $ssh_start_vip = "/sbin/ifconfig $interface:$key $vip;/sbin/arping -I $interface -c 3 -s $vip $gateway >/dev/null 2>&1";
my $ssh_stop_vip = "/sbin/ifconfig $interface:$key down";
GetOptions(
'command=s' => /$command,
'ssh_user=s' => /$ssh_user,
'orig_master_host=s' => /$orig_master_host,
'orig_master_ip=s' => /$orig_master_ip,
'orig_master_port=i' => /$orig_master_port,
'new_master_host=s' => /$new_master_host,
'new_master_ip=s' => /$new_master_ip,
'new_master_port=i' => /$new_master_port,
);
exit &main();
sub main {
print "/n/nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===/n/n";
if ( $command eq "stop" || $command eq "stopssh" ) {
# $orig_master_host, $orig_master_ip, $orig_master_port are passed.
# If you manage master ip address at global catalog database,
# invalidate orig_master_ip here.
my $exit_code = 1;
eval {
print "Disabling the VIP on old master: $orig_master_host /n";
&stop_vip();
$exit_code = 0;
};
if ($@) {
warn "Got Error: $@/n";
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "start" ) {
# all arguments are passed.
# If you manage master ip address at global catalog database,
# activate new_master_ip here.
# You can also grant write access (create user, set read_only=0, etc) here.
my $exit_code = 10;
eval {
print "Enabling the VIP - $vip on the new master - $new_master_host /n";
&start_vip();
$exit_code = 0;
};
if ($@) {
warn $@;
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "status" ) {
print "Checking the Status of the script.. OK /n";
`ssh $ssh_user/@$orig_master_host /" $ssh_start_vip /"`;
exit 0;
}
else {
&usage();
exit 1;
}
}
# A simple system call that enable the VIP on the new master
sub start_vip() {
`ssh $ssh_user/@$new_master_host /" $ssh_start_vip /"`;
}
# A simple system call that disable the VIP on the old_master
sub stop_vip() {
`ssh $ssh_user/@$orig_master_host /" $ssh_stop_vip /"`;
}
sub usage {
print
"Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port/n";
}
⑧启动MHA
nohup masterha_manager --conf=/etc/masterha/app1.cnf > /mha/app1/mha_manager.log < /dev/null 2>&1 & (注:这种启动方式经验证关闭shell时进程也会挂掉,可以写到脚本里执行就没有此问题了)
检查:masterha_check_status --conf=/etc/masterha/app1.cnf
app1 (pid:19570) is running(0:PING_OK), master:10.39.251.187
停止manager:
masterha_stop --conf=/etc/masterha/app1.cnf
# 如果不能停止, 加 --abort选项
masterha_check_repl工具验证mysql复制是否成功
masterha_check_repl --conf=/etc/masterha/app1.cnf
在master节点新增虚拟IP:
/sbin/ifconfig eth0:0 10.39.251.192 netmask 255.255.255.0 up
4、 MHA切换
停止187上的master节点mysql,查看189上manager日志 tail -f /mha/app1/manager.log主节点已切换,登录slaver的mysql查看show slave status/G,发现master已切换至188,并且虚拟IP192已经绑定在188节点上,客户端仍正常访问192即可
切换过程中需要关注的几个问题:
1.切换过程会自动把read_only关闭
2.切换之后需要删除手工删除/masterha/app1/app1.failover.complete,才能进行第二次测试
3.一旦发生切换管理进程将会退出,无法进行再次测试,需将故障数据库加入到MHA环境中来
4.原主节点重新加入到MHA时只能设置为slave,在
change master to MASTER_HOST='192.168.16.5', MASTER_USER='replicationuser',MASTER_PASSWORD='replicationuser',MASTER_LOG_FILE='mysql-bin.000004',MASTER_LOG_POS=106;
之前需要先 reset slave
5.关于ip地址的接管有几种方式,这里采用的是MHA自动调用ip别名的方式,好处是在能够保证数据库状态与业务Ip 切换的一致性。启动管理节点之后 vip会自动别名到当前主节点上,keepalived也只能做到对3306的健康检查,但是做不到比如像MySQL复制中的slave-SQL、slave-IO进程的检查,容易出现对切换的误判。
6.注意:二级从服务器需要将log_slave_updates打开
7.手工切换需要先定义好master_ip_online_change_script脚本,不然只会切换mysql,Ip地址不会绑定上去,可以根据模板来配置该脚本
8.通过设置no_master=1可以让某一个节点永远不成为新的主节点
恢复集群运行:
①在189上删除app1.failover.complete文件
cd /mha/app1
rm -f app1.failover.complete
②原187主节点服务启动
service mysql start
③189管理节点,检查同步报错
masterha_check_repl --conf=/etc/masterha/app1.cnf
Fri Aug 21 11:23:34 2015 - [error][/usr/share/perl5/vendor_perl/MHA/ServerManager.pm, ln604] There are 2 non-slave servers! MHA manages at most one non-slave server. Check configurations.
⑤查看现在的master188上的信息
show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 3721 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
④配置187节点mysql为新的slave,并启动同步进程
change master to master_host='10.39.251.188',
master_port=3306, master_user='repluser',
master_password='oracle', master_log_file='mysql-bin.000001',master_log_pos=3721
mysql> start slave;
再次在管理节点上检查同步状态成功:
masterha_check_repl --conf=/etc/masterha/app1.cnf
需注意:按如上步骤操作后,此时187节点作为slaver已加入到集群中,但是宕机这段时间188、189中新产生的数据在187中没有,所以还需要先从主节点备份导入最新的数据再启动同步,步骤参考上面写的主从复制部分内容
⑤启动MHA
nohup masterha_manager --conf=/etc/masterha/app1.cnf > /mha/app1/mha_manager.log < /dev/null 2>&1 &
回切:
同样的道理,以上步骤配置无问题的话停止当前master的MySQL进程,MHA可直接切换master至原节点