MySQL 高可用叢集架構 MHA 詳解
MHA(Master HighAvailability)目前在MySQL高可用方面是一個相對成熟的解決方案,它由日本DeNA公司youshimaton(現就職於Facebook公司)開發,是一套優秀的作為MySQL高可用性環境下故障切換和主從提升的高可用軟體。在MySQL故障切換過程中,MHA能做到在0~30秒之內自動完成資料庫的故障切換操作,並且在進行故障切換的過程中,MHA能在最大程度上保證資料的一致性,以達到真正意義上的高可用。
MHA裡有兩個角色一個是MHA Node(資料節點)另一個是MHA Manager(管理節點)。
MHA Manager可以單獨部署在一臺獨立的機器上管理多個master-slave叢集,也可以部署在一臺slave節點上。MHA Node執行在每臺MySQL伺服器上,MHA Manager會定時探測叢集中的master節點,當master出現故障時,它可以自動將最新資料的slave提升為新的master,然後將所有其他的slave重新指向新的master。整個故障轉移過程對應用程式完全透明。
在MHA自動故障切換過程中,MHA試圖從宕機的主伺服器上儲存二進位制日誌,最大程度的保證資料的不丟失,但這並不總是可行的。例如,如果主伺服器硬體故障或無法通過ssh訪問,MHA沒法儲存二進位制日誌,只進行故障轉移而丟失了最新的資料。使用MySQL 5.5的半同步複製,可以大大降低資料丟失的風險。MHA可以與半同步複製結合起來。如果只有一個slave已經收到了最新的二進位制日誌,MHA可以將最新的二進位制日誌應用於其他所有的slave伺服器上,因此可以保證所有節點的資料一致性。
注:從MySQL5.5開始,MySQL以外掛的形式支援半同步複製。如何理解半同步呢?首先我們來看看非同步,全同步的概念:
非同步複製(Asynchronous replication)
MySQL預設的複製即是非同步的,主庫在執行完客戶端提交的事務後會立即將結果返給給客戶端,並不關心從庫是否已經接收並處理,這樣就會有一個問題,主如果crash掉了,此時主上已經提交的事務可能並沒有傳到從上,如果此時,強行將從提升為主,可能導致新主上的資料不完整。
全同步複製(Fully synchronous replication)
指當主庫執行完一個事務,所有的從庫都執行了該事務才返回給客戶端。因為需要等待所有從庫執行完該事務才能返回,所以全同步複製的效能必然會受到嚴重的影響。
半同步複製(Semisynchronous replication
介於非同步複製和全同步複製之間,主庫在執行完客戶端提交的事務後不是立刻返回給客戶端,而是等待至少一個從庫接收到並寫到relay log中才返回給客戶端。相對於非同步複製,半同步複製提高了資料的安全性,同時它也造成了一定程度的延遲,這個延遲最少是一個TCP/IP往返的時間。所以,半同步複製最好在低延時的網路中使用。
下面來看看半同步複製的原理圖:
總結:非同步與半同步異同
預設情況下MySQL的複製是非同步的,Master上所有的更新操作寫入Binlog之後並不確保所有的更新都被複制到Slave之上。非同步操作雖然效率高,但是在Master/Slave出現問題的時候,存在很高資料不同步的風險,甚至可能丟失資料。 MySQL5.5引入半同步複製功能的目的是為了保證在master出問題的時候,至少有一臺Slave的資料是完整的。在超時的情況下也可以臨時轉入非同步複製,保障業務的正常使用,直到一臺salve追趕上之後,繼續切換到半同步模式。
工作原理:
相較於其它HA軟體,MHA的目的在於維持MySQL Replication中Master庫的高可用性,其最大特點是可以修復多個Slave之間的差異日誌,最終使所有Slave保持資料一致,然後從中選擇一個充當新的Master,並將其它Slave指向它。
-從宕機崩潰的master儲存二進位制日誌事件(binlogevents)。
-識別含有最新更新的slave。
-應用差異的中繼日誌(relay log)到其它slave。
-應用從master儲存的二進位制日誌事件(binlogevents)。
-提升一個slave為新master。
-使其它的slave連線新的master進行復制。
目前MHA主要支援一主多從的架構,要搭建MHA,要求一個複製叢集中必須最少有三臺資料庫伺服器,一主二從,即一臺充當master,一臺充當備用master,另外一臺充當從庫,因為至少需要三臺伺服器。
部署環境如下:
角色 | Ip | 主機名 | os |
master | 192.168.137.134 | master | CentOS 6.5 x86_64 |
Candidate | 192.168.137.130 | Candidate | |
slave+manage | 192.168.137.146 | slave |
其中master對外提供寫服務,Candidate為備選master,管理節點放在純slave機器上。master一旦宕機,Candidate提升為主庫
一、基礎環境準備
1、在3臺機器上配置epel源
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
rpm -ivh http://dl.Fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
2、建立ssh無互動登入環境,
[[email protected] ~]#ssh-keygen -t rsa -P ''
chmod 600 .ssh/*
cat .ssh/id_rsa.pub >.ssh/authorized_keys
scp -p .ssh/id_rsa .ssh/authorized_keys 192.168.137.130:/root/.ssh
scp -p .ssh/id_rsa .ssh/authorized_keys 192.168.137.146:/root/.ssh
二、配置mysql半同步複製
注意:mysql主從複製操作此處不做演示
master授權:
grant replication slave,replication client on *.* to 'repl'@'192.168.137.%' identified by '123456';
grant all on *.* to 'mhauser'@'192.168.137.%' identified by '123456';
Candidate授權:
grant replication slave,replication client on *.* to 'repl'@'192.168.137.%' identified by '123456';
grant all on *.* to 'mhauser'@'192.168.137.%' identified by '123456';
slave授權:
grant all on *.* to 'mhauser'@'192.168.137.%' identified by '123456';
如果用mysql預設的非同步模式,當主庫硬體損壞宕機造成的資料丟失,因此在配置MHA的同時建議配置成MySQL的半同步複製。
注:mysql半同步外掛是由谷歌提供,具體位置/usr/local/mysql/lib/plugin/下,一個是master用的semisync_master.so,一個是slave用的semisync_slave.so,
mysql> show variables like '%plugin_dir%';
+---------------+------------------------------+
| Variable_name | Value |
+---------------+------------------------------+
| plugin_dir | /usr/local/mysql/lib/plugin/ |
+---------------+------------------------------+
1、分別在主從節點上安裝相關的外掛(master,Candidate,slave)
在MySQL上安裝外掛需要資料庫支援動態載入。檢查是否支援,用如下檢測:
mysql> show variables like '%have_dynamic_loading%';
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| have_dynamic_loading | YES
所有mysql資料庫伺服器,安裝半同步外掛(semisync_master.so,semisync_slave.so)
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
檢查Plugin是否已正確安裝: mysql> show plugins; 或 mysql> select * from information_schema.plugins;
檢視半同步相關資訊
mysql> show variables like '%rpl_semi_sync%';
rpl_semi_sync_master_enabled | OFF |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_slave_enabled | OFF |
| rpl_semi_sync_slave_trace_level | 32
上圖可以看到半同複製外掛已經安裝,只是還沒有啟用,所以是OFF
2、修改my.cnf檔案,配置主從同步:
注:若主MYSQL伺服器已經存在,只是後期才搭建從MYSQL伺服器,在置配資料同步前應先將主MYSQL伺服器的要同步的資料庫拷貝到從MYSQL伺服器上(如先在主MYSQL上備份資料庫,再用備份在從MYSQL伺服器上恢復)
master mysql主機:
server-id = 1 log-bin=mysql-bin binlog_format=mixed
log-bin-index=mysql-bin.index
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=10000
rpl_semi_sync_slave_enabled=1
relay_log_purge=0
relay-log= relay-bin
relay-log-index = relay-bin.index
注:
rpl_semi_sync_master_enabled=1 1表是啟用,0表示關閉
rpl_semi_sync_master_timeout=10000:毫秒單位,該引數主伺服器等待確認訊息10秒後,不再等待,變為非同步方式。
Candidate 主機:
server-id = 2 log-bin=mysql-bin binlog_format=mixed
log-bin-index=mysql-bin.index
relay_log_purge=0
relay-log= relay-bin
relay-log-index = slave-relay-bin.index
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=10000
rpl_semi_sync_slave_enabled=1
注:relay_log_purge=0,禁止 SQL 執行緒在執行完一個 relay log 後自動將其刪除,對於MHA場景下,對於某些滯後從庫的恢復依賴於其他從庫的relaylog,因此採取禁用自動刪除功能
Slave主機:
Server-id = 3
log-bin = mysql-bin
relay-log = relay-bin
relay-log-index = slave-relay-bin.index read_only = 1
rpl_semi_sync_slave_enabled = 1
檢視半同步相關資訊
mysql> show variables like '%rpl_semi_sync%';
檢視半同步狀態:
mysql> show status like '%rpl_semi_sync%';
| Rpl_semi_sync_master_clients | 2 |
重點關注的引數:
rpl_semi_sync_master_status :顯示主服務是非同步複製模式還是半同步複製模式
rpl_semi_sync_master_clients :顯示有多少個從伺服器配置為半同步複製模式
rpl_semi_sync_master_yes_tx :顯示從伺服器確認成功提交的數量
rpl_semi_sync_master_no_tx :顯示從伺服器確認不成功提交的數量
rpl_semi_sync_master_tx_avg_wait_time :事務因開啟 semi_sync ,平均需要額外等待的時間
rpl_semi_sync_master_net_avg_wait_time :事務進入等待佇列後,到網路平均等待時間
三、配置mysql-mha
-
所有mysql節點安裝
rpm -ivh perl-DBD-MySQL-4.013-3.el6.i686.rpm [yum -y install perl-DBD-MySQL]
rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm
2. manage需安裝依賴的perl包
rpm -ivh perl-Config-Tiny-2.12-7.1.el6.noarch.rpm
rpm -ivh perl-DBD-MySQL-4.013-3.el6.i686.rpm [yum -y install perl-DBD-MySQL]
rpm -ivh compat-db43-4.3.29-15.el6.x86_64.rpm
rpm -ivh perl-Mail-Sender-0.8.16-3.el6.noarch.rpm
rpm -ivh perl-Parallel-ForkManager-0.7.9-1.el6.noarch.rpm
rpm -ivh perl-TimeDate-1.16-11.1.el6.noarch.rpm
rpm -ivh perl-MIME-Types-1.28-2.el6.noarch.rpm
rpm -ivh perl-MailTools-2.04-4.el6.noarch.rpm
rpm -ivh perl-Email-Date-Format-1.002-5.el6.noarch.rpm
rpm -ivh perl-Params-Validate-0.92-3.el6.x86_64.rpm
rpm -ivh perl-Params-Validate-0.92-3.el6.x86_64.rpm
rpm -ivh perl-MIME-Lite-3.027-2.el6.noarch.rpm
rpm -ivh perl-Mail-Sendmail-0.79-12.el6.noarch.rpm
rpm -ivh perl-Log-Dispatch-2.27-1.el6.noarch.rpm
yum install -y perl-Time-HiRes-1.9721-144.el6.x86_64
rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm
3. 配置mha
配置檔案位於管理節點,通常包括每一個mysql server的主機名,mysql使用者名稱,密碼,工作目錄等等。
mkdir /etc/masterha/
vim /etc/masterha/app1.cnf
[server default]
user=mhauser
password=123456
manager_workdir=/data/masterha/app1
manager_log=/data/masterha/app1/manager.log
remote_workdir=/data/masterha/app1
ssh_user=root
repl_user=repl
repl_password=123456
ping_interval=1
[server1]
hostname=192.168.137.134
port=3306
master_binlog_dir=/usr/local/mysql/data
candidate_master=1
[server2]
hostname=192.168.137.130
port=3306
master_binlog_dir=/usr/local/mysql/data
candidate_master=1
[server3]
hostname=192.168.137.146
port=3306
master_binlog_dir=/usr/local/mysql/data
no_master=1
配關配置項的解釋:
manager_workdir=/masterha/app1//設定manager的工作目錄
manager_log=/masterha/app1/manager.log//設定manager的日誌
user=manager//設定監控使用者manager
password=123456 //監控使用者manager的密碼
ssh_user=root //ssh連線使用者
repl_user=mharep //主從複製使用者
repl_password=123.abc//主從複製使用者密碼
ping_interval=1 //設定監控主庫,傳送ping包的時間間隔,預設是3秒,嘗試三次沒有迴應的時候自動進行failover
master_binlog_dir=/usr/local/mysql/data //設定master 儲存binlog的位置,以便MHA可以找到master的日誌,我這裡的也就是mysql的資料目錄
candidate_master=1//設定為候選master,如果設定該引數以後,發生主從切換以後將會將此從庫提升為主庫。
檢測各節點間ssh互信通訊配置是否ok
masterha_check_ssh --conf=/etc/masterha/app1.cnf
結果:All SSH connection tests passed successfully.
檢測各節點間主從複製是否ok
masterha_check_repl --conf=/etc/masterha/app1.cnf
結果:MySQL Replication Health is OK.
在驗證時,若遇到這個錯誤:Can't exec "mysqlbinlog" ......
解決方法是在所有伺服器上執行:
ln -s /usr/local/mysql/bin/* /usr/local/bin/
啟動manager:
nohup /usr/bin/masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf --ignore_last_failover > /etc/masterha/manager.log 2>&1 &
--remove_dead_master_conf 為主從切換後,老的主庫IP將會從配置檔案中移除
--ignore_last_failover 忽略生成的切換完成檔案,若不忽略,則8小時內無法再次切換
--ignore_fail_on_start
##當有slave 節點宕掉時,MHA預設是啟動不了的,加上此引數即使有節點宕掉也能啟動MHA,
關閉MHA:
masterha_stop --conf=/etc/masterha/app1.cnf
檢視MHA狀態:
masterha_check_status --conf=/etc/masterha/app1.cnf
app1 (pid:45128) is running(0:PING_OK), master:192.168.137.134
4.模擬故障轉移
-
停掉master,
/etc/init.d/mysqld stop
-
檢視 MHA 日誌 /data/masterha/app1/manager.log
----- Failover Report -----
app1: MySQL Master failover 192.168.137.134(192.168.137.134:3306) to 192.168.137.1
30(192.168.137.130:3306) succeeded
Master 192.168.137.134(192.168.137.134:3306) is down!
Check MHA Manager logs at zifuji:/data/masterha/app1/manager.log for details.
Started automated(non-interactive) failover.
The latest slave 192.168.137.130(192.168.137.130:3306) has all relay logs for reco
very.
Selected 192.168.137.130(192.168.137.130:3306) as a new master.
192.168.137.130(192.168.137.130:3306): OK: Applying all logs succeeded.
192.168.137.146(192.168.137.146:3306): This host has the latest relay log events.
Generating relay diff files from the latest slave succeeded.
192.168.137.146(192.168.137.146:3306): OK: Applying all logs succeeded. Slave star
ted, replicating from 192.168.137.130(192.168.137.130:3306)
192.168.137.130(192.168.137.130:3306): Resetting slave info succeeded.
Master failover to 192.168.137.130(192.168.137.130:3306) completed successfully.
3. 檢視slave複製狀態
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.137.130
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003