mysql高可用研究(二) 主從+MHA+Atlas

關於Atlas的詳細介紹請訪問:https://github.com/Qihoo360/Atlas/blob/master/README_ZH.mdnode

爲何要使用Atlas?應用程序直連數據庫很差嗎?還要在前面加上一層代理,會不會下降應用的讀寫性能?會不會增長維護管理的成本?我想這是每一個使用atlas以前的疑問。mysql

一、爲何要使用Atlas?git

咱們使用atlas,主要使用它的讀寫分離和從庫負載均衡功能。由於我們這讀業務遠遠多於寫,故採用讀寫分離的架構再合適不過了。以前實現讀寫分離,通常都是經過應用程序實現的,這樣大大增長了開發的難度。而使用atlas,能夠將應用和數據庫分離開來,程序員專一業務邏輯開發便可,數據庫對於應用徹底透明。另外,才用讀寫分離,還能夠增長冗餘,增長了機器的處理能力,對於讀操做爲主的應用,使用讀寫分離能夠確保寫的服務器壓力更小。程序員

二、應用程序直連數據庫很差嗎?還要在前面加上一層代理,會不會下降應用的讀寫性能? github

這裏有人專門的測試過,請參考:https://github.com/Qihoo360/Atlas/wiki/Atlas%E7%9A%84%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95sql

下面經過實驗介紹Atlas的部署實現讀寫分離和從庫負載均衡功能。數據庫

1、Atlas安裝後端

【環境說明】:服務器

默認三臺機器上都已安裝mysql5.6,且主從複製已經配置完成。
角色 主機名 ip地址 功能
主庫                     node1     192.168.245.129    (w/r)
candidate_master        node2     192.168.245.131     (r)
從庫                     node3     192.168.245.132     (r)
atlas monitor 192.168.245.133 讀寫分離 vip:
192.168.245.100

一、這裏採用官方推薦的rpm安裝方式,比較簡單,下載rpm包:https://github.com/Qihoo360/Atlas/releases架構

[root@monitor software]# yum install Atlas-2.2.1.el6.x86_64.rpm

安裝的目錄在:/usr/local/mysql-proxy

注意事項:

(1).Atlas只能安裝運行在64位的系統上。

(2).Centos 5.X安裝 Atlas-XX.el5.x86_64.rpm,Centos 6.X安裝Atlas-XX.el6.x86_64.rpm。

(3).後端mysql版本應大於5.1,建議使用Mysql 5.6

二、配置Atlas

Atlas運行須要依賴一個配置文件(test.cnf)。在運行Atlas以前,須要對該文件進行配置。Atlas的安裝目錄是/usr/local /mysql-proxy,進入安裝目錄下的conf目錄,能夠看到已經有一個名爲test.cnf的默認配置文件,咱們只須要修改裏面的某些配置項,不 須要從頭寫一個配置文件。

[mysql-proxy]

#帶#號的爲非必需的配置項目

#管理接口的用戶名
admin-username = user

#管理接口的密碼
admin-password = pwd

#Atlas後端鏈接的MySQL主庫的IP和端口,可設置多項,用逗號分隔
proxy-backend-addresses = 127.0.0.1:3306

#Atlas後端鏈接的MySQL從庫的IP和端口,@後面的數字表明權重,用來做負載均衡,若省略則默認爲1,可設置多項,用逗號分隔
#proxy-read-only-backend-addresses = 127.0.0.1:3305@1

#用戶名與其對應的加密過的MySQL密碼,密碼使用PREFIX/bin目錄下的加密程序encrypt加密,下行的user1和user2爲示例,將其替換爲你的MySQL的用戶名和加密密碼!
pwds = user1:+jKsgB3YAG8=, user2:GS+tr4TPgqc=

#設置Atlas的運行方式,設爲true時爲守護進程方式,設爲false時爲前臺方式,通常開發調試時設爲false,線上運行時設爲true,true後面不能有空格。
daemon = true

#設置Atlas的運行方式,設爲true時Atlas會啓動兩個進程,一個爲monitor,一個爲worker,monitor在worker意外退出後會自動將其重啓,設爲false時只有worker,沒有monitor,通常開發調試時設爲false,線上運行時設爲true,true後面不能有空格。
keepalive = true

