mysql-master-ha:mysql master高可用性管理工具 一.MHA介绍 MHA自动化主服务器故障转移,快速将从服务器晋级为主服务器(通常在10-30s),而不影响复制的一致性,不需要花钱买更多的新服务器,不会有性能损耗,容易安装,不必更改现有的部署环境,适用于任何存储引擎。 MHA提供在线主服务器切换,改变先正运行的主服务器到另外一台上,这个过程只需0.5-2s的时间,这个时间内数据无法写入。 MHA Manager通过ssh连接mysql slave服务器。 虽然MHA试图从挡掉的主服务器上保存二进制日志,并不是总是可行的。例如,如果主服务器硬件故障或无法通过ssh访问,MHA没法保存二进制日志,只进行故障转移而丢失最新数据。 使用半同步复制,可以大大降低数据丢失的风险。MHA可以与半同步复制结合起来。如果只有一个slave已经收到了最新的二进制日志,MHA可以将最新的二进制日志应用于其他所有的slave服务器上,因此他们彼此保持一致性。 MHA有如下特性: 1.主服务器的自动监控和故障转移 MHA监控复制架构的主服务器,一旦检测到主服务器故障,就会自动进行故障转移。即使有些从服务器没有收到最新的relay log,MHA自动从最新的从服务器上识别差异的relay log并把这些日志应用到其他从服务器上,因此所有的从服务器保持一致性了。MHA通常在几秒内完成故障转移,9-12秒可以检测出主服务器故障,7-10秒内关闭故障的主服务器以避免脑裂,几秒中内应用差异的relay log到新的主服务器上,整个过程可以在10-30s内完成。还可以设置优先级指定其中的一台slave作为master的候选人。由于MHA在slaves之间修复一致性,因此可以将任何slave变成新的master,而不会发生一致性的问题,从而导致复制失败。 2.交互式主服务器故障转移 可以只使用MHA的故障转移,而不用于监控主服务器,当主服务器故障时,人工调用MHA来进行故障故障。 3.非交互式的主故障转移 不监控主服务器,但自动实现故障转移。这种特征适用于已经使用其他软件来监控主服务器状态,比如heartbeat来检测主服务器故障和虚拟IP地址接管,可以使用MHA来实现故障转移和slave服务器晋级为master服务器。 4.在线切换主服务器 在许多情况下,需要将现有的主服务器迁移到另外一台服务器上。比如主服务器硬件故障,RAID控制卡需要重建,将主服务器移到性能更好的服务器上等等。维护主服务器引起性能下降,导致停机时间至少无法写入数据。另外,阻塞或杀掉当前运行的会话会导致主主之间数据不一致的问题发生。MHA提供快速切换和优雅的阻塞写入,这个切换过程只需要0.5-2s的时间,这段时间内数据是无法写入的。在很多情况下,0.5-2s的阻塞写入是可以接受的。因此切换主服务器不需要计划分配维护时间窗口(呵呵,不需要你在夜黑风高时通宵达旦完成切换主服务器的任务)。 注:MHA可以应用于任何复制结构 二. MHA所需条件 1.SSH公钥验证 MHA管理节点通过ssh连接mysql服务器,MHA节点通过scp发送最新的relay log到其他slaves服务器上。为了使这些过程自动化,使用SSH公钥验证密码。 2.操作系统 MHA目前只支持Linux系统 3.单台可写主服务器和多台从服务器或只读主服务器 当主服务器当掉时,MHA修复从服务器之间数据一致性。MHA试图从当掉的主服务器上保存尚未发送的二进制日志文件并应用于所有从服务器。如果只有一个从服务器,就不需在意从服务器之间一致性问题。即使只有一个从服务器,MHA也会从当掉的主服务器上保存尚未发送的二进制日志事件只要能通过ssh访问到主服务器。使用半同步复制可以解决当主服务器当掉后,无法ssh到主服务器上保存尚未发送的二进制日志事件。 从MHA Manager0.52版本开始,支持多主复制结构。只允许其中一台主服务器可写,其他主服务器必须设置read-only=1。默认情况下,被管理服务器应该是两层复制结构。 4.在三层或三层以上复制情况下 默认情况下,MHA不支持三层或三层以上的复制结构。如master1—master2—-slave3。MHA故障转移和恢复是直接从从服务器中选择一台作为当前的主主服务器。MHA可以管理master1和master2,当master1当掉后,将master2作为主,MHA不会监控和恢复slave3因为slave3是从不同的主服务器上(master2)复制的。为了使MHA工作在这种架构下,需要做如下设置: 只在MHA配置文件中配置master1和master2 在MHA配置文件中所有主机上设置multi_tier_slave=1 在这种情况下,MHA只管理主主服务器和二层的从服务器,在故障转移过程中,三层从服务器仍然可以正常工作的。 5.mysql版本5.0或更高 MHA支持mysql5.0或以上版本。因为从mysql5.0版本起二进制日志格式(binlog v4格式)改变了。当MHA解析二进制日志来确定目标中继日志位置,是使用v4格式的。MySQL版本不得低于5.0.60。 6.mysqlbinlog版本3.3或更高 MHA在目标从服务器上应用二进制事件使用mysqlbinlog。如果主服务器使用基于行格式复制,基于行格式的事件写入到二进制文件中,这种二进制日志格式的文件只能被MySQL5.1或更高版本的mysqlbinlog解析。MySQL5.0.60以下版本中的mysqlbinlog不支持基于行格式的。 7.候选主服务器log-bin必须开启 如果当前的从服务器没有开启log-bin,那么将不可能成为主服务器。MHA管理节点会检测是否有配置log-bin。如果当前所有从服务器都没有设置log-bin,那么MHA不进行故障转移。 8.所有服务器上的二进制日志和中继日志过滤规则必须相同 binlog-do-db和replicate-ignore-db设置必须相同。MHA在启动时候会检测过滤规则,如果过滤规则不同,MHA不启动监控和故障转移。 9.候选主服务器上的复制用户必须存在 当故障转移后,所有从服务器上将执行change master to命令。 10.保留中继日志和定期清理 默认情况下,从服务器上的中继日志在SQL线程执行完后会被自动删除的。但是这些中继日志在恢复其他从服务器时候可能会被用到,因此需要禁用中继日志的自动清除和定期清除旧的中继日志。定期清除中继日志需要考虑到复制延时的问题。在ext3文件系统下,删除大的文件需要一定的时间,会导致严重的复制延时。为了避免复制延时,暂时为中继日志创建硬链接。 MHA节点包含pure_relay_logs命令工具,它可以为中继日志创建硬链接,执行SET GLOBAL relay_log_purge=1,等待几秒中以便SQL线程切换到新的中继日志,再执行SET GLOBAL relay_log_purge=0。 pure_relay_logs参数如下所示: –user mysql用户名 –password mysql密码 –host mysql服务器地址 –port 端口号 –workdir 创建和删除中继日志硬链接目录。成功执行脚本后,硬链接的中继日志文件将被删除。默认目录是/var/tmp。 –disable_relay_log_purge 如果relay_log_purge=1,purge_relay_logs脚本将退出不做任何事情。设置–disable_relay_log_purge参数,purge_relay_logs脚本不会退去,且自动设置relay_log_purge=0。 定期执行purge_relay_logs脚本: Purge_relay_logs脚本删除中继日志不会阻塞SQL线程。因此在每台从服务器上设置计划任务定期清除中继日志。 00 00 * * * /usr/bin/purge_relay_logs –user=root –password=passwd –disable_relay_log_purge >> /data/masterha/log/purge_relay_logs.log 2>&1 最好在每台从服务器上不同时间点执行计划任务。 11. LOAD DATA INFILE不要使用基于语句型的二进制日志 如果使用非事务性存储引擎,在执行完LOAD DATA INFILE基于语句型二进制日志时,主服务器当掉,MHA可能不会产生差异的中继日志事件。使用LOAD DATA INFILE基于语句型二进制日志有一些已知问题,在mysql5.1版本中不建议使用,同时还会引起严重的复制延时,因此没有理由使用它。 三.MHA过程 1.监控和故障转移过程 检测复制设置和确定当前主服务器 监控主服务器 检测主服务器当掉 再次检测从服务器配置 关闭当掉的主服务器(可选) 恢复一个新的主服务器 激活新的主服务器 恢复其余的从服务器 告警(可选) 2.在线切换过程 检测复制设置和确定当前主服务器 确定新的主服务器 阻塞写入到当前主服务器 等待所有从服务器赶上复制 授予写入到新的主服务器 重新设置从服务器 四.MHA安装 MHA节点包含三个脚本,依赖perl模块。 save_binary_logs:保存和复制当掉的主服务器二进制日志 apply_diff_relay_logs:识别差异的relay log事件,并应用于其他salve服务器 purge_relay_logs:清除relay log文件 需要在所有mysql服务器上安装MHA节点,MHA管理服务器也需要安装。MHA管理节点模块内部依赖MHA节点模块。MHA管理节点通过ssh连接管理mysql服务器和执行MHA节点脚本。MHA节点依赖perl的DBD::mysql模块。 1.安装MHA Node 在所有的mysql服务器上安装 # apt-get install libdbd-mysql-perl # wget # perl Makefile.PL # make # make install 2.安装MHA Manager # apt-get install libdbd-mysql-perl # wget # perl Makefile.PL # make # make install # apt-get install libconfig-tiny-perl # apt-get install liblog-dispatch-perl # apt-get install libparallel-forkmanager-perl # apt-get install libnet-telnet-perl # wget # tar zxvf mha4mysql-manager-0.52.tar.gz -C ../software/ # perl Makefile.PL # make # make install 五.配置 1.配置主从结构 【node2】 server-id = 101 log-bin=mysql-bin-101 mysql> grant replication slave on *.* to identified by ’replpasswd’; mysql> grant all privileges on *.* to identified by ’123456′; mysql> grant all privileges on *.* to identified by ’123456′; 【node3】 server-id = 103 log-bin=mysql-bin-103 read_only=1 relay_log_purge=0 mysql> grant replication slave on *.* to identified by ’replpasswd’; mysql> grant all privileges on *.* to identified by ’123456′; mysql> grant all privileges on *.* to identified by ’123456′; mysql> change master to -> master_host=’192.168.1.101′, -> master_user=’repl’, -> master_password=’replpasswd’, -> master_log_file=’mysql-bin-101.000003′, -> master_log_pos=660; 【node4】 server-id = 114 log-bin=mysql-bin-114 read_only=1 relay_log_purge=0 mysql> grant replication slave on *.* to identified by ’replpasswd’; mysql> grant all privileges on *.* to identified by ’123456′; mysql> grant all privileges on *.* to identified by ’123456′; mysql> change master to -> master_host=’192.168.1.101′, -> master_user=’repl’, -> master_password=’replpasswd’, -> master_log_file=’mysql-bin-101.000003′, -> master_log_pos=660; 2.配置mha # mkdir /etc/masterha # mkdir -p /masterha/app1 # cp ./mha4mysql-manager-0.52/samples/conf/* /etc/masterha/ # vim app1.cnf [server default] manager_workdir=/masterha/app1 manager_log=/masterha/app1/manager.log user=root password=123456 ssh_user=root repl_user=repl repl_password=replpasswd ping_interval=1 shutdown_script=”" master_ip_failover_script=”/usr/local/bin/master_ip_failover” master_ip_online_change_script=”" report_script=”" [server1] hostname=192.168.1.101 master_binlog_dir=/data/mydata candidate_master=1 [server2] hostname=192.168.1.103 master_binlog_dir=/data/mydata candidate_master=1 [server3] hostname=192.168.1.114 master_binlog_dir=/data/mydata mysql> grant all privileges on *.* to identified by ’123456′; :~# ssh-keygen -t rsa :~# ssh-copy-id -i /root/.ssh/id_rsa.pub :~# ssh-copy-id -i /root/.ssh/id_rsa.pub :~# ssh-copy-id -i /root/.ssh/id_rsa.pub :~# ssh-keygen -t rsa :~# ssh-copy-id -i /root/.ssh/id_rsa.pub :~# ssh-copy-id -i /root/.ssh/id_rsa.pub :~# ssh-keygen -t rsa :~# ssh-copy-id -i /root/.ssh/id_rsa.pub :~# ssh-copy-id -i /root/.ssh/id_rsa.pub :~# ssh-keygen -t rsa :~# ssh-copy-id -i /root/.ssh/id_rsa.pub :~# ssh-copy-id -i /root/.ssh/id_rsa.pub :~# masterha_check_ssh –conf=/etc/masterha/app1.cnf Tue Oct 25 20:51:04 2011 - [info] Reading default configuratoins from /etc/masterha_default.cnf.. Tue Oct 25 20:51:04 2011 - [info] Reading application default configurations from /etc/masterha/app1.cnf.. Tue Oct 25 20:51:04 2011 - [info] Reading server configurations from /etc/masterha/app1.cnf.. Tue Oct 25 20:51:04 2011 - [info] Starting SSH connection tests.. Tue Oct 25 20:51:05 2011 - [debug] Tue Oct 25 20:51:04 2011 - [debug] Connecting via SSH from ) to ).. Tue Oct 25 20:51:05 2011 - [debug] ok. Tue Oct 25 20:51:05 2011 - [debug] Connecting via SSH from ) to ).. Tue Oct 25 20:51:05 2011 - [debug] ok. Tue Oct 25 20:51:05 2011 - [debug] Tue Oct 25 20:51:05 2011 - [debug] Connecting via SSH from ) to ).. Tue Oct 25 20:51:05 2011 - [debug] ok. Tue Oct 25 20:51:05 2011 - [debug] Connecting via SSH from ) to ).. Tue Oct 25 20:51:05 2011 - [debug] ok. Tue Oct 25 20:51:06 2011 - [debug] Tue Oct 25 20:51:05 2011 - [debug] Connecting via SSH from ) to ).. Tue Oct 25 20:51:06 2011 - [debug] ok. Tue Oct 25 20:51:06 2011 - [debug] Connecting via SSH from ) to ).. Tue Oct 25 20:51:06 2011 - [debug] ok. Tue Oct 25 20:51:06 2011 - [info] All SSH connection tests passed successfully. :~# masterha_check_repl –conf=/etc/masterha/app1.cnf Wed Oct 26 20:47:34 2011 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping. Wed Oct 26 20:47:34 2011 - [info] Reading application default configurations from /etc/masterha/app1.cnf.. Wed Oct 26 20:47:34 2011 - [info] Reading server configurations from /etc/masterha/app1.cnf.. Wed Oct 26 20:47:34 2011 - [info] MHA::MasterMonitor version 0.52. Wed Oct 26 20:47:35 2011 - [info] Dead Servers: Wed Oct 26 20:47:35 2011 - [info] Alive Servers: Wed Oct 26 20:47:35 2011 - [info] 192.168.1.101(192.168.1.101:3306) Wed Oct 26 20:47:35 2011 - [info] 192.168.1.103(192.168.1.103:3306) Wed Oct 26 20:47:35 2011 - [info] 192.168.1.114(192.168.1.114:3306) Wed Oct 26 20:47:35 2011 - [info] Alive Slaves: Wed Oct 26 20:47:35 2011 - [info] 192.168.1.103(192.168.1.103:3306) Version=5.5.14-log (oldest major version between slaves) log-bin:enabled Wed Oct 26 20:47:35 2011 - [info] Replicating from 192.168.1.101(192.168.1.101:3306) Wed Oct 26 20:47:35 2011 - [info] Primary candidate for the new Master (candidate_master is set) Wed Oct 26 20:47:35 2011 - [info] 192.168.1.114(192.168.1.114:3306) Version=5.5.14-log (oldest major version between slaves) log-bin:enabled Wed Oct 26 20:47:35 2011 - [info] Replicating from 192.168.1.101(192.168.1.101:3306) Wed Oct 26 20:47:35 2011 - [info] Current Alive Master: 192.168.1.101(192.168.1.101:3306) Wed Oct 26 20:47:35 2011 - [info] Checking slave configurations.. Wed Oct 26 20:47:35 2011 - [info] Checking replication filtering settings.. Wed Oct 26 20:47:35 2011 - [info] binlog_do_db= , binlog_ignore_db= Wed Oct 26 20:47:35 2011 - [info] Replication filtering check ok. Wed Oct 26 20:47:35 2011 - [info] Starting SSH connection tests.. Wed Oct 26 20:47:37 2011 - [info] All SSH connection tests passed successfully. Wed Oct 26 20:47:37 2011 - [info] Checking MHA Node version.. Wed Oct 26 20:47:37 2011 - [info] Version check ok. Wed Oct 26 20:47:37 2011 - [info] Checking SSH publickey authentication and checking recovery script configurations on the current master.. Wed Oct 26 20:47:38 2011 - [info] Executing command: save_binary_logs –command=test –start_file=mysql-bin-101.000003 –start_pos=4 –binlog_dir=/data/mydata –output_file=/var/tmp/save_binary_logs_test –manager_version=0.52 Wed Oct 26 20:47:38 2011 - [info] Connecting to ).. Creating /var/tmp if not exists.. ok. Checking output directory is accessible or not.. ok. Binlog found at /data/mydata, up to mysql-bin-101.000003 Wed Oct 26 20:47:38 2011 - [info] Master setting check done. Wed Oct 26 20:47:38 2011 - [info] Checking SSH publickey authentication and checking recovery script configurations on all alive slave servers.. Wed Oct 26 20:47:38 2011 - [info] Executing command : apply_diff_relay_logs –command=test –slave_user=root –slave_host=192.168.1.103 –slave_ip=192.168.1.103 –slave_port=3306 –workdir=/var/tmp –target_version=5.5.14-log –manager_version=0.52 –relay_log_info=/data/mydata/relay-log.info –slave_pass=xxx Wed Oct 26 20:47:38 2011 - [info] Connecting to ).. Checking slave recovery environment settings.. Opening /data/mydata/relay-log.info … ok. Relay log found at /data/mydata, up to node3-relay-bin.000004 Temporary relay log file is /data/mydata/node3-relay-bin.000004 Testing mysql connection and privileges.. done. Testing mysqlbinlog output.. done. Cleaning up test file(s).. done. Wed Oct 26 20:47:38 2011 - [info] Executing command : apply_diff_relay_logs –command=test –slave_user=root –slave_host=192.168.1.114 –slave_ip=192.168.1.114 –slave_port=3306 –workdir=/var/tmp –target_version=5.5.14-log –manager_version=0.52 –relay_log_info=/data/mydata/relay-log.info –slave_pass=xxx Wed Oct 26 20:47:38 2011 - [info] Connecting to ).. Checking slave recovery environment settings.. Opening /data/mydata/relay-log.info … ok. Relay log found at /data/mydata, up to node4-relay-bin.000002 Temporary relay log file is /data/mydata/node4-relay-bin.000002 Testing mysql connection and privileges.. done. Testing mysqlbinlog output.. done. Cleaning up test file(s).. done. Wed Oct 26 20:47:39 2011 - [info] Slaves settings check done. Wed Oct 26 20:47:39 2011 - [info] 192.168.1.101 (current master) +–192.168.1.103 +–192.168.1.114 Wed Oct 26 20:47:39 2011 - [info] Checking replication health on 192.168.1.103.. Wed Oct 26 20:47:39 2011 - [info] ok. Wed Oct 26 20:47:39 2011 - [info] Checking replication health on 192.168.1.114.. Wed Oct 26 20:47:39 2011 - [info] ok. Wed Oct 26 20:47:39 2011 - [info] Checking master_ip_failvoer_script status: Wed Oct 26 20:47:39 2011 - [info] /usr/local/bin/master_ip_failover –command=status –ssh_user=root –orig_master_host=192.168.1.101 –orig_master_ip=192.168.1.101 –orig_master_port=3306 Wed Oct 26 20:47:39 2011 - [info] OK. Wed Oct 26 20:47:39 2011 - [warning] shutdown_script is not defined. Wed Oct 26 20:47:39 2011 - [info] Got exit code 0 (Not master dead). MySQL Replication Health is OK. :~# masterha_check_status –conf=/etc/masterha/app1.cnf app1 (pid:16179) is running(0:PING_OK), master:192.168.1.101 :~# crontab -l 00 00 * * * /usr/local/bin/purge_relay_logs –user=root –password=123456 –disable_relay_log_purge >> /masterha/purge_relay_logs.log 2>&1 :~# crontab -l 00 01 * * * /usr/local/bin/purge_relay_logs –user=root –password=123456 –disable_relay_log_purge >> /masterha/purge_relay_logs.log 2>&1 3.启动MHA :~# nohup masterha_manager –conf=/etc/masterha/app1.cnf < /dev/null > /masterha/app1/manager.log 2>&1 & 六.测试 :~# pkill mysql* :~# tail -f manager.log 将看到整个过程 —– Failover Report —– app1: MySQL Master failover 192.168.1.101 to 192.168.1.103 succeeded Master 192.168.1.101 is down! Check MHA Manager logs at ubuntu:/masterha/app1/manager.log for details. Started automated(non-interactive) failover. Invalidated master IP address on 192.168.1.101. The latest slave 192.168.1.103(192.168.1.103:3306) has all relay logs for recovery. Selected 192.168.1.103 as a new master. 192.168.1.103: OK: Applying all logs succeeded. Failed to activate master IP address for 192.168.1.103 with return code 10:0 192.168.1.114: This host has the latest relay log events. Generating relay diff files from the latest slave succeeded. 192.168.1.114: OK: Applying all logs succeeded. Slave started, replicating from 192.168.1.103. 192.168.1.103: Resetting slave info succeeded. Master failover to 192.168.1.103(192.168.1.103:3306) completed successfully. node3> show slave hosts; +———–+——+——+———–+ | Server_id | Host | Port | Master_id | +———–+——+——+———–+ | 114 | | 3306 | 103 | +———–+——+——+———–+ node4> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.1.103 成功将主服务器切换到192.168.1.103,同时将从服务器的主切换到192.168.1.103。