MHA(Master High Availability)目前在MySQL高可用方面是一個相對成熟的解決方案,它由日本DeNA公司youshimaton(現就任於Facebook公司)開發,是一套優秀的做爲MySQL高可用性環境下故障切換和主從提高的高可用軟件。在MySQL故障切換過程當中,MHA能作到在10~30秒以內自動完成數據庫的故障切換操做,而且在進行故障切換的過程當中,MHA能在最大程度上保證數據的一致性,以達到真正意義上的高可用。html
MHA可以在較短的時間內實現自動故障檢測和故障轉移,一般在10-30秒之內;在複製 框架中,MHA可以很好地解決複製過程當中的數據一致性問題,因爲不須要在現有的 replication中添加額外的服務器,僅須要一個manager節點,而一個Manager能管理多套複製,因此能大大地節約服務器的數量;另外,安裝簡單,無性能損耗,以及不須要修改現 有的複製部署也是它的優點之處。前端
MHA還提供在線主庫切換的功能,可以安全地切換當前運行的主庫到一個新的主庫中 (經過將從庫提高爲主庫),大概0.5-2秒內便可完成。node
該軟件由兩部分組成:MHA Manager(管理節點)和MHA Node(數據節點)。MHA Manager能夠單獨部署在一臺獨立的機器上管理多個master-slave集羣,也能夠部署在一臺slave節點上。MHA Node運行在每臺MySQL服務器上,MHA Manager會定時探測集羣中的master節點,當master出現故障時,它能夠自動將最新數據的slave提高爲新的master,而後將全部其餘的slave從新指向新的master。整個故障轉移過程對應用程序徹底透明。mysql
在MHA自動故障切換過程當中,MHA試圖從宕機的主服務器上保存二進制日誌,最大程度的保證數據的不丟失,但這並不老是可行的。例如,若是主服務器硬件故障或沒法經過ssh訪問,MHA無法保存二進制日誌,只進行故障轉移而丟失了最新的數據。使用MySQL 5.5的半同步複製,能夠大大下降數據丟失的風險。git
MHA能夠與半同步複製結合起來。若是隻有一個slave已經收到了最新的二進制日誌,MHA能夠將最新的二進制日誌應用於其餘全部的slave服務器上,所以能夠保證全部節點的數據一致性。程序員
目前MHA主要支持一主多從的架構,要搭建MHA,要求一個複製集羣中必須最少有三臺數據庫服務器,一主二從,即一臺充當master,一臺充當備用master,另一臺充當從庫,由於至少須要三臺服務器,出於機器成本的考慮,淘寶也在該基礎上進行了改造,目前淘寶TMHA已經支持一主一從。github
工做原理說明: 一、保存master上的全部binlog事件 二、找到含有最新binlog位置點的slave 三、經過中繼日誌將數據恢復到其餘的slave 四、將包含最新binlog位置點的slave提高爲master 五、將其餘從庫slave指向新的master原slave01 並開啓主從複製 六、將保存下來的binlog恢復到新的master上 | |
---|---|
一、監控全部node節點MHA功能說明:web
二、自動故障切換(failover)面試
前提是必須有三個節點存在,而且有兩個從庫sql
(1)選主前提,按照配置文件的順序進行,可是若是此節點後主庫100M以上relay-log 就不會選
(2)若是你設置了權重,總會切換帶此節點;通常在多地多中心的狀況下,通常會把權重設置在本地節點。
(3)選擇s1爲新主
(4)保存主庫binlog日誌
三、從新構建主從
(1)將有問題的節點剔除MHA
進行第一階段數據補償,S2缺失部分補全90
(2)s1切換角色爲新主,將s2指向新主S1
s2 change master to s1
(3) 第二階段數據補償
將保存過來的新主和原有主缺失部分的binlog,應用到新主。
(4)虛擬IP漂移到新主,對應用透明無感知
(5)通知管理員故障切換
MHA軟件由兩部分組成,Manager工具包和Node工具包,具體的說明以下:
Manager工具包主要包括如下幾個工具:
masterha_check_ssh #檢査 MHA 的 ssh-key^ masterha_check_repl #檢査主從複製狀況 masterha_manger #啓動MHA masterha_check_status #檢測MHA的運行狀態^ masterha_mast er_monitor #檢測master是否宕機一 masterha_mast er_switch #手動故障轉移— masterha_conf_host #手動添加server倍息一 masterha_secondary_check #創建TCP鏈接從遠程服務器v masterha_stop #中止MHA
Node工具包主要包括如下幾個工具:
save_binary_1ogs #保存宕機的master的binlog apply_diff_relay_logs #識別relay log的差別 filter_mysqlbinlog #防止回滾事件一MHA已再也不使用這個工具 purge_relay_logs #清除中繼曰志一不會阻塞SQL線程
一、自動故障轉移
二、主庫崩潰不存在數據不一致的狀況
三、不須要對當前的mysql環境作重大修改
四、不須要添加額外的服務器
五、性能優秀,能夠工做再半同步和異步複製框架
六、只要replication支持的存儲引擎mha都支持
在本次的實驗中,共須要用到三臺主機,系統、軟件說明以下。
db01主機(master)
[root@db01 ~]# cat /etc/redhat-release CentOS release 6.9 (Final) [root@db01 ~]# uname -r 2.6.32-696.el6.x86_64 [root@db01 ~]# /etc/init.d/iptables status iptables: Firewall is not running. [root@db01 ~]# getenforce Disabled [root@db01 ~]# hostname -I 10.0.0.51 172.16.1.51
db02主機(slave1)
1 [root@db02 ~]# cat /etc/redhat-release 2 CentOS release 6.9 (Final) 3 [root@db02 ~]# uname -r 4 2.6.32-696.el6.x86_64 5 [root@db02 ~]# /etc/init.d/iptables status 6 iptables: Firewall is not running. 7 [root@db02 ~]# getenforce 8 Disabled 9 [root@db02 ~]# hostname -I 10 10.0.0.52 172.16.1.52
db03主機(slave1,MHA Manages、Atlas節點)
1 [root@db02 ~]# cat /etc/redhat-release 2 CentOS release 6.9 (Final) 3 [root@db02 ~]# uname -r 4 2.6.32-696.el6.x86_64 5 [root@db02 ~]# /etc/init.d/iptables status 6 iptables: Firewall is not running. 7 [root@db02 ~]# getenforce 8 Disabled 9 [root@db02 ~]# hostname -I 10 10.0.0.52 172.16.1.52
三臺服務器上都全新安裝mysql 5.6.36 :
[root@db01 ~]# mysql --version mysql Ver 14.14 Distrib 5.6.36, for Linux (x86_64) using EditLine wrapper
關於mysql數據庫具體的安裝方法參考:http://www.cnblogs.com/clsn/p/8038964.html#_label3
🔊 主庫和從庫都要開啓binlog
🔊 主庫和從庫server-id必須不一樣
🔊 要有主從複製用戶
db01 my.cnf****文件
[root@db01 ~]# cat /etc/my.cnf [mysqld] basedir=/application/mysql datadir=/application/mysql/data socket=/tmp/mysql.sock log-error=/var/log/mysql.log log-bin=/data/mysql/mysql-bin binlog_format=row secure-file-priv=/tmp server-id=51 skip-name-resolve # 跳過域名解析 gtid-mode=on # 啓用gtid類型,不然就是普通的複製架構 enforce-gtid-consistency=true #強制GTID的一致性 log-slave-updates=1 # slave更新是否記入日誌(5.6必須的) relay_log_purge = 0 [mysql] socket=/tmp/mysql.sock
db02 my.cnf****文件
1 [root@db02 ~]# cat /etc/my.cnf 2 [mysqld] 3 basedir=/application/mysql 4 datadir=/application/mysql/data 5 socket=/tmp/mysql.sock 6 log-error=/var/log/mysql.log 7 log-bin=/data/mysql/mysql-bin 8 binlog_format=row 9 secure-file-priv=/tmp 10 server-id=52 11 skip-name-resolve 12 gtid-mode=on 13 enforce-gtid-consistency=true 14 log-slave-updates=1 15 relay_log_purge = 0 16 [mysql] 17 socket=/tmp/mysql.sock
db03 my.cnf****文件
1 [root@db03 ~]# cat /etc/my.cnf 2 [mysqld] 3 basedir=/application/mysql 4 datadir=/application/mysql/data 5 socket=/tmp/mysql.sock 6 log-error=/var/log/mysql.log 7 log-bin=/data/mysql/mysql-bin 8 binlog_format=row 9 secure-file-priv=/tmp 10 server-id=53 11 skip-name-resolve 12 gtid-mode=on 13 enforce-gtid-consistency=true 14 log-slave-updates=1 15 relay_log_purge = 0 16 skip-name-resolve 17 [mysql] 18 socket=/tmp/mysql.sock
建立複製用戶 (51做爲主節點,5二、53爲從)
GRANT REPLICATION SLAVE ON *.* TO repl@'10.0.0.%' IDENTIFIED BY '123';
從庫開啓複製
change master to master_host='10.0.0.51', master_user='repl', master_password='123', MASTER_AUTO_POSITION=1;
啓動從庫複製
start slave;
MySQL GTID****簡介
GTID的全稱爲 global transaction identifier ,能夠翻譯爲全局事務標示符,GTID在原始master上的事務提交時被建立。GTID須要在全局的主-備拓撲結構中保持惟一性,GTID由兩部分組成:
GTID = source_id:transaction_id
source_id用於標示源服務器,用server_uuid來表示,這個值在第一次啓動時生成,並寫入到配置文件data/auto.cnf中
transaction_id則是根據在源服務器上第幾個提交的事務來肯定。
GTID**事件結構
GTID**在二進制日誌中的結構
一個GTID*的生命週期包括:*
1.事務在主庫上執行並提交給事務分配一個gtid(由主庫的uuid和該服務器上未使用的最小事務序列號),該GTID被寫入到binlog中。
2.備庫讀取relaylog中的gtid,並設置session級別的gtid_next的值,以告訴備庫下一個事務必須使用這個值
3.備庫檢查該gtid是否已經被其使用並記錄到他本身的binlog中。slave須要擔保以前的事務沒有使用這個gtid,也要擔保此時已分讀取gtid,但未提交的事務也不恩呢過使用這個gtid.
4.因爲gtid_next非空,slave不會去生成一個新的gtid,而是使用從主庫得到的gtid。這能夠保證在一個複製拓撲中的同一個事務gtid不變。因爲GTID在全局的惟一性,經過GTID,咱們能夠在自動切換時對一些複雜的複製拓撲很方便的提高新主庫及新備庫,例如經過指向特定的GTID來肯定新備庫複製座標。
GTID是用來替代之前classic的複製方法;
MySQL5.6.2支持 MySQL5.6.10後完善;
GTID****相比傳統複製的優勢:
1.一個事務對應一個惟一ID,一個GTID在一個服務器上只會執行一次
2.GTID是用來代替傳統複製的方法,GTID複製與普通複製模式的最大不一樣就是不須要指定二進制文件名和位置
3.減小手工干預和下降服務故障時間,當主機掛了以後經過軟件從衆多的備機中提高一臺備機爲主機
GTID****的限制:
1.不支持非事務引擎
2.不支持create table ... select 語句複製(主庫直接報錯)
原理:( 會生成兩個sql,一個是DDL建立表SQL,一個是insert into 插入數據的sql。
因爲DDL會致使自動提交,因此這個sql至少須要兩個GTID,可是GTID模式下,只能給這個sql生成一個GTID )
3.不容許一個SQL同時更新一個事務引擎表和非事務引擎表
4.在一個複製組中,必需要求統一開啓GTID或者是關閉GTID
5.開啓GTID須要重啓(5.7除外)
6.開啓GTID後,就再也不使用原來的傳統複製方式
7.對於create temporary table 和 drop temporary table語句不支持
8.不支持sql_slave_skip_counter
從機發送到主機執行的事務的標識符的主範圍
Master send all other transactions to slave
一樣的GTID不能被執行兩次,若是有一樣的GTID,會自動被skip掉。
slave1:將本身的UUID1:1發送給master,而後接收到了UUID1:2,UUID1:3 event
slave2:將本身的UUID1:1,UUID1:2發送給master,而後接收到了UUID1:3事件
GTID****組成
GTID其實是由UUID+TID組成的。其中UUID是一個MySQL實例的惟一標識。TID表明了該實例上已經提交的事務數量,而且隨着事務提交單調遞增
GTID = source_id :transaction_id 7E11FA47-31CA-19E1-9E56-C43AA21293967:29
主節點my.cnf文件
# vi /etc/my.cnf [mysqld] basedir=/usr/local/mysql datadir=/data/mysql server-id=1 log-bin=mysql-bin socket=/tmp/mysql.sock binlog-format=ROW gtid-mode=on enforce-gtid-consistency=true log-slave-updates=1
從節點my.cnf文件
# vi /etc/my.cnf [mysqld] basedir=/usr/local/mysql datadir=/data/mysql server-id=2 binlog-format=ROW gtid-mode=on enforce-gtid-consistency=true log-bin=mysql-bin log_slave_updates = 1 socket=/tmp/mysql.sock
配置文件註解
server-id=x # 同一個複製拓撲中的全部服務器的id號必須唯一 binlog-format=RO # 二進制日誌格式,強烈建議爲ROW gtid-mode=on # 啓用gtid類型,不然就是普通的複製架構 enforce-gtid-consistency=true # 強制GTID的一致性 log-slave-updates=1 # slave更新是否記入日誌
複製用戶準備(Master主節點)
mysql>GRANT REPLICATION SLAVE ON *.* TO rep@'10.0.0.%' IDENTIFIED BY '123';
開啓複製(Slave從節點)
mysql>start slave; mysql>show slave status\G
如今就能夠進行主從複製測試。
本次MHA的部署基於GTID複製成功構建,普通主從複製也能夠構建MHA架構。
安裝依賴包
yum install perl-DBD-MySQL -y
下載mha軟件,mha官網:https://code.google.com/archive/p/mysql-master-ha/
github下載地址:https://github.com/yoshinorim/mha4mysql-manager/wiki/Downloads
*下載軟件包*
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
rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm
建立mha管理用戶
grant all privileges on *.* to mha@'10.0.0.%' identified by 'mha';
# 主庫上建立,從庫會自動複製(在從庫上查看)
建立命令軟鏈接(重要)
若是不建立命令軟鏈接,檢測mha複製狀況的時候會報錯
ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog ln -s /application/mysql/bin/mysql /usr/bin/mysql
在mysql-db03上部署管理節點
# 安裝epel源,軟件須要 wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo # 安裝manager 依賴包 yum install -y perl-Config-Tiny epel-release perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes # 安裝manager管理軟件 rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm
建立必須目錄
mkdir -p /etc/mha mkdir -p /var/log/mha/app1 ----》能夠管理多套主從複製
編輯mha-manager*配置文件*
[root@db03 ~]# cat /etc/mha/app1.cnf [server default] manager_log=/var/log/mha/app1/manager manager_workdir=/var/log/mha/app1 master_binlog_dir=/data/mysql user=mha password=mha ping_interval=2 repl_password=123 repl_user=repl ssh_user=root [server1] hostname=10.0.0.51 port=3306 [server2] hostname=10.0.0.52 port=3306 [server3] hostname=10.0.0.53 port=3306
【配置文件詳解】
[server default] 2 #設置manager的工做目錄 3 manager_workdir=/var/log/masterha/app1 4 #設置manager的日誌 5 manager_log=/var/log/masterha/app1/manager.log 6 #設置master 保存binlog的位置,以便MHA能夠找到master的日誌,我這裏的也就是mysql的數據目錄 7 master_binlog_dir=/data/mysql 8 #設置自動failover時候的切換腳本 9 master_ip_failover_script= /usr/local/bin/master_ip_failover 10 #設置手動切換時候的切換腳本 11 master_ip_online_change_script= /usr/local/bin/master_ip_online_change 12 #設置mysql中root用戶的密碼,這個密碼是前文中建立監控用戶的那個密碼 13 password=123456 14 #設置監控用戶root 15 user=root 16 #設置監控主庫,發送ping包的時間間隔,嘗試三次沒有迴應的時候自動進行failover 17 ping_interval=1 18 #設置遠端mysql在發生切換時binlog的保存位置 19 remote_workdir=/tmp 20 #設置複製用戶的密碼 21 repl_password=123456 22 #設置複製環境中的複製用戶名 23 repl_user=rep 24 #設置發生切換後發送的報警的腳本 25 report_script=/usr/local/send_report 26 #一旦MHA到server02的監控之間出現問題,MHA Manager將會嘗試從server03登陸到server02 27 secondary_check_script= /usr/local/bin/masterha_secondary_check -s server03 -s server02 --user=root --master_host=server02 --master_ip=10.0.0.51 --master_port=3306 28 #設置故障發生後關閉故障主機腳本(該腳本的主要做用是關閉主機放在發生腦裂,這裏沒有使用) 29 shutdown_script="" 30 #設置ssh的登陸用戶名 31 ssh_user=root 32 33 [server1] 34 hostname=10.0.0.51 35 port=3306 36 37 [server2] 38 hostname=10.0.0.52 39 port=3306 40 #設置爲候選master,若是設置該參數之後,發生主從切換之後將會將此從庫提高爲主庫,即便這個主庫不是集羣中事件最新的slave 41 candidate_master=1 42 #默認狀況下若是一個slave落後master 100M的relay logs的話,MHA將不會選擇該slave做爲一個新的master,由於對於這個slave的恢復須要花費很長時間,經過設置check_repl_delay=0,MHA觸發切換在選擇一個新的master的時候將會忽略複製延時,這個參數對於設置了candidate_master=1的主機很是有用,由於這個候選主在切換的過程當中必定是新的master 43 check_repl_delay=0
配置ssh信任(密鑰分發,在全部節點上執行)
# 生成密鑰 ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1 # 分發公鑰,包括本身 for i in 1 2 3 ;do ssh-copy-id -i /root/.ssh/id_dsa.pub root@10.0.0.5$i ;done
分發完成後測試分發是否成功
for i in 1 2 3 ;do ssh 10.0.0.5$i date ;done 或 [root@db03 ~]# masterha_check_ssh --conf=/etc/mha/app1.cnf 最後一行信息爲以下字樣即爲分發成功: Thu Dec 28 18:44:53 2017 - [info] All SSH connection tests passed successfully.
通過上面的部署事後,mha架構已經搭建完成
# 啓動mha 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@db03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf app1 (pid:3298) is running(0:PING_OK), master:10.0.0.51
查看如今的主庫是哪一個
[root@db03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf app1 (pid:11669) is running(0:PING_OK), master:10.0.0.51
手動中止主庫
[root@db01 ~]# /etc/init.d/mysqld stop Shutting down MySQL..... SUCCESS!
再中止數據的同時查看日誌信息的變化
[root@db03 ~]# tailf /var/log/mha/app1/manager ~~~ Fri Dec 29 15:51:14 2017 - [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='repl', MASTER_PASSWORD='xxx';
修復主從
① 啓動原主庫,添加change master to 信息
[root@db01 ~]# /etc/init.d/mysqld start Starting MySQL. SUCCESS! mysql> CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123'; mysql> start slave;
② 查看主從複製狀態
mysql> show slave status\G Master_Host: 10.0.0.52 Slave_IO_Running: Yes Slave_SQL_Running: Yes
修復mha
① 修改app1.cnf配置文件,添加回被剔除主機
[root@db03 ~]# cat /etc/mha/app1.cnf [binlog1] hostname=10.0.0.53 master_binlog_dir=/data/mysql/binlog/ no_master=1 [server default] manager_log=/var/log/mha/app1/manager manager_workdir=/var/log/mha/app1 master_binlog_dir=/data/mysql master_ip_failover_script=/usr/local/bin/master_ip_failover password=mha ping_interval=2 repl_password=123 repl_user=repl ssh_user=root user=mha [server1] hostname=10.0.0.51 port=3306 [server2] hostname=10.0.0.52 port=3306 [server3] hostname=10.0.0.53 port=3306
② mha檢查複製狀態
[root@db03 ~]# masterha_check_repl --conf=/etc/mha/app1.cnf MySQL Replication Health is OK.
③ 啓動mha程序
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@db03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf app1 (pid:11978) is running(0:PING_OK), master:10.0.0.52
實驗結束將主庫切換回db01.
① 中止mha
[root@db03 ~]# masterha_stop --conf=/etc/mha/app1.cnf Stopped app1 successfully.
② 中止全部從庫slave(全部庫操做)
stop slave; reset slave all;
③ 重作主從複製(db0二、db03)
CHANGE MASTER TO MASTER_HOST='10.0.0.51', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';
④ 啓動slave
start slave;
啓動以後檢查從庫是否爲兩個yes show slave status\G
⑤ mha檢查主從複製
[root@db03 ~]# masterha_check_repl --conf=/etc/mha/app1.cnf MySQL Replication Health is OK.
⑥ 啓動mha
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@db03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf app1 (pid:12127) is running(0:PING_OK), master:10.0.0.51
到此主主節點有切回到db01
修改[server1]的權重
[server1] hostname=10.0.0.51 port=3306 candidate_master=1 check_repl_delay=0
配置說明
candidate_master=1 ----》無論怎樣都切到優先級高的主機,通常在主機性能差別的時候用 check_repl_delay=0 ----》無論優先級高的備選庫,數據延時多久都要往那切
注:
一、多地多中心,設置本地節點爲高權重
二、在有半同步複製的環境中,設置半同步複製節點爲高權重
三、你覺着哪一個機器適合作主節點,配置較高的 、性能較好的
🐶 經過keepalived的方式,管理虛擬IP的漂移
🐶 經過MHA自帶腳本方式,管理虛擬IP的漂移
修改mha****配置文件
[root@db03 ~]# grep "script" /etc/mha/app1.cnf [server default] master_ip_failover_script=/usr/local/bin/master_ip_failover
再主配置中添加VIP腳本
腳本內容
[root@db03 ~]# cat /usr/local/bin/master_ip_failover #!/usr/bin/env perl use strict; use warnings FATAL => 'all'; use Getopt::Long; 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"; GetOptions( 'command=s' => \$command, 'ssh_user=s' => \$ssh_user, 'orig_master_host=s' => \$orig_master_host, 'orig_master_ip=s' => \$orig_master_ip, 'orig_master_port=i' => \$orig_master_port, 'new_master_host=s' => \$new_master_host, 'new_master_ip=s' => \$new_master_ip, 'new_master_port=i' => \$new_master_port, ); exit &main(); sub main { print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n"; if ( $command eq "stop" || $command eq "stopssh" ) { my $exit_code = 1; eval { print "Disabling the VIP on old master: $orig_master_host \n"; &stop_vip(); $exit_code = 0; }; if ($@) { warn "Got Error: $@\n"; exit $exit_code; } exit $exit_code; } elsif ( $command eq "start" ) { my $exit_code = 10; eval { print "Enabling the VIP - $vip on the new master - $new_master_host \n"; &start_vip(); $exit_code = 0; }; if ($@) { warn $@; exit $exit_code; } exit $exit_code; } elsif ( $command eq "status" ) { print "Checking the Status of the script.. OK \n"; exit 0; } else { &usage(); exit 1; } } sub start_vip() { `ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`; } sub stop_vip() { return 0 unless ($ssh_user); `ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`; } sub usage { print "Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n"; }
該腳本爲軟件自帶,腳本獲取方法:再mha源碼包中的samples目錄下有該腳本的模板,對該模板進行修改便可使用。路徑如: mha4mysql-manager-0.56/samples/scripts
腳本修改內容
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沒法啓動
chmod +x /usr/local/bin/master_ip_failover
手動綁定VIP(****主庫)
ifconfig eth0:0 10.0.0.55/24
檢查
[root@db01 ~]# ip a s eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:0c:29:6c:7a:11 brd ff:ff:ff:ff:ff:ff 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 inet6 fe80::20c:29ff:fe6c:7a11/64 scope link valid_lft forever preferred_lft forever
至此vip****漂移配置完成
查看db02的slave信息
View Code 如今主從狀態
停掉主庫
[root@db01 ~]# /etc/init.d/mysqld stop
在db03上查看從庫slave信息
View Code 停掉主庫後的主從信息
在db01上查看vip信息
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:0c:29:6c:7a:11 brd ff:ff:ff:ff:ff:ff inet 10.0.0.51/24 brd 10.0.0.255 scope global eth0 inet6 fe80::20c:29ff:fe6c:7a11/64 scope link valid_lft forever preferred_lft forever
在db02上查看vip信息
[root@db02 ~]# ip a s eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:0c:29:d6:0a:b3 brd ff:ff:ff:ff:ff:ff 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 inet6 fe80::20c:29ff:fed6:ab3/64 scope link valid_lft forever preferred_lft forever
至此,VIP漂移就測試成功
1)前期準備:
一、準備一臺新的mysql實例(db03),GTID必須開啓。
二、未來binlog接收目錄,不能和主庫binlog目錄同樣
2)中止mha
masterha_stop --conf=/etc/mha/app1.cnf
3)在app1.cnf開啓binlogserver功能
[binlog1] no_master=1 hostname=10.0.0.53 ----> 主機DB03 master_binlog_dir=/data/mysql/binlog/ ----> binlog保存目錄
4)開啓binlog接收目錄,注意權限
mkdir -p /data/mysql/binlog/ chown -R mysql.mysql /data/mysql # 進入目錄啓動程序 cd /data/mysql/binlog/ &&\ mysqlbinlog -R --host=10.0.0.51 --user=mha --password=mha --raw --stop-never mysql-bin.000001 &
參數說明:-R 遠程主機
5)啓動mha
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 &
#查看binlog目錄中的binlog
[root@db03 binlog]# ll total 44 -rw-r--r-- 1 root root 285 Mar 8 03:11 mysql-bin.000001
#登陸主庫
[root@mysql-db01 ~]# mysql -uroot -p123
#刷新binlog
mysql> flush logs;
#再次查看binlog目錄
[root@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
Atlas是由 Qihoo 360公司Web平臺部基礎架構團隊開發維護的一個基於MySQL協議的數據中間層項目。它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基礎上,修改了大量bug,添加了不少功能特性。目前該項目在360公司內部獲得了普遍應用,不少MySQL業務已經接入了Atlas平臺,天天承載的讀寫請求數達幾十億條。
同時,有超過50家公司在生產環境中部署了Atlas,超過800人已加入了咱們的開發者交流羣,而且這些數字還在不斷增長。並且安裝方便。配置的註釋寫的蠻詳細的,都是中文。
Atlas官方連接: https://github.com/Qihoo360/Atlas/blob/master/README_ZH.md
Atlas下載連接: https://github.com/Qihoo360/Atlas/releases
讀寫分離、從庫負載均衡、自動分表、IP過濾
SQL語句黑白名單、DBA可平滑上下線DB、自動摘除宕機的DB
Atlas相對於官方MySQL-Proxy的優點
1.將主流程中全部Lua代碼用C重寫,Lua僅用於管理接口
2.重寫網絡模型、線程模型
3.實現了真正意義上的鏈接池
4.優化了鎖機制,性能提升數十倍
Atlas是一個位於前端應用與後端MySQL數據庫之間的中間件,它使得應用程序員無需再關心讀寫分離、分表等與MySQL相關的細節,能夠專一於編寫業務邏輯,同時使得DBA的運維工做對前端應用透明,上下線DB前端應用無感知。
Atlas是一個位於應用程序與MySQL之間中間件。在後端DB看來,Atlas至關於鏈接它的客戶端,在前端應用看來,Atlas至關於一個DB。
Atlas做爲服務端與應用程序通信,它實現了MySQL的客戶端和服務端協議,同時做爲客戶端與MySQL通信。它對應用程序屏蔽了DB的細節,同時爲了下降MySQL負擔,它還維護了鏈接池.
Mysql-proxy(oracle)
Mysql-router(oracle)
Atlas (Qihoo 360)
Atlas-sharding (Qihoo 360)
Cobar(是阿里巴巴(B2B)部門開發)
Mycat(基於阿里開源的Cobar產品而研發)
TDDL Smart Client的方式(淘寶)
Oceanus(58同城數據庫中間件)
OneProxy(原支付寶首席架構師樓方鑫開發 )
vitess(谷歌開發的數據庫中間件)
Heisenberg(百度)
TSharding(蘑菇街白輝)
Xx-dbproxy(金山的Kingshard、噹噹網的sharding-jdbc )
amoeba
軟件獲取地址:https://github.com/Qihoo360/Atlas/releases
注意:
一、Atlas只能安裝運行在64位的系統上
二、Centos 5.X安裝 Atlas-XX.el5.x86_64.rpm,Centos 6.X安裝Atlas-XX.el6.x86_64.rpm。
三、後端mysql版本應大於5.1,建議使用Mysql 5.6以上
Atlas (普通) : Atlas-2.2.1.el6.x86_64.rpm
Atlas (分表) : Atlas-sharding_1.0.1-el6.x86_64.rpm
下載安裝atlas
wget https://github.com/Qihoo360/Atlas/releases/download/2.2.1/Atlas-2.2.1.el6.x86_64.rpm rpm -ivh Atlas-2.2.1.el6.x86_64.rpm
至此安裝完成
atlas配置文件中的密碼須要加密,可使用,軟件自帶的加密工具進行加密
cd /usr/local/mysql-proxy/conf/ /usr/local/mysql-proxy/bin/encrypt 密碼 ---->製做加密密碼
生產密文密碼:
[root@db03 bin]# /usr/local/mysql-proxy/bin/encrypt 123 3yb5jEku5h4= [root@db03 bin]# /usr/local/mysql-proxy/bin/encrypt mha O2jBXONX098=
編輯配置文件
vim /usr/local/mysql-proxy/conf/test.cnf [mysql-proxy] admin-username = user admin-password = pwd proxy-backend-addresses = 10.0.0.55:3306 proxy-read-only-backend-addresses = 10.0.0.52:3306,10.0.0.53:3306 pwds = repl:3yb5jEku5h4=,mha:O2jBXONX098= daemon = true keepalive = true event-threads = 8 log-level = message log-path = /usr/local/mysql-proxy/log sql-log=ON proxy-address = 0.0.0.0:33060 admin-address = 0.0.0.0:2345 charset=utf8
配置文件內爲全中文註釋,這裏有一份較爲詳細的解釋:
View Code Atlas配置文件說明
編寫一個atlas的管理腳本,固然也能夠寫腳本,能夠直接手動的管理:
/usr/local/mysql-proxy/bin/mysql-proxyd test start #啓動 /usr/local/mysql-proxy/bin/mysql-proxyd test stop #中止 /usr/local/mysql-proxy/bin/mysql-proxyd test restart #重啓
注意:test是配置文件的名稱
腳本內容:
View Code Atas管理腳本
檢查端口是否正常
[root@db03 ~]# netstat -lntup|grep mysql-proxy tcp 0 0 0.0.0.0:33060 0.0.0.0:* LISTEN 2125/mysql-proxy tcp 0 0 0.0.0.0:2345 0.0.0.0:* LISTEN 2125/mysql-proxy
登入管理接口
[root@db03 ~]# 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.55:3306 | up | rw | | 2 | 10.0.0.52:3306 | up | ro | | 3 | 10.0.0.53:3306 | up | ro | +-------------+----------------+-------+------+ 3 rows in set (0.00 sec)
平滑摘除mysql
mysql> REMOVE BACKEND 2; Empty set (0.00 sec)
檢查是否摘除
mysql> SELECT * FROM backends; +-------------+----------------+-------+------+ | backend_ndx | address | state | type | +-------------+----------------+-------+------+ | 1 | 10.0.0.55:3306 | up | rw | | 2 | 10.0.0.53:3306 | up | ro | +-------------+----------------+-------+------+ 2 rows in set (0.00 sec)
保存到配置文件中
mysql> SAVE CONFIG;
將節點再添加回來
mysql> add slave 10.0.0.52:3306; Empty set (0.00 sec)
查看是否添加成功
mysql> SELECT * FROM backends; +-------------+----------------+-------+------+ | backend_ndx | address | state | type | +-------------+----------------+-------+------+ | 1 | 10.0.0.55:3306 | up | rw | | 2 | 10.0.0.53:3306 | up | ro | | 3 | 10.0.0.52:3306 | up | ro | +-------------+----------------+-------+------+ 3 rows in set (0.00 sec)
保存到配置文件中
mysql> SAVE CONFIG;
經過atlas登錄數據,注意,使用的是數據庫上的用戶及密碼
shell> mysql -umha -pmha -h127.0.0.1 -P33060
第一次查詢server_id
mysql> show variables like "server_id"; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | server_id | 53 | +---------------+-------+ 1 row in set (0.00 sec)
第二次查詢server_id
mysql> show variables like "server_id"; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | server_id | 52 | +---------------+-------+ 1 row in set (0.00 sec)
*經過上面能夠看到負載成功*
Atlas會透明的將事務語句和寫語句發送至主庫執行,讀語句發送至從庫執行。具體如下語句會在主庫執行:
顯式事務中的語句
autocommit=0時的全部語句
含有select GET_LOCK()的語句
除SELECT、SET、USE、SHOW、DESC、EXPLAIN外的。
從庫負載均衡配置
proxy-read-only-backend-addresses=ip1:port1@權重,ip2:port2@權重
自動分表
使用Atlas的分表功能時,首先須要在配置文件test.cnf設置tables參數。
tables參數設置格式:數據庫名.表名.分表字段.子表數量,好比:
你的數據庫名叫school,表名叫stu,分表字段叫id,總共分爲2張表,那麼就寫爲school.stu.id.2,若是還有其餘的分表,以逗號分隔便可。
用戶須要手動創建2張子表(stu_0,stu_1,注意子表序號是從0開始的)。
全部的子表必須在DB的同一個database裏。
當經過Atlas執行(SELECT、DELETE、UPDATE、INSERT、REPLACE)操做時,Atlas會根據分表結果(id%2=k),定位到相應的子表(stu_k)。
例如,執行select * from stu where id=3;,Atlas會自動從stu_1這張子表返回查詢結果。
但若是執行SQL語句(select * from stu;)時不帶上id,則會提示執行stu表不存在。
Atles功能的說明
Atlas暫不支持自動建表和跨庫分表的功能。
Atlas目前支持分表的語句有SELECT、DELETE、UPDATE、INSERT、REPLACE。
IP****過濾:client-ips
該參數用來實現IP過濾功能。
在傳統的開發模式中,應用程序直接鏈接DB,所以DB會對部署應用的機器(好比web服務器)的IP做訪問受權。
在引入中間層後,由於鏈接DB的是Atlas,因此DB改成對部署Atlas的機器的IP做訪問受權,若是任意一臺客戶端均可以鏈接Atlas,就會帶來潛在的風險。
client-ips參數用來控制鏈接Atlas的客戶端的IP,能夠是精確IP,也能夠是IP段,以逗號分隔寫在一行上便可。
如: client-ips=192.168.1.2, 192.168.2
這就表明192.168.1.2這個IP和192.168.2.*這個段的IP能夠鏈接Atlas,其餘IP均不能鏈接。若是該參數不設置,則任意IP都可鏈接Atlas。若是設置了client-ips參數,且Atlas前面掛有LVS,則必須設置lvs-ips參數,不然能夠不設置lvs-ips。
SQL****語句黑白名單功能: Atlas會屏蔽不帶where條件的delete和update操做,以及sleep函數。
Sharding的基本思想就是把一個數據表中的數據切分紅多個部分, 存放到不一樣的主機上去(切分的策略有多種), 從而緩解單臺機器的性能跟容量的問題.
sharding是一種水平切分, 適用於單表數據龐大的情景. 目前atlas支持靜態的
sharding方案, 暫時不支持數據的自動遷移以及數據組的動態加入.
Atlas以表爲單位sharding, 同一個數據庫內能夠同時共有sharding的表和不sharding的表, 不sharding的表數據存在未sharding的數據庫組中.
目前Atlas sharding支持insert, delete, select, update語句, 只支持不跨shard的事務. 全部的寫操做如insert, delete, update只能一次命中一個組, 不然會報"ERROR 1105 (HY000):write operation is only allow to one dbgroup!"錯誤.
因爲sharding取替了Atlas的分表功能, 因此在Sharding分支裏面, Atlas單機分表的功能已經移除, 配置tables將不會再有效.
Atlas支持非sharding跟sharding的表共存在同一個Atlas中, 2.2.1以前的配置能夠直接運行. 以前的配置如
proxy-backend-addresses = 192.168.0.12:3306 proxy-read-only-backend-addresses = 192.168.0.13:3306,192.168.0.14:3306 ...
這配置了一個master和兩個slave,這屬於非sharding的組, 全部非sharding的表跟語句都會發往這個組內.
因此以前沒有Sharding的Atlas的表能夠無縫的在新版上使用,
注意: 非Sharding的組只能配置一個, 而sharding的組能夠配置多個. 下面的配置, 配置了Sharding的組, 注意與上面的配置區分
[shardrule-0] table = test.sharding_test
分表名,有數據庫+表名組成 t
ype = range
sharding類型:range 或 hash
shard-key = id
sharding 字段
groups = 0:0-999,1:1000-1999
分片的group,若是是range類型的sharding,則groups的格式是:group_id:id範圍。若是是hash類型的sharding,則groups的格式是:group_id。例如groups = 0, 1
[group-0] proxy-backend-addresses=192.168.0.15:3306 proxy-read-only-backend-addresses=192.168.0.16:3306 [group-1] proxy-backend-addresses=192.168.0.17:3306 proxy-read-only-backend-addresses=192.168.0.18:3306
關於支持的語句
Atlas sharding只對sql語句提供有限的支持, 目前支持基本的Select, insert/replace, delete,update語句,支持所有的Where語法(SQL-92標準), 不支持DDL(create drop alter)以及一些管理語句,DDL請直連MYSQL執行, 請只在Atlas上執行Select, insert, delete, update(CRUD)語句.
對於如下語句, 若是語句命中了多臺dbgroup, Atlas均未作支持(若是語句只命中了一個dbgroup, 如 select count(*) from test where id < 1000, 其中dbgroup0範圍是0 - 1000, 那麼這些特性都是支持的)Limit Offset(支持Limit)
Order by
Group by Join
ON
Count, Max, Min等函數
增長節點
注意: 暫時只支持range方式的節點擴展, hash方式因爲須要數據遷移, 暫時未作支持.
擴展節點在保證原來節點的範圍不改變的狀況下, 如已有dbgroup0爲範圍0 - 999, dbgroup1爲範圍 1000-1999, 這個時候能夠增長範圍>2000的節點. 如增長一個節點爲2000 - 2999, 修改配置文件, 重啓Atlas便可.
來源:博客園 http://dwz.date/d8qV
歡迎關注公衆號 【碼農開花】一塊兒學習成長 我會一直分享Java乾貨,也會分享免費的學習資料課程和麪試寶典 回覆:【計算機】【設計模式】【面試】有驚喜哦