#工做線程數,對Atlas的性能有很大影響,若是追求Atlas處理SQL請求時的QPS,將event-threads值設置爲CPU個數的2-4倍。若是追求Atlas處理SQL請求的完成時間,將event-threads值設置爲CPU個數便可。
event-threads = 8

#日誌級別,分爲message、warning、critical、error、debug五個級別
log-level = message

#日誌存放的路徑
log-path = /usr/local/mysql-proxy/log

#SQL日誌的開關,可設置爲OFF、ON、REALTIME,OFF表明不記錄SQL日誌,ON表明記錄SQL日誌,REALTIME表明記錄SQL日誌且實時寫入磁盤,默認爲OFF
#sql-log = OFF

#慢日誌輸出設置。當設置了該參數時,則日誌只輸出執行時間超過sql-log-slow(單位:ms)的日誌記錄。不設置該參數則輸出所有日誌。
#sql-log-slow = 10

#實例名稱,用於同一臺機器上多個Atlas實例間的區分
#instance = test

#Atlas監聽的工做接口IP和端口
proxy-address = 0.0.0.0:1234

#Atlas監聽的管理接口IP和端口
admin-address = 0.0.0.0:2345

#分表設置,此例中person爲庫名,mt爲表名,id爲分表字段,3爲子表數量,可設置多項,以逗號分隔,若不分表則不須要設置該項
#tables = person.mt.id.3

#默認字符集,設置該項後客戶端再也不須要執行SET NAMES語句
#charset = utf8

#容許鏈接Atlas的客戶端的IP,能夠是精確IP,也能夠是IP段,以逗號分隔,若不設置該項則容許全部IP鏈接,不然只容許列表中的IP鏈接
#client-ips = 127.0.0.1, 192.168.1

#Atlas前面掛接的LVS的物理網卡的IP(注意不是虛IP),如有LVS且設置了client-ips則此項必須設置,不然能夠不設置
#lvs-ips = 192.168.1.1

注意事項:

(1)pwds參數加密密碼獲取:

[root@monitor bin]# cd /usr/local/mysql-proxy/bin
[root@monitor bin]# ./encrypt root
DAJnl8cVzy8=

(2)event-threads設置:

     若是追求Atlas處理SQL請求時的QPS,將event-threads值設置爲CPU個數的2-4倍。若是追求Atlas處理SQL請求的完成時間,將event-threads值設置爲CPU個數便可。

(3)Atlas的工做端口

     proxy-address項配置,例如proxy-address = 0.0.0.0:1234表明客戶端應該使用1234這個端口鏈接Atlas來發送SQL請求。

(4)Atlas的管理端口

     admin-address項配置,例如admin-address = 0.0.0.0:2345表明DBA應該使用2345這個端口鏈接Atlas來執行運維管理操做。

(5)管理接口的用戶名和密碼

     admin-username項和admin-password項設置,這兩項是用來進入Atlas的管理界面的,與後端鏈接的MySQL沒有關係,因此能夠任意設置,不須要MySQL在配置上作任何改動。

2、Atlas啓動

進入/usr/local/mysql-proxy/bin目錄,執行下面的命令啓動、重啓或中止Atlas。

(1)  ./mysql-proxyd test start,啓動Atlas。

(2)  ./mysql-proxyd test restart,重啓Atlas。

(3)  ./mysql-proxyd test stop,中止Atlas。

[root@monitor bin]# ./mysql-proxyd test start
#查看是否啓動
[root@monitor bin]# ps -ef | grep mysql-proxy
root     13451     1  0 01:39 ?        00:00:00 /usr/local/mysql-proxy/bin/mysql-proxy --defaults-file=/usr/local/mysql-proxy/conf/test.cnf
root     13452 13451  0 01:39 ?        00:00:00 /usr/local/mysql-proxy/bin/mysql-proxy --defaults-file=/usr/local/mysql-proxy/conf/test.cnf

這時,atlas已經啓動成功了,先嚐試在atlas本機上鍊接,做爲應用程序能夠鏈接上了。

[root@monitor conf]# /data/mysql/bin/mysql -uroot -proot -h 192.168.245.133 -P1234 -c
Warning: Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.0.81-log MySQL Community Server (GPL)

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

dba管理用戶這樣鏈接:

[root@monitor bin]# /data/mysql/bin/mysql -uadmin -padmin -h 127.0.0.1 -P2345

