最近公司需要配置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至原节点