一.MHA簡介 作者簡介 松信嘉範: MySQL/Linux專家 2001年索尼公司入職 2001年開始使用oracle 2004年開始使用MySQL 2006年9月 2010年8月MySQL從事顧問 2010年 2012年 DeNA 2012年~至今 Facebook 軟體簡介 MHA能夠在較短的 ...
一.MHA簡介
作者簡介
松信嘉範:
MySQL/Linux專家
2001年索尼公司入職
2001年開始使用oracle
2004年開始使用MySQL
2006年9月-2010年8月MySQL從事顧問
2010年-2012年 DeNA
2012年~至今 Facebook
軟體簡介
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)把宕機的master二進位日誌保存下來。
2)找到binlog位置點最新的slave。
3)在binlog位置點最新的slave上用relay log(差異日誌)修複其它slave。
4)將宕機的master上保存下來的二進位日誌恢復到含有最新位置點的slave上。
5)將含有最新位置點binlog所在的slave提升為master。
6)將其它slave重新指向新提升的master,並開啟主從複製。
三.MHA架構圖

- MHA manager 可以安裝在任意一臺伺服器上
- 一個MHA manager可以管理多套mysql集群(上百套)
- 儘量避免安裝在主庫上(防止主庫斷點,斷網)
- c\s結構的服務
四.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工具包主要包括以下幾個工具:
cd /root/mha4mysql-node-0.56/bin
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的性能和簡單的主從複製框架性能一樣。
ping baidu.com 10.0.0.50(icmp)
sql ping
select ping 檢測主庫的心跳
6)Works with any storage engine
只要replication支持的存儲引擎,MHA都支持,不會局限於innodb
MySQL環境準備
1)環境檢查
mysql-db01
#系統版本
[root@mysql-db01 ~]# cat /etc/redhat-release
CentOS release 6.7 (Final)
#內核版本
[root@mysql-db01 ~]# uname -r
2.6.32-573.el6.x86_64
#IP地址
[root@mysql-db01 ~]# hostname -I
10.0.0.51
mysql-db02
#系統版本
[root@mysql-db02 ~]# cat /etc/redhat-release
CentOS release 6.7 (Final)
#內核版本
[root@mysql-db02 ~]# uname -r
2.6.32-573.el6.x86_64
#IP地址
[root@mysql-db02 ~]# hostname -I
10.0.0.52
mysql-db03
#系統版本
[root@mysql-db03 ~]# cat /etc/redhat-release
CentOS release 6.7 (Final)
#內核版本
[root@mysql-db03 ~]# uname -r
2.6.32-573.el6.x86_64
#IP地址
[root@mysql-db03 ~]# hostname -I
10.0.0.53
安裝MySQL
1)安裝包准備
#創建安裝包存放目錄
[root@mysql-db01 ~]# mkdir /home/oldboy/tools -p
#進入目錄
[root@mysql-db01 ~]# cd /home/oldboy/tools/
#上傳mysql安裝包(mysql-5.6.16-linux-glibc2.5-x86_64.tar.gz)
[root@mysql-db01 tools]# rz -be
2)安裝
#創建安裝目錄
[root@mysql-db01 tools]# mkdir /application
#解壓mysql二進位包
[root@mysql-db01 tools]# tar xf mysql-5.6.16-linux-glibc2.5-x86_64.tar.gz
#移動安裝包
[root@mysql-db01 tools]# mv mysql-5.6.16-linux-glibc2.5-x86_64 /application/mysql-5.6.16
#做軟鏈接
[root@mysql-db01 tools]# ln -s /application/mysql-5.6.16/ /application/mysql
#創建mysql用戶
[root@mysql-db01 tools]# useradd mysql -s /sbin/nologin -M
#進入mysql初始化目錄
[root@mysql-db01 tools]# cd /application/mysql/scripts/
#初始化mysql
[root@mysql-db01 scripts]# ./mysql_install_db \
--user=mysql \
--datadir=/application/mysql/data/ \
--basedir=/application/mysql/
#註解
--user: 指定mysql用戶
--datadir:指定mysql數據存放目錄
--basedir:指定mysql base目錄
#拷貝mysql配置文件
[root@mysql-db01 ~]# \cp /application/mysql/support-files/my-default.cnf /etc/my.cnf
#拷貝mysql啟動腳本
[root@mysql-db01 ~]# cp /application/mysql/support-files/mysql.server /etc/init.d/mysqld
#修改mysql預設安裝目錄(否則無法啟動)
[root@mysql-db01 ~]# sed -i 's#/usr/local#/application#g' /etc/init.d/mysqld
[root@mysql-db01 ~]# sed -i 's#/usr/local#/application#g' /application/mysql/bin/mysqld_safe
#配置mysql環境變數
[root@mysql-db01 ~]# echo 'export PATH="/application/mysql/bin:$PATH"' >> /etc/profile.d/mysql.sh
#刷新環境變數
[root@mysql-db01 ~]# source /etc/profile
2.2.3啟動
#加入開機自啟
[root@mysql-db01 ~]# chkconfig mysqld on
#啟動mysql
[root@mysql-db01 ~]# /etc/init.d/mysqld start
Starting MySQL........... SUCCESS! #啟動成功
2.2.4配置密碼
#配置mysql密碼為oldboy123
[root@mysql-db01 ~]# mysqladmin -uroot password oldboy123
五.基於GTID的主從複製
GTID:全局唯一標識符,由UUID+TID,TID是事務提交編號,提交一個事務+1
342a3b8f-0d8e-11ea-8095-000c29c7dac3:1
342a3b8f-0d8e-11ea-8095-000c29c7dac3:2
342a3b8f-0d8e-11ea-8095-000c29c7dac3:23
先決條件
1)主庫和從庫都要開啟binlog
2)主庫和從庫server-id不同
3)要有主從複製用戶
GTID優點:
(1).支持多線程複製:事實上是針對每個database開啟相應的獨立線程,即每個庫有一個單獨的(sql
thread).
(2).支持啟用GTID,在配置主從複製,傳統的方式里,你需要找到binlog和POS點,然後change master to指向. 在
mysql5.6里,無須再知道binlog和POS點,只需要知道master的IP/埠/賬號密碼即可,因為同步複製是自動的,MySQL通
過內部機制GTID自動找點同步.(show master status)
(3).基於Row複製只保存改變的列,大大節省Disk Space/Network resources和Memory usage.
(4).支持把Master 和Slave的相關信息記錄在Table中 原來是記錄在文件里,記錄在表裡,增強可用性
(5).支持延遲複製
缺點:
- mysqldump備份起來很麻煩,需要額外加參數,--set-gtid=on
- 如果只從複製遇到了錯誤,s起來停了.跳過錯誤,gtid無法跳過錯誤
主庫操作
修改配置文件
#編輯mysql配置文件
[root@mysql-db01 ~]# vim /etc/my.cnf
#在mysqld標簽下配置
[mysqld]
#主庫server-id為1,從庫不等於1
server_id =1
#開啟binlog日誌
log_bin=mysql-bin
創建主從複製用戶
#登錄資料庫
[root@mysql-db01 ~]# mysql -uroot -poldboy123
#創建rep用戶
mysql> grant replication slave on *.* to rep@'10.0.0.%' identified by 'oldboy123';
從庫操作
修改配置文件
#修改mysql-db02配置文件
[root@mysql-db02 ~]# vim /etc/my.cnf
#在mysqld標簽下配置
[mysqld]
#主庫server-id為1,從庫必須大於1
server_id =5
#開啟binlog日誌
log_bin=mysql-bin
#重啟mysql
[root@mysql-db02 ~]# /etc/init.d/mysqld restart
#修改mysql-db03配置文件
[root@mysql-db03 ~]# vim /etc/my.cnf
#在mysqld標簽下配置
[mysqld]
#主庫server-id為1,從庫必須大於1
server_id =10
#開啟binlog日誌
log_bin=mysql-bin
#重啟mysql
[root@mysql-db03 ~]# /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配置文件(主庫從庫都需要修改)
[root@mysql-db01 ~]# vim /etc/my.cnf
#在[mysqld]標簽下添加
[mysqld]
gtid_mode=ON
log_slave_updates #保持binlog刷新
enforce_gtid_consistency
#重啟資料庫
[root@mysql-db01 ~]# /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 | |
+--------------------------+-------+
log-slave-updates 什麼時候用
- 雙主模式
- 級聯複製
- GTID
註:主庫從庫都需要開啟GTID否則在做主從複製的時候就會報錯:
[root@mysql-db02 ~]# 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.
配置主從複製
#登錄資料庫
[root@mysql-db02 ~]# 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
*************************** 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.000003
Read_Master_Log_Pos: 403
Relay_Log_File: mysql-db02-relay-bin.000002
Relay_Log_Pos: 613
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 403
Relay_Log_Space: 822
Until_Condition: None
六.部署MHA(前提已經做好主從,儘量不在主庫上安裝管理節點)
主庫
1.開啟binlog
2.開啟server_id
3.創建主從複製用戶
從庫
1.開啟binlog
2.開啟server_id:從庫與主庫之間的server_id不同即可, 從庫之間不可以相同
3.change master to
4.在做主從之前,要保證數據的一致性
5.從庫也要創建主從複製用戶
前提條件
#臨時關閉relay log(主庫和從庫)
set global relay_log_purge = 0;
# 臨時開啟 只讀(從庫)
set global read_only=1;
# 永久關閉自動刪除relay log(主庫和從庫)
relay_log_purge = 0
1)環境準備(所有節點)
# 安裝node和manager,必須要有epel
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
# 安裝node節點(有幾台資料庫就裝幾個node節點)
[root@db01 ~]# yum localinstall -y mha4mysql-node-0.56-0.el6.noarch.rpm
# 每台資料庫上都要創建 mha 管理用戶(主庫執行從庫會複製)
mysql> grant all on *.* to mha@'%' identified by 'mha';
命令軟連接(所有節點)
#如果不創建命令軟連接,檢測mha複製情況的時候會報錯
[root@mysql-db01 ~]# ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
[root@mysql-db01 ~]# ln -s /application/mysql/bin/mysql /usr/bin/mysql
部署管理節點(mha-manager:mysql-db03)
#安裝manager包
[root@mysql-db03 tools]# rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm
Preparing... ########################################### [100%]
1:mha4mysql-manager ########################################### [100%]
編輯配置文件
#創建配置文件目錄
[root@mysql-db03 ~]# mkdir -p /etc/mha
#創建日誌目錄
[root@mysql-db03 ~]# mkdir -p /etc/mha/app1
#編輯mha配置文件
[root@mysql-db03 ~]# vim /etc/mha/app1.cnf
# 修改配置文件
[server default]
#MHA日誌名字
manager_log=/etc/mha/manager.log
#MHA的工作目錄
manager_workdir=/etc/mha/app1
#資料庫binlog存放路徑
master_binlog_dir=/application/mysql/data
#mha管理用戶的用戶名
user=mha
#mha管理用戶的密碼
password=mha
#監測心跳,每隔2秒監測一次(預設是3秒)
ping_interval=2
#主從複製用戶的密碼
repl_password=123
#主從複製用戶
repl_user=slave
#ssh遠程連接用戶(做完免密的)
ssh_user=root
[server1]
hostname=10.0.0.51
port=3306
[server2]
hostname=10.0.0.52
port=3306
ssh 免密認證
MHA監測啟動
[server3]
hostname=10.0.0.53
port=3306
[server4]
hostname=10.0.0.54
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信任(所有節點)
#創建秘鑰對
[root@mysql-db01 ~]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1
#發送公鑰,包括自己
[root@mysql-db01 ~]# ssh-copy-id -i /root/.ssh/id_dsa.pub [email protected]
[root@mysql-db01 ~]# ssh-copy-id -i /root/.ssh/id_dsa.pub [email protected]
[root@mysql-db01 ~]# ssh-copy-id -i /root/.ssh/id_dsa.pub [email protected]
啟動測試
#測試ssh
[root@mysql-db03 ~]# masterha_check_ssh --conf=/etc/mha/app1.cnf
#看到如下字樣,則測試成功
Tue Mar 7 01:03:33 2017 - [info] All SSH connection tests passed successfully.
#測試複製
[root@mysql-db03 ~]# masterha_check_repl --conf=/etc/mha/app1.cnf
#看到如下字樣,則測試成功
MySQL Replication Health is OK.
啟動MHA
#啟動
[root@mysql-db03 ~]# 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 &
#測試啟動是否成功
[root@db04 scripts]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:7916) is running(0:PING_OK), master:10.0.0.51
切換master測試
#登錄資料庫(db02)
[root@mysql-db02 ~]# 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)
[root@mysql-db03 ~]# 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
#停掉主庫
[root@mysql-db01 ~]# /etc/init.d/mysqld stop
Shutting down MySQL..... SUCCESS!
#登錄資料庫(db02)
[root@mysql-db02 ~]# mysql -uroot -poldboy123
#查看slave狀態
mysql> show slave status\G
#db02的slave已經為空
Empty set (0.00 sec)
#登錄資料庫(db03)
[root@mysql-db03 ~]# 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
mha恢復(傳統的)
#1.恢複舊主庫
[root@db01 ~]# /etc/init.d/mysqld start
Starting MySQL SUCCESS!
#2.在mha日誌中找到change master to
[root@db04 ~]# grep -i 'change master to' /etc/mha/manager.log
Tue Nov 19 20:50:57 2019 - [info] All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='slave', MASTER_PASSWORD='xxx';
Wed Nov 20 03:29:19 2019 - [info] All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000005', MASTER_LOG_POS=120, MASTER_USER='slave', MASTER_PASSWORD='xxx';
#3.在舊主庫中執行change master語句
CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000005', MASTER_LOG_POS=120, MASTER_USER='slave', MASTER_PASSWORD='xxx';
#4.將mha配置文件修複
[server1]
hostname=10.0.0.51
port=3306
#5.啟動mha
[root@db04 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --
ignore_last_failover < /dev/null > /etc/mha/manager.log 2>&1 &
[root@db04 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
#MHA啟動命令 詳解
nohup masterha_manager
#配置文件路徑
--conf=/etc/mha/app1.cnf
#從配置文件中移除主庫
--remove_dead_master_conf
#忽略上次切換
--ignore_last_failover
< /dev/null > /etc/mha/manager.log 2>&1 &
#mha工作機制:在mha一次切換後,會在mha的工作目錄下生成一個lock,鎖文件
註意:重新切換後,再次啟動mha
腳本恢復
#分別放在每個node節點服務下
[root@db03 ~]# vim abc.sh
#!/bin/bash
/etc/init.d/mysqld start
change=`ssh 10.0.0.54 "grep -i 'change master to' /etc/mha/manager.log"|awk -F : '{print $4}'|sed 's#xxx#123#g'`
mysql -e "$change;start slave;"
ssh 10.0.0.54 \cp /etc/mha/app1.cnf.ori /etc/mha/app1.cnf
MHA切換
如果在數據量相同的情況下,根據server標簽,越小優先順序越高
七.配置VIP漂移
VIP漂移的兩種方式
1)通過keepalived的方式,管理虛擬IP的漂移
2)通過MHA自帶腳本方式,管理虛擬IP的漂移
MHA腳本方式
修改配置文件
#編輯配置文件
[root@mysql-db03 ~]# vim /etc/mha/app1.cnf
#在[server default]標簽下添加
[server default]
#使用MHA自帶腳本
master_ip_failover_script=/usr/local/bin/master_ip_failover
編輯腳本
#修改ssh埠.配置文件APP1.cnf和/etc/mha/master_ip_failover都要添加
#根據配置文件中腳本路徑編輯
[root@mysql-db03 ~]# vim /etc/mha/master_ip_failover
#修改以下幾行內容
my $vip = '10.0.0.55/24';
my $key = '0';
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";
#添加執行許可權,否則mha無法啟動
[root@mysql-db03 ~]# chmod +x /etc/mha/master_ip_failover
#語法問題
#格式問題
yum -y install dos2unix
[root@db04 mha]# dos2unix master_ip_failover
dos2unix: converting file master_ip_failover to Unix format ...
手動綁定VIP
#綁定vip
[root@mysql-db01 ~]# ifconfig eth0:0 10.0.0.55/24
#宕掉
ifconfig eth0:0 down
#查看vip
[root@mysql-db01 ~]# ip a |grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 10.0.0.51/24 brd 10.0.0.255 scope global eth0
inet 10.0.0.55/24 brd 10.0.0.255 scope global secondary eth0:0
測試ip漂移
#登錄db02
[root@mysql-db02 ~]# 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.51
Master_User: rep
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000007
Read_Master_Log_Pos: 191
Relay_Log_File: mysql-db02-relay-bin.000002
Relay_Log_Pos: 361
Relay_Master_Log_File: mysql-bin.000007
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
#停掉主庫
[root@mysql-db01 ~]# /etc/init.d/mysqld stop
Shutting down MySQL..... SUCCESS!
#在db03上查看從庫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
#在db01上查看vip信息
[root@mysql-db01 ~]# ip a |grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 10.0.0.51/24 brd 10.0.0.255 scope global eth0
#在db02上查看vip信息
[root@mysql-db02 ~]# ip a |grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 10.0.0.52/24 brd 10.0.0.255 scope global eth0
inet 10.0.0.55/24 brd 10.0.0.255 scope global secondary eth0:0
出現腦裂
1.停止vip
2.重新做從庫指向
預防:
停庫檢查mha配置文件是否補全,沒有,補全,啟動mha
測試動點vip漂移
一、創建建表語句
=============================================
學生表:Student(Sno,Sname,Ssex,Sage,Sdept)
------(學號-主鍵,姓名,性別,年齡,所在系)
=============================================
create table student(
Sno int(10) NOT NULL COMMENT '學號',
Sname varchar(16) NOT NULL COMMENT '姓名',
Ssex char(2) NOT NULL COMMENT '性別',
Sage tinyint(2) NOT NULL default '0' COMMENT '學生年齡',
Sdept varchar(16) default NULL COMMENT '學生所在系別',
PRIMARY KEY (Sno)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
二、批量插入數據腳本
#!/bin/bash
MysqlLogin="mysql -uroot -p123"
i=1
while true
do
${MysqlLogin} -e "insert into test.student values ("$I",'zls"$i"','m','21','computer"$i"');"
((i++))
sleep 2;
done
八.配置binlog-server
修改mha配置文件
[root@mysql-db03 ~]# vim /etc/mha/app1.cnf
[binlog1]
no_master=1
hostname=10.0.0.54 #主庫
master_binlog_dir=/data/mysql/binlog/
備份binlog
#創建備份binlog目錄
[root@mysql-db03 ~]# mkdir -p /data/mysql/binlog/
#進入該目錄
[root@mysql-db03 ~]# cd /data/mysql/binlog/
#備份binlog(進入創鍵目錄下)
[root@mysql-db03 binlog]# mysqlbinlog -R --host=10.0.0.51 --user=mha --password=mha --raw --stop-never mysql-bin.000001 &
#啟動mha
[root@mysql-db03 binlog]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/manager.log 2>&1 &
測試binlog備份
#查看binlog目錄中的binlog
[root@mysql-db03 binlog]# ll
total 44
-rw-r--r-- 1 root root 285 Mar 8 03:11 mysql-bin.000001
#登錄主庫
[root@mysql-db01 ~]# mysql -uroot -poldboy123
#刷新binlog
mysql> flush logs;
#再次查看binlog目錄
[root@mysql-db03 binlog]# ll
total 48
-rw-r--r-- 1 root root 285 Mar 8 03:11 mysql-bin.000001
-rw-r--r-- 1 root root 143 Mar 8 04:00 mysql-bin.000002
九.MySQL中間件Atlas
Atlas簡介
Atlas是由 Qihoo 360公司Web平臺部基礎架構團隊開發維護的一個基於MySQL協議的數據中間層項目。它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基礎上,修改了大量bug,添加了很多功能特性。它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基礎上,修改了大量bug,添加了很多功能特性。
Atlas主要功能
- 1.讀寫分離
- 2.從庫負載均衡
- 3.IP過濾
- 4.自動分表
- 5.DBA可平滑上下線DB
- 6.自動摘除宕機的DB
Atlas相對於官方MySQL-Proxy的優勢
- 1.將主流程中所有Lua代碼用C重寫,Lua僅用於管理介面
- 2.重寫網路模型、線程模型
- 3.實現了真正意義上的連接池
- 4.優化了鎖機制,性能提高數十倍
安裝Atlas
同學們有福了,安裝Atlas真的是炒雞簡單,官方提供的Atlas有兩種:
1)Atlas (普通) : Atlas-2.2.1.el6.x86_64.rpm
2)Atlas (分表) : Atlas-sharding_1.0.1-el6.x86_64.rpm
這裡我們只需要下載普通的即可。
#在主庫安裝,進入安裝包目錄
[root@mysql-db01 ~]# cd /home/oldboy/tools/
#下載Atlas
[root@mysql-db01 tools]#
wget httpss://github.com/Qihoo360/Atlas/releases/download/2.2.1/Atlas-2.2.1.el6.x86_64.rpm
#安裝
[root@mysql-db01 tools]# rpm -ivh Atlas-2.2.1.el6.x86_64.rpm
Preparing... ########################################### [100%]
1:Atlas ########################################### [100%]
編輯配置文件
#進入Atlas工具目錄
[root@mysql-db01 ~]# cd /usr/local/mysql-proxy/bin/
#生成密碼
[root@mysql-db01 bin]# ./encrypt oldboy123
#修改Atlas配置文件
[root@mysql-db01 ~]# vim /usr/local/mysql-proxy/conf/test.cnf #(instance = test)
#Atlas後端連接的MySQL主庫的IP和埠,可設置多項,用逗號分隔
proxy-backend-addresses = 10.0.0.51:3306
#Atlas後端連接的MySQL從庫的IP和埠
proxy-read-only-backend-addresses = 10.0.0.52:3306,10.0.0.53:3306
#用戶名與其對應的加密過的MySQL密碼
pwds = root:1N/CNLSgqXuTZ6zxvGQr9A==
#SQL日誌的開關
sql-log = ON
#Atlas監聽的工作介面IP和埠
proxy-address = 0.0.0.0:3307
#預設字元集,設置該項後客戶端不再需要執行SET NAMES語句
charset = utf8
啟動Atlas
[root@mysql-db01 ~]# /usr/local/mysql-proxy/bin/mysql-proxyd test start
OK: MySQL-Proxy of test is started
Atlas管理介面操作
#用atlas管理用戶登錄
[root@mysql-db01 ~]# mysql -uuser -ppwd -h127.0.0.1 -P2345
#查看可用命令幫助
mysql> select * from help;
#查看後端代理的庫
mysql> SELECT * FROM backends;
+-------------+----------------+-------+------+
| backend_ndx | address | state | type |
+-------------+----------------+-------+------+
| 1 | 10.0.0.51:3307 | up | rw |
| 2 | 10.0.0.53:3307 | up | ro |
| 3 | 10.0.0.52:3307 | up | ro |
+-------------+----------------+-------+------+
#平滑摘除mysql
mysql> REMOVE BACKEND 2;
Empty set (0.00 sec)
#檢查是否摘除成功
mysql> SELECT * FROM backends;
+-------------+----------------+-------+------+
| backend_ndx | address | state | type |
+-------------+----------------+-------+------+
| 1 | 10.0.0.51:3307 | up | rw |
| 2 | 10.0.0.52:3307 | up | ro |
+-------------+----------------+-------+------+
#保存到配置文件中
mysql> SAVE CONFIG;
Empty set (0.06 sec)
mysql> select * from help;
+----------------------------+---------------------------------------------------------+
| command | description |
+----------------------------+---------------------------------------------------------+
| SELECT * FROM help | shows this help |
| SELECT * FROM backends | 查看後端的伺服器狀態 |
| SET OFFLINE $backend_id | 平滑下線 例如:set offline 2; |
| SET ONLINE $backend_id | 平滑上線 例如:set online 2; |
| ADD MASTER $backend | 添加後端主庫:add master 10.0.0.56:3306 |
| ADD SLAVE $backend | 添加後端從庫:add slave 10.0.0.56:3306; |
| REMOVE BACKEND $backend_id | 刪除後端節點: remove backend 1; |
| SELECT * FROM clients | 查看允許連接的客戶端IP |
| ADD CLIENT $client | 添加客戶端IP:add client 10.0.0.51; |
| REMOVE CLIENT $client | 刪除客戶端IP:remove client 10.0.0.51 |
| SELECT * FROM pwds | 查看後端資料庫的用戶和密碼 |
| ADD PWD $pwd | 添加用戶,自動加密:add pwd root:123 |
| ADD ENPWD $pwd | 添加用戶,需要手動加密後的密碼 |
| REMOVE PWD $pwd | 刪除沒有用的用戶:remove pwd xxx; |
| SAVE CONFIG | 保存到配置文件 |
| SELECT VERSION | 查看版本 |
+----------------------------+---------------------------------------------------------+
補充:傳統做法
主配:
[root@db01 scripts]# cat /etc/my.cnf
[mysqld]
log-bin=mysql-bin
server_id=1
#gtid_mode=on
#log-slave-updates
#enforce_gtid_consistency
#relay_log_purge = 0
skip_name_resolve
relay_log_purge = 0
從配:
[root@db02 scripts]# cat /etc/my.cnf
[mysqld]
server_id=2
#gtid_mode=on
log-bin=mysql-bin
#log-slave-updates
#enforce_gtid_consistency
#relay_log_purge = 0
skip_name_resolve
#管理節點:註意擋掉之後節點就沒了,需添加
[root@db04 scripts]# vim /etc/mha/app1.cnf
[server default]
manager_log=/etc/mha/manager.log
manager_workdir=/etc/mha/app1
master_binlog_dir=/application/mysql/data
password=mha
ping_interval=2
repl_password=123
repl_user=slave
ssh_user=root
user=mha
[server2]
hostname=10.0.0.52
port=3306
[server3]
hostname=10.0.0.53
port=3306
[server4]
hostname=10.0.0.54
port=3306
vip漂移,atlas
node節點自動恢復從庫腳本
[root@db02 ~]# cat abc.sh
#!/bin/bash
/etc/init.d/mysqld start
change=`ssh 10.0.0.54 "grep -i 'change master to' /etc/mha/manager.log"|awk -F : '{print $4}'|sed 's#xxx#123#g'`
mysql -e "$change;start slave;"
管理節點調用腳本實現非交互,實現VIP漂移
vim master_ip_failover
''''
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.0.0.55/24';
my $key = '0';
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";
'''
sub start_vip() {
`ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
`ssh $ssh_user\@$orig_master_host \" sh /root/abc.sh \"`;
}
sub stop_vip() {
return 0 unless ($ssh_user);
`ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}
'''
實現atlas管理資料庫腳本
[root@db04 mha]# vim /root/cre.sh
#!/bin/bash
while true;do
succ=`sed -nr 's#^Master.*ted (.*)\.$#\1#gp' /etc/mha/manager.log`
if [[ $succ == 'successfully' ]];then
\cp /etc/mha/app1.cnf.ori /etc/mha/app1.cnf
down_master=`sed -nr 's#^Master (.*)\(.*down\!#\1#gp' /etc/mha/manager.log`
new_master=`sed -rn 's#^Master .*\((.*)\) completed.*#\1#gp' /etc/mha/manager.log`
new_master_num=`mysql -uuser -ppwd -h127.0.0.1 -P2345 -e 'select * from backends;'|grep '$new_master' |awk '{print $1}'`
mysql -uuser -ppwd -h127.0.0.1 -P2345 -e "remove backend ${new_master_num};save config;"
mysql -uuser -ppwd -h127.0.0.1 -P2345 -e "add slave ${down_master}:3306;save config;"
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/manager.log 2>&1 &
else
echo "$(date +%F-%T) MHA沒有切換" > /etc/mha/app1.log
sleep 2
fi
done