在遠程機器上(內網的同一網段中)用SQLyog客戶端進行鏈接,報錯鏈接不上:ERROR 2003 (HY000): Can't connect to MySQL server on '192.168.245.133' (113)

用戶名和密碼都是對的,在安裝atlas的本機上能夠鏈接上atlas,但是換到別的機器上就不行了,那隻能是端口問題了,是否防火牆阻止了呢?因而在別的機器上測試133機器的1234端口,果真是端口不通:

[root@node3 mysql]# ssh -v -p 1234 root@192.168.245.133
OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Applying options for *
debug1: Connecting to 192.168.245.133 [192.168.245.133] port 1234.
debug1: connect to address 192.168.245.133 port 1234: No route to host
ssh: connect to host 192.168.245.133 port 1234: No route to host

接下來就好辦了,在atlas機器上執行:iptables -F ,而後就通了,再次經過sqlyog鏈接,解決問題。

[root@node3 mysql]# ssh -v -p 1234 root@192.168.245.133
OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Applying options for *
debug1: Connecting to 192.168.245.133 [192.168.245.133] port 1234.
debug1: Connection established.

3、測試讀寫分離

一、中止主從複製:爲了看清inset操做究竟是分配到主庫仍是從庫上

mysql> stop slave;
Query OK, 0 rows affected (0.07 sec)

二、鏈接atlas並測試

(1)測試insert操做:

[root@monitor log]# /data/mysql/bin/mysql -uroot -proot -h 192.168.245.133 -P 1234
Warning: Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.0.81-log MySQL Community Server (GPL)

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> insert into backup.test(id) values(3); #測試插入操做
Query OK, 1 row affected (0.02 sec)

而後到主庫上查看:

#這是沒插入以前的數據
(product)root@192.168.245.129 [(none)]> select * from backup.test;
+----+
| id |
+----+
|  1 |
|  2 |
|  4 |
|  5 |
+----+
4 rows in set (0.10 sec)
#插入後,有數據了!神奇吧
(product)root@192.168.245.129 [(none)]> select * from backup.test;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
|  5 |
+----+
5 rows in set (0.00 sec)

從庫上的數據依然沒變,說明寫操做只分配到主庫上:

(product)root@127.0.0.1 [backup]> select * from test;
+----+
| id |
+----+
|  1 |
|  2 |
|  4 |
|  5 |
+----+
4 rows in set (0.00 sec)

(2)測試select操做:爲了效果,保持主庫數據和從庫數據的不一致,以下:

#主庫129上的數據:
(product)root@192.168.245.129 [(none)]> select * from a.a1;
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
+----+------+
2 rows in set (0.00 sec)
#從庫上的數據:
(product)root@127.0.0.1 [a]> select * from a.a1;
+----+------+
| id | name |
+----+------+
|  3 | c    |
|  4 | d    |
+----+------+
2 rows in set (0.00 sec)
#在atlas中發送select請求,數據以下:
mysql> select * from a.a1;
+----+------+
| id | name |
+----+------+
|  3 | c    |
|  4 | d    |
+----+------+
2 rows in set (0.02 sec)

有時主從有延時,能夠經過/*master*/將select強制發送到主庫,因爲mysql命令行默認是過濾掉註釋的,須要在鏈接mysql命令行時指定-c參數:      

#mysql -c參數介紹
-c, --comments      Preserve comments. Send comments to the server. The
                      default is --skip-comments (discard comments), enable
                      with --comments.
#鏈接mysql
[root@monitor bin]# /data/mysql/bin/mysql -uroot -proot -h 127.0.0.1 -P1234 -c
mysql> /*master*/select * from a.a1;
+----+------+
| id | name |
+----+------+
|  1 | test |
|  2 | b    |
+----+------+
2 rows in set (0.02 sec)

#查看後臺日誌,已經發向主庫了
[11/18/2015 21:31:15] C:127.0.0.1:48380 S:192.168.245.100:3306 OK 15.525 "/*master*/ select * from a.a1"

(3)過濾update和delete不帶where子句:

mysql> update a.a1 set name='test';
ERROR 1105 (07000): Proxy Warning - Syntax Forbidden
mysql> update a.a1 set name='test' where id=1;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0

