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


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

為什么要使用Atlas?應用程序直連數據庫不好嗎?還要在前面加上一層代理,會不會降低應用的讀寫性能?會不會增加維護管理的成本?我想這是每個使用atlas之前的疑問。

1、為什么要使用Atlas?

我們使用atlas,主要使用它的讀寫分離和從庫負載均衡功能。因為咱們這讀業務遠遠多於寫,故采用讀寫分離的架構再合適不過了。之前實現讀寫分離,一般都是通過應用程序實現的,這樣大大增加了開發的難度。而使用atlas,可以將應用和數據庫分離開來,程序員專注業務邏輯開發即可,數據庫對於應用完全透明。另外,才用讀寫分離,還可以增加冗余,增加了機器的處理能力,對於讀操作為主的應用,使用讀寫分離可以確保寫的服務器壓力更小。

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

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

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

一、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

1、這里采用官方推薦的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

2、配置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在配置上做任何改動。

二、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.

三、測試讀寫分離

1、停止主從復制:為了看清inset操作到底是分配到主庫還是從庫上

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

2、連接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語句。

 四、Atlas結合MHA測試

由於我們數據庫架構是主從復制+MHA實現主庫的高可用。如果主庫掛了,這時atlas怎么處理呢?經過詳細的測試,大致處理步驟如下:

 

【說明】

1、主庫上綁定vip,在atlas配置文件中主庫設置為vip地址,這樣無論主庫怎么切換,最終的vip不會改變。atlas永遠把vip對應的服務器當作主庫。

2、由於備用主庫原來是從庫,即在atlas配置文件中是作為從庫的,故當接管為主庫時,這時該庫既可以寫入也可以讀。故需要手工移除從庫的讀功能。(到管理界面,remove backend idx)

3、如果需要修復原主庫,那么原主庫作為新主庫的從庫存在。可以手工加入atlas中(add slave ip:port)

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM