1. 程式人生 > >MHA高可用及讀寫分離

MHA高可用及讀寫分離

軟體簡介 MHA能夠在較短的時間內實現自動故障檢測和故障轉移,通常在10-30秒以內;在複製框架中,MHA能夠很好地解決複製過程中的資料一致性問題,由於不需要在現有的replication中新增額外的伺服器,僅需要一個manager節點,而一個Manager能管理多套複製,所以能大大地節約伺服器的數量;另外,安裝簡單,無效能損耗,以及不需要修改現有的複製部署也是它的優勢之處。 MHA還提供線上主庫切換的功能,能夠安全地切換當前執行的主庫到一個新的主庫中(通過將從庫提升為主庫),大概0.5-2秒內即可完成。 MHA由兩部分組成:MHA Manager(管理節點)和MHA Node(資料節點)。MHA Manager可以獨立部署在一臺獨立的機器上管理多個Master-Slave叢集,也可以部署在一臺Slave上。當Master出現故障時,它可以自動將最新資料的Slave提升為新的Master,然後將所有其他的Slave重新指向新的Master。整個故障轉移過程對應用程式是完全透明的。 1.工作流程 1)把宕機的master二進位制日誌儲存下來。 2)找到binlog位置點最新的slave。 3)在binlog位置點最新的slave上用relay log(差異日誌)修復其它slave。 4)將宕機的master上儲存下來的二進位制日誌恢復到含有最新位置點的slave上。 5)將含有最新位置點binlog所在的slave提升為master。 6)將其它slave重新指向新提升的master,並開啟主從複製。 2.MHA工具介紹 MHA軟體由兩部分組成,Manager工具包和Node工具包,具體的說明如下: Manager工具包主要包括以下幾個工具: masterha_check_ssh #檢查MHA的ssh-key masterha_check_repl #檢查主從複製情況 masterha_manger #啟動MHA masterha_check_status #檢測MHA的執行狀態 masterha_master_monitor #檢測master是否宕機 masterha_master_switch #手動故障轉移 masterha_conf_host #手動新增server資訊 masterha_secondary_check #建立TCP連線從遠端伺服器 masterha_stop #停止MHA Node工具包主要包括以下幾個工具: save_binary_logs #儲存宕機的master的binlog apply_diff_relay_logs #識別relay log的差異 filter_mysqlbinlog #防止回滾事件 purge_relay_logs #清除中繼日誌 MHA優點總結 1)Masterfailover and slave promotion can be done very quickly 自動故障轉移快 2)Mastercrash does not result in data inconsistency 主庫崩潰不存在資料一致性問題 3)Noneed to modify current MySQL settings (MHA works with regular MySQL) 不需要對當前mysql環境做重大修改 4)Noneed to increase lots of servers 不需要新增額外的伺服器(僅一臺manager就可管理上百個replication) 5)Noperformance penalty 效能優秀,可工作在半同步複製和非同步複製,當監控mysql狀態時,僅需要每隔N秒向master傳送ping包(預設3秒),所以對效能無影響。你可以理解為MHA的效能和簡單的主從複製框架效能一樣。 6)Works with any storage engine 只要replication支援的儲存引擎,MHA都支援,不會侷限於innodb MySQL環境準備 1)環境檢查 #系統版本 [[email protected] ~]# cat /etc/redhat-release CentOS release 6.7 (Final) #核心版本 [[email protected] ~]# uname -r 2.6.32-573.el6.x86_64 #IP地址 [[email protected] ~]# hostname -I 10.0.0.51 安裝MySQL 1)安裝包準備 #建立安裝包存放目錄 [[email protected] ~]# mkdir /home/oldboy/tools -p #進入目錄 [[email protected] ~]# cd /home/oldboy/tools/ #上傳mysql安裝包(mysql-5.6.16-linux-glibc2.5-x86_64.tar.gz) [
[email protected]
tools]# rz -be 2)安裝 #建立安裝目錄 [[email protected] tools]# mkdir /application #解壓mysql二進位制包 [[email protected] tools]# tar xf mysql-5.6.16-linux-glibc2.5-x86_64.tar.gz #移動安裝包 [[email protected] tools]# mv mysql-5.6.16-linux-glibc2.5-x86_64 /application/mysql-5.6.16 #做軟連結 [
[email protected]
tools]# ln -s /application/mysql-5.6.16/ /application/mysql #建立mysql使用者 [[email protected] tools]# useradd mysql -s /sbin/nologin -M #進入mysql初始化目錄 [[email protected] tools]# cd /application/mysql/scripts/ #初始化mysql [[email protected] scripts]# ./mysql_install_db \ --user=mysql \ --datadir=/application/mysql/data/ \ --basedir=/application/mysql/ #註解 --user: 指定mysql使用者 --datadir:指定mysql資料存放目錄 --basedir:指定mysql base目錄 #拷貝mysql配置檔案 [
[email protected]
~]# \cp /application/mysql/support-files/my-default.cnf /etc/my.cnf #拷貝mysql啟動指令碼 [[email protected] ~]# cp /application/mysql/support-files/mysql.server /etc/init.d/mysqld #修改mysql預設安裝目錄(否則無法啟動) [[email protected] ~]# sed -i 's#/usr/local#/application#g' /etc/init.d/mysqld [[email protected] ~]# sed -i 's#/usr/local#/application#g' /application/mysql/bin/mysqld_safe #配置mysql環境變數 [[email protected] ~]# echo 'export PATH="/application/mysql/bin:$PATH"' >> /etc/profile.d/mysql.sh #重新整理環境變數 [[email protected] ~]# source /etc/profile 2.2.3啟動 #加入開機自啟 [[email protected] ~]# chkconfig mysqld on #啟動mysql [[email protected] ~]# /etc/init.d/mysqld start Starting MySQL........... SUCCESS! #啟動成功 2.2.4配置密碼 #配置mysql密碼為oldboy123 [[email protected] ~]# mysqladmin -uroot password oldboy123 4.基於GTID的主從複製 先決條件 1)主庫和從庫都要開啟binlog 2)主庫和從庫server-id不同 3)要有主從複製使用者 主庫操作 修改配置檔案 #編輯mysql配置檔案 [[email protected] ~]# vim /etc/my.cnf #在mysqld標籤下配置 [mysqld] #主庫server-id為1,從庫不等於1 server_id =1 #開啟binlog日誌 log_bin=mysql-bin 建立主從複製使用者 #登入資料庫 [[email protected] ~]# mysql -uroot -poldboy123 #建立rep使用者 mysql> grant replication slave on *.* to [email protected]'10.0.0.%' identified by 'oldboy123'; 從庫操作 修改配置檔案 #修改mysql-db02配置檔案 [[email protected] ~]# vim /etc/my.cnf #在mysqld標籤下配置 [mysqld] #主庫server-id為1,從庫必須大於1 server_id =5 #開啟binlog日誌 log_bin=mysql-bin #重啟mysql [[email protected] ~]# /etc/init.d/mysqld restart #修改mysql-db03配置檔案 [[email protected] ~]# vim /etc/my.cnf #在mysqld標籤下配置 [mysqld] #主庫server-id為1,從庫必須大於1 server_id =10 #開啟binlog日誌 log_bin=mysql-bin #重啟mysql [[email protected] ~]# /etc/init.d/mysqld restart 注:在以往如果是基於binlog日誌的主從複製,則必須要記住主庫的master狀態資訊。 mysql> show master status; +------------------+----------+ | File | Position | +------------------+----------+ | mysql-bin.000002 | 120 | +------------------+----------+ 開啟GTID #沒開啟之前先看一下GTID的狀態 mysql> show global variables like '%gtid%'; +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | enforce_gtid_consistency | OFF | | gtid_executed | | | gtid_mode | OFF | | gtid_owned | | | gtid_purged | | +--------------------------+-------+ #編輯mysql配置檔案(主庫從庫都需要修改) [[email protected] ~]# vim /etc/my.cnf #在[mysqld]標籤下新增 [mysqld] gtid_mode=ON log_slave_updates enforce_gtid_consistency #重啟資料庫 [[email protected] ~]# /etc/init.d/mysqld restart #檢查GTID狀態 mysql> show global variables like '%gtid%'; +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | enforce_gtid_consistency | ON | #執行GTID一致 | gtid_executed | | | gtid_mode | ON | #開啟GTID模組 | gtid_owned | | | gtid_purged | | +--------------------------+-------+ 注:主庫從庫都需要開啟GTID否則在做主從複製的時候就會報錯: [[email protected] ~]# mysql -uroot -poldboy123 mysql> change master to -> master_host='10.0.0.51', -> master_user='rep', -> master_password='oldboy123', -> master_auto_position=1; ERROR 1777 (HY000): CHANGE MASTER TO MASTER_AUTO_POSITION = 1 can only be executed when @@GLOBAL.GTID_MODE = ON. 配置主從複製 #登入資料庫 [[email protected] ~]# mysql -uroot -poldboy123 #配置複製主機資訊 mysql> change master to #主庫IP -> master_host='10.0.0.51', #主庫複製使用者 -> master_user='rep', #主庫複製使用者的密碼 -> master_password='oldboy123', #GTID位置點 -> master_auto_position=1; #開啟slave mysql> start slave; #檢視slave狀態 mysql> show slave status\G Slave_IO_Running: Yes Slave_SQL_Running: Yes 從庫設定 #登入從庫 [[email protected] ~]# mysql -uroot -poldboy123 #禁用自動刪除relay log 功能 mysql> set global relay_log_purge = 0; #設定只讀 mysql> set global read_only=1; #編輯配置檔案 [[email protected] ~]# vim /etc/my.cnf #在mysqld標籤下新增 [mysqld] #禁用自動刪除relay log 永久生效 relay_log_purge = 0 5.部署MHA #安裝依賴包 [[email protected] ~]# yum install perl-DBD-MySQL -y #進入安裝包存放目錄 [[email protected] ~]# cd /home/oldboy/tools/ #上傳mha安裝包 [[email protected] tools]# rz -be mha4mysql-manager-0.56-0.el6.noarch.rpm mha4mysql-manager-0.56.tar.gz mha4mysql-node-0.56-0.el6.noarch.rpm mha4mysql-node-0.56.tar.gz #安裝node包 [[email protected] tools]# rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm #登入資料庫 [[email protected] tools]# mysql -uroot -poldboy123 #新增mha管理賬號 mysql> grant all privileges on *.* to [email protected]'10.0.0.%' identified by 'mha'; #檢視是否新增成功 mysql> select user,host from mysql.user; #主庫上建立,從庫會自動複製(在從庫上檢視) mysql> select user,host from mysql.user; 命令軟連線(所有節點) #如果不建立命令軟連線,檢測mha複製情況的時候會報錯 [[email protected] ~]# ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog [[email protected] ~]# ln -s /application/mysql/bin/mysql /usr/bin/mysql 部署管理節點(mha-manager:mysql-db03) #使用epel源 [[email protected] ~]# wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-6.repo #安裝manager依賴包 [root[email protected] ~]# yum install -y perl-Config-Tiny epel-release perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes #安裝manager包 [[email protected] tools]# rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm 編輯配置檔案 #建立配置檔案目錄 [[email protected] ~]# mkdir -p /etc/mha #建立日誌目錄 [[email protected] ~]# mkdir -p /var/log/mha/app1 #編輯mha配置檔案 [[email protected] ~]# vim /etc/mha/app1.cnf [server default] manager_log=/var/log/mha/app1/manager manager_workdir=/var/log/mha/app1 master_binlog_dir=/application/mysql/data user=mha password=mha ping_interval=2 repl_password=oldboy123 repl_user=rep ssh_user=root [server1] hostname=10.0.0.51 port=3306 [server2] candidate_master=1 check_repl_delay=0 hostname=10.0.0.52 port=3306 [server3] hostname=10.0.0.53 port=3306 配置檔案詳解 [server default] #設定manager的工作目錄 manager_workdir=/var/log/masterha/app1 #設定manager的日誌 manager_log=/var/log/masterha/app1/manager.log #設定master 儲存binlog的位置,以便MHA可以找到master的日誌,我這裡的也就是mysql的資料目錄 master_binlog_dir=/data/mysql #設定自動failover時候的切換指令碼 master_ip_failover_script= /usr/local/bin/master_ip_failover #設定手動切換時候的切換指令碼 master_ip_online_change_script= /usr/local/bin/master_ip_online_change #設定mysql中root使用者的密碼,這個密碼是前文中建立監控使用者的那個密碼 password=123456 #設定監控使用者root user=root #設定監控主庫,傳送ping包的時間間隔,嘗試三次沒有迴應的時候自動進行failover ping_interval=1 #設定遠端mysql在發生切換時binlog的儲存位置 remote_workdir=/tmp #設定複製使用者的密碼 repl_password=123456 #設定複製環境中的複製使用者名稱 repl_user=rep #設定發生切換後傳送的報警的指令碼 report_script=/usr/local/send_report #一旦MHA到server02的監控之間出現問題,MHA Manager將會嘗試從server03登入到server02 secondary_check_script= /usr/local/bin/masterha_secondary_check -s server03 -s server02 --user=root --master_host=server02 --master_ip=192.168.0.50 --master_port=3306 #設定故障發生後關閉故障主機指令碼(該指令碼的主要作用是關閉主機放在發生腦裂,這裡沒有使用) shutdown_script="" #設定ssh的登入使用者名稱 ssh_user=root [server1] hostname=10.0.0.51 port=3306 [server2] hostname=10.0.0.52 port=3306 #設定為候選master,如果設定該引數以後,發生主從切換以後將會將此從庫提升為主庫,即使這個主庫不是叢集中事件最新的slave。 candidate_master=1 #預設情況下如果一個slave落後master 100M的relay logs的話,MHA將不會選擇該slave作為一個新的master,因為對於這個slave的恢復需要花費很長時間,通過設定check_repl_delay=0,MHA觸發切換在選擇一個新的master的時候將會忽略複製延時,這個引數對於設定了candidate_master=1的主機非常有用,因為這個候選主在切換的過程中一定是新的master check_repl_delay=0 配置ssh信任(所有節點) #建立祕鑰對 [[email protected] ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1 #傳送公鑰,包括自己 [[email protected] ~]# ssh-copy-id -i /root/.ssh/id_dsa.pub [email protected] [[email protected] ~]# ssh-copy-id -i /root/.ssh/id_dsa.pub [email protected] [[email protected] ~]# ssh-copy-id -i /root/.ssh/id_dsa.pub [email protected] 啟動測試 [[email protected] ~]# masterha_check_ssh --conf=/etc/mha/app1.cnf #看到如下字樣,則測試成功 Tue Mar 7 01:03:33 2017 - [info] All SSH connection tests passed successfully. #測試複製 [[email protected] ~]# masterha_check_repl --conf=/etc/mha/app1.cnf #看到如下字樣,則測試成功 MySQL Replication Health is OK. 啟動MHA #啟動 [[email protected] ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 & 切換master測試 #登入資料庫(db02) [[email protected] ~]# mysql -uroot -poldboy123 #檢查複製情況 mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.0.0.51 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000006 Read_Master_Log_Pos: 191 Relay_Log_File: mysql-db02-relay-bin.000002 Relay_Log_Pos: 361 Relay_Master_Log_File: mysql-bin.000006 Slave_IO_Running: Yes Slave_SQL_Running: Yes #登入資料庫(db03) [[email protected] ~]# mysql -uroot -poldboy123 #檢查複製情況 mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.0.0.51 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000006 Read_Master_Log_Pos: 191 Relay_Log_File: mysql-db03-relay-bin.000002 Relay_Log_Pos: 361 Relay_Master_Log_File: mysql-bin.000006 Slave_IO_Running: Yes Slave_SQL_Running: Yes #停掉主庫 [[email protected] ~]# /etc/init.d/mysqld stop #登入資料庫(db02) [[email protected] ~]# mysql -uroot -poldboy123 #檢視slave狀態 mysql> show slave status\G #db02的slave已經為空 Empty set (0.00 sec) #登入資料庫(db03) [[email protected] ~]# mysql -uroot -poldboy123 #檢視slave狀態 mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.0.0.52 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000006 Read_Master_Log_Pos: 191 Relay_Log_File: mysql-db03-relay-bin.000002 Relay_Log_Pos: 361 Relay_Master_Log_File: mysql-bin.000006 Slave_IO_Running: Yes Slave_SQL_Running: Yes