#後臺日誌顯示:[11/18/2015 21:16:15] C:127.0.0.1:47135 S:192.168.245.100:3306 OK 21.627 "update a.a1 set name='test' where id=1"

(4)特殊sql語句測試:

  • select ....for update形式:
[11/18/2015 22:47:02] C:192.168.245.1:65459 S:192.168.245.131:3306 OK 9.374 "select * from a.`a1` for update"

從執行日誌能夠發現,這類語句是發向從庫上的。不能保證鎖定master,因此此寫法謹慎使用。

  • 存儲過程測試:

咱們知道,一個存儲過程可能很複雜,裏面可能有各類sql語句,那麼這些語句atlas是怎麼處理的呢?咱們先來建立一個簡單的存儲過程,裏面有delete,select,insert等操做:

DELIMITER $$
CREATE PROCEDURE a.p_test()
BEGIN
  DECLARE cc INT DEFAULT 0;

  SELECT COUNT(*) INTO cc FROM a.a2;
  IF cc > 0 THEN
    DELETE FROM a.a2;
  END IF;
  INSERT INTO a.a2(id,NAME) VALUES(1,'a'),(2,'b'),(3,'c');
END$$
DELIMITER ;

查看後臺日誌,建立存儲過程是發向主庫(192.168.245.100)的,我想這個你們都沒有疑問:

[11/18/2015 23:00:21] C:192.168.245.1:65459 S:192.168.245.100:3306 OK 23.551 "create procedure a.p_test()
begin
  DECLARE cc INT DEFAULT 0;
  select count(*) into cc from a.a2;
  if cc > 0 then
    delete from a.a2;
  end if;
  insert into a.a2(id,name) values(1,'a'),(2,'b'),(3,'c');
END"

關鍵時刻到來了,那麼執行存儲過程呢?這個時候別忘了開啓主從複製,讓從庫上也有這個存儲過程。執行日誌以下:

[11/18/2015 23:07:48] C:192.168.245.1:65459 S:192.168.245.100:3306 OK 30.336 "call a.p_test()"

【結論】如今知道了吧,在處理存儲過程,不管裏面是否select等,通通的都在主庫上面執行。

  • 參數調整語句:

對於一些調整參數的語句如set read-only=1;show variables like ...這類語句都是發往從庫上執行的,因此對於這類語句強烈建議鏈接到真正的庫上執行

[11/18/2015 22:45:12] C:192.168.245.1:65459 S:192.168.245.131:3306 OK 5.872 "SHOW VARIABLES LIKE 'profiling'"
[11/18/2015 22:45:12] C:192.168.245.1:65459 S:192.168.245.131:3306 OK 26.542 "SET PROFILING = 1"
[11/18/2015 22:45:12] C:192.168.245.1:65459 S:192.168.245.131:3306 OK 2.113 "SET profiling_history_size = 0"
[11/18/2015 22:45:12] C:192.168.245.1:65459 S:192.168.245.131:3306 OK 0.833 "SET profiling_history_size = 15"
[11/18/2015 22:45:12] C:192.168.245.1:65459 S:192.168.245.131:3306 OK 8.288 "SHOW STATUS"
[11/18/2015 22:45:12] C:192.168.245.1:65459 S:192.168.245.131:3306 OK 3.652 "SHOW STATUS"
  • DDL語句:

使用Alter語句操做數據庫的時候,每次操做的都是master.能夠經過atlas的接口發佈DDL語句。

 4、Atlas結合MHA測試

因爲咱們數據庫架構是主從複製+MHA實現主庫的高可用。若是主庫掛了,這時atlas怎麼處理呢?通過詳細的測試,大體處理步驟以下:

 

【說明】

一、主庫上綁定vip,在atlas配置文件中主庫設置爲vip地址,這樣不管主庫怎麼切換,最終的vip不會改變。atlas永遠把vip對應的服務器看成主庫。

二、因爲備用主庫原來是從庫,即在atlas配置文件中是做爲從庫的,故當接管爲主庫時,這時該庫既能夠寫入也能夠讀。故須要手工移除從庫的讀功能。(到管理界面,remove backend idx)

三、若是須要修復原主庫,那麼原主庫做爲新主庫的從庫存在。能夠手工加入atlas中(add slave ip:port)

【結論】:能夠很好的支持MHA切換,可是須要注意以上第2點內容。

相關文章
相關標籤/搜索