MHA有如下特性:
主服務器的自動監(jiān)控和故障轉移
MHA監(jiān)控復制架構的主服務器,一旦檢測到主服務器故障,就會自動進行故障轉移。即使有些從服務器沒有收到最新的relay log,MHA自動從最新的從服務器上識別差異的relay log并把這些日志應用到其他從服務器上,因此所有的從服務器保持一致性了。MHA通常在幾秒內完成故障轉移,9-12秒可以檢測出主服務器故障,7-10秒內關閉故障的主服務器以避免腦裂,幾秒中內應用差異的relay log到新的主服務器上,整個過程可以在10-30s內完成。還可以設置優(yōu)先級指定其中的一臺slave作為master的候選人。由于MHA在slaves之間修復一致性,因此可以將任何slave變成新的master,而不會發(fā)生一致性的問題,從而導致復制失敗。
交互式主服務器故障轉移
可以只使用MHA的故障轉移,而不用于監(jiān)控主服務器,當主服務器故障時,人工調用MHA來進行故障故障。
非交互式的主故障轉移
不監(jiān)控主服務器,但自動實現(xiàn)故障轉移。這種特征適用于已經使用其他軟件來監(jiān)控主服務器狀態(tài),比如heartbeat來檢測主服務器故障和虛擬IP地址接管,可以使用MHA來實現(xiàn)故障轉移和slave服務器晉級為master服務器。
在線切換主服務器
在許多情況下,需要將現(xiàn)有的主服務器遷移到另外一臺服務器上。比如主服務器硬件故障,RAID控制卡需要重建,將主服務器移到性能更好的服務器上等等。維護主服務器引起性能下降,導致停機時間至少無法寫入數(shù)據(jù)。另外,阻塞或殺掉當前運行的會話會導致主主之間數(shù)據(jù)不一致的問題發(fā)生。MHA提供快速切換和優(yōu)雅的阻塞寫入,這個切換過程只需要0.5-2s的時間,這段時間內數(shù)據(jù)是無法寫入的。在很多情況下,0.5-2s的阻塞寫入是可以接受的。因此切換主服務器不需要計劃分配維護時間窗口(呵呵,不需要你在夜黑風高時通宵達旦完成切換主服務器的任務)。
注:MHA可以應用于任何復制結構
二.MHA所需條件
SSH公鑰驗證
MHA管理節(jié)點通過ssh連接mysql服務器,MHA節(jié)點通過scp發(fā)送最新的relay log到其他slaves服務器上。為了使這些過程自動化,使用SSH公鑰驗證密碼。
操作系統(tǒng)
MHA目前只支持Linux系統(tǒng)
單臺可寫主服務器和多臺從服務器或只讀主服務器
當主服務器當?shù)魰r,MHA修復從服務器之間數(shù)據(jù)一致性。MHA試圖從當?shù)舻闹鞣掌魃媳4嫔形窗l(fā)送的二進制日志文件并應用于所有從服務器。如果只有一個從服務器,就不需在意從服務器之間一致性問題。即使只有一個從服務器,MHA也會從當?shù)舻闹鞣掌魃媳4嫔形窗l(fā)送的二進制日志事件只要能通過ssh訪問到主服務器。使用半同步復制可以解決當主服務器當?shù)艉?,無法ssh到主服務器上保存尚未發(fā)送的二進制日志事件。
從MHA Manager0.52版本開始,支持多主復制結構。只允許其中一臺主服務器可寫,其他主服務器必須設置read-only=1。默認情況下,被管理服務器應該是兩層復制結構。
在三層或三層以上復制情況下
默認情況下,MHA不支持三層或三層以上的復制結構。如master1—master2—-slave3。MHA故障轉移和恢復是直接從從服務器中選擇一臺作為當前的主主服務器。MHA可以管理master1和master2,當master1當?shù)艉?,將master2作為主,MHA不會監(jiān)控和恢復slave3因為slave3是從不同的主服務器上(master2)復制的。為了使MHA工作在這種架構下,需要做如下設置:
只在MHA配置文件中配置master1和master2
在MHA配置文件中所有主機上設置multi_tier_slave=1
在這種情況下,MHA只管理主主服務器和二層的從服務器,在故障轉移過程中,三層從服務器仍然可以正常工作的。
mysql版本5.0或更高
MHA支持mysql5.0或以上版本。因為從mysql5.0版本起二進制日志格式(binlog v4格式)改變了。當MHA解析二進制日志來確定目標中繼日志位置,是使用v4格式的。MySQL版本不得低于5.0.60。
mysqlbinlog版本3.3或更高
MHA在目標從服務器上應用二進制事件使用mysqlbinlog。如果主服務器使用基于行格式復制,基于行格式的事件寫入到二進制文件中,這種二進制日志格式的文件只能被MySQL5.1或更高版本的mysqlbinlog解析。MySQL5.0.60以下版本中的mysqlbinlog不支持基于行格式的。
候選主服務器log-bin必須開啟
如果當前的從服務器沒有開啟log-bin,那么將不可能成為主服務器。MHA管理節(jié)點會檢測是否有配置log-bin。如果當前所有從服務器都沒有設置log-bin,那么MHA不進行故障轉移。
所有服務器上的二進制日志和中繼日志過濾規(guī)則必須相同
binlog-do-db和replicate-ignore-db設置必須相同。MHA在啟動時候會檢測過濾規(guī)則,如果過濾規(guī)則不同,MHA不啟動監(jiān)控和故障轉移。
候選主服務器上的復制用戶必須存在
當故障轉移后,所有從服務器上將執(zhí)行change master to命令。
保留中繼日志和定期清理
默認情況下,從服務器上的中繼日志在SQL線程執(zhí)行完后會被自動刪除的。但是這些中繼日志在恢復其他從服務器時候可能會被用到,因此需要禁用中繼日志的自動清除和定期清除舊的中繼日志。定期清除中繼日志需要考慮到復制延時的問題。在ext3文件系統(tǒng)下,刪除大的文件需要一定的時間,會導致嚴重的復制延時。為了避免復制延時,暫時為中繼日志創(chuàng)建硬鏈接。
MHA節(jié)點包含pure_relay_logs命令工具,它可以為中繼日志創(chuàng)建硬鏈接,執(zhí)行SET GLOBAL relay_log_purge=1,等待幾秒中以便SQL線程切換到新的中繼日志,再執(zhí)行SET GLOBAL relay_log_purge=0。
pure_relay_logs參數(shù)如下所示:
–user mysql用戶名
–password mysql密碼
–host mysql服務器地址
–port 端口號
–workdir 創(chuàng)建和刪除中繼日志硬鏈接目錄。成功執(zhí)行腳本后,硬鏈接的中繼日志文件將被刪除。默認目錄是/var/tmp。
–disable_relay_log_purge 如果relay_log_purge=1,purge_relay_logs腳本將退出不做任何事情。設置–disable_relay_log_purge參數(shù),purge_relay_logs腳本不會退去,且自動設置relay_log_purge=0。
定期執(zhí)行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
最好在每臺從服務器上不同時間點執(zhí)行計劃任務。
11. LOAD DATA INFILE不要使用基于語句型的二進制日志
如果使用非事務性存儲引擎,在執(zhí)行完LOAD DATA INFILE基于語句型二進制日志時,主服務器當?shù)?,MHA可能不會產生差異的中繼日志事件。使用LOAD DATA INFILE基于語句型二進制日志有一些已知問題,在mysql5.1版本中不建議使用,同時還會引起嚴重的復制延時,因此沒有理由使用它。
三.MHA過程
1.監(jiān)控和故障轉移過程
檢測復制設置和確定當前主服務器
監(jiān)控主服務器
檢測主服務器當?shù)?BR>再次檢測從服務器配置
關閉當?shù)舻闹鞣掌?可選)
恢復一個新的主服務器
激活新的主服務器
恢復其余的從服務器
告警(可選)
2.在線切換過程
檢測復制設置和確定當前主服務器
確定新的主服務器
阻塞寫入到當前主服務器
等待所有從服務器趕上復制
授予寫入到新的主服務器
重新設置從服務器
四.MHA安裝
MHA節(jié)點包含三個腳本,依賴perl模塊。
save_binary_logs:保存和復制當?shù)舻闹鞣掌鞫M制日志
apply_diff_relay_logs:識別差異的relay log事件,并應用于其他salve服務器
purge_relay_logs:清除relay log文件
需要在所有mysql服務器上安裝MHA節(jié)點,MHA管理服務器也需要安裝。MHA管理節(jié)點模塊內部依賴MHA節(jié)點模塊。MHA管理節(jié)點通過ssh連接管理mysql服務器和執(zhí)行MHA節(jié)點腳本。MHA節(jié)點依賴perl的DBD::mysql模塊。
安裝MHA Node
在所有的mysql服務器上安裝
# apt-get install libdbd-mysql-perl
# wget http://mysql-master-ha./files/mha4mysql-node-0.52.tar.gz
# perl Makefile.PL
# make
# make install
安裝MHA Manager
# apt-get install libdbd-mysql-perl
# wget http://mysql-master-ha./files/mha4mysql-node-0.52.tar.gz
# 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 http://mysql-master-ha./files/mha4mysql-manager-0.52.tar.gz
# tar zxvf mha4mysql-manager-0.52.tar.gz -C ../software/
# perl Makefile.PL
# make
# make install
五.MHA配置
配置主從結構
【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
啟動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。