MySQL 中介軟體Atlas 實現讀寫分離

神諭丶發表於2016-08-05
〇 Atlas架構介紹

Atlas是Qihoo360開發的一箇中介軟體,位於Client和MySQL Server中間層,可以作為讀寫分離,分庫分表中介軟體。
對於MySQL Server而言,Atlas像是個Client,而對於Client而言,Atlas則是一個DB server。







〇 實驗結構

OS: CentOS 6.5 64bit
MySQL version: 5.6.30

Master:192.168.1.185
Slave:192.168.1.186
proxy(Atlas):192.168.1.187
客戶端:192.168.1.192




〇 MySQL部分:
(主從建立步驟略)
主/從上建立具有增刪改查賬號:
  1. GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO 'dev'@'192.168.1.187' IDENTIFIED BY 'dev';
  2. FLUSH PRIVILEGES;

從庫上可以設定:
  1. SET GLOBAL read_only=1;
如果該從庫永遠不用做master,可以寫到配置檔案中。



〇 Atlas部分
Atlas開發者給出部分建議:

1、Atlas只能執行在64bit的發行版本上
2、若曾經安裝過,在新安裝時會報錯:如“file /usr/local/mysql-proxy/bin/encrypt from install of Atlas-2.0.1-1.x86_64 conflicts with file from package Atlas-1.0.3-1.x86_64”,此時需要sudo rpm –e Atlas-1.0.3-1.x86_64,再執行新的安裝。
3、建議使用MySQL 5.6,此外,不宜小於MySQL 5.1

在proxy機上安裝Atlas:
  1. wget
  2. rpm -ivh Atlas-2.2.1.el6.x86_64.rpm

透過rpm包安裝方式,預設的配置檔案在
/usr/local/mysql-proxy/conf/test.cnf


首先可以先獲取一下之前步驟中,dev@'192.168.1.187'這個使用者加密後的密碼:
# /usr/local/mysql-proxy/bin/encrypt dev
A2OS3vFVUmY=
因為之前給dev使用者的密碼的明文是dev,所以此處也對dev加密,加密後的密碼輸出在其後,也就是A2OS3vFVUmY=這個密碼稍後要新增到Atlas配置檔案中。


test.cnf配置檔案內容可以參考這個:
  1. [mysql-proxy]
  2. # 基礎設定
  3. # 以守護程式方式啟動 
  4. daemon = true
  5. 設定atlas的執行方式,若為true,則表示多一個monitor,該程式會在woker程式掛掉後將其重啟。若為false,則只有一個工作程式woker。
  6. keepalive = true
  7. # atlas例項名,便於區分一臺機子上的不同atlas
  8. instance = test
  9. # 工作執行緒數,atlas開發人員推薦將其設定為CPU個數的2~4倍。
  10. event-threads = 8
  11. # SQL日誌的開關,共有三個可選項:OFF、ON、REALTIME,分別為:不記錄sql日誌、記錄sql日誌,並等待緩衝區填滿後,才會落地到磁碟、記錄sql日誌並實時寫入磁碟。
  12. sql-log = OFF
  13. # 等同於客戶端連線到mysql-server後輸入SET names utf8;
  14. charset = utf8
  15. # 如果這樣配置,可以透過mysql -h127.0.0.1 -P2345 -uadmin -padmin可以連線到Atlas管理介面
  16. admin-username = admin
  17. admin-password = admin
  18. # 該引數設定Atlas後臺管理地址和埠
  19. admin-address = 192.168.1.187:2345
  20. # 設定主庫和從庫的地址,其中主庫為寫庫,從庫為只讀庫
  21. # 主庫地址
  22. proxy-backend-addresses = 192.168.1.185:3306
  23. # 設定讀庫地址和埠
  24. proxy-read-only-backend-addresses = 192.168.1.186:3306
  25. # 若配置為主庫也分擔讀請求,並且設定權重為 (主:從)=(1:3),則可以寫作
  26. #proxy-read-only-backend-addresses = 192.168.1.185:3306@1, 192.168.1.186:3306@3
  27. # 設定Atlas工作監聽的地址和埠,應用程式將連線到這個地址,既然客戶端把Atlas當做一個mysql-server,故此處直接寫成3306埠
  28. proxy-address = 192.168.1.187:3306
  29. # 設定使用者的密碼(這個密碼為MySQL中dev使用者透過Atlas加密程式加密後的密碼),多個可以用逗號隔開
  30. pwds = dev:A2OS3vFVUmY=
  31. # 設定Atlas日誌資訊,其中log-level有message、warning、critical、error、debug五個級別
  32. log-level = message
  33. # 日誌存放的路徑,日誌名為$instance_name.log,比如$log-path/test.log
  34. log-path = /usr/local/mysql-proxy/log
  35. # 設定允許連線Atlas的客戶端ip,非必須,可以是多個,可以是精準ip也可以是ip段,比如:
  36. #client-ips = 127.0.0.1, 192.168.1
  37. # 掛接lvs的物理網路卡ip,若有lvs結構,且設定了client-ips,則必須設定此項,反之可不設定。
  38. #lvs-ips = 192.168.1.1 

配置好後,直接啟動就好:
  1. /usr/local/mysql-proxy/bin/mysql-proxyd test start
其中test為配置檔案中instance的值。
當然可以檢查一下是否已經啟動成功:

  1. /usr/local/mysql-proxy/bin/mysql-proxyd test status
  2. MySQL-Proxy of test is running (5176)
  3. MySQL-Proxy of test is running (5177)


比如這樣就可以連線到Atlas後臺介面:
  1. mysql -h192.168.1.187 -P2345 -uadmin -padmin

進去之後可以檢視當前配置的DBserver和狀態。
  1. mysql> SELECT * FROM backends;
  2. +-------------+--------------------+-------+------+
  3. | backend_ndx | address            | state | type |
  4. +-------------+--------------------+-------+------+
  5. | 1           | 192.168.1.185:3306 | up    | rw   |
  6. | 2           | 192.168.1.186:3306 | up    | ro   |
  7. +-------------+--------------------+-------+------+
  8. 2 rows in set (0.00 sec)

當然更多的選項可以透過SELECT * FROM help;來獲取:
  1. mysql> SELECT * FROM help;
  2. +----------------------------+---------------------------------------------------------+
  3. | command                    | description                                             |    
  4. +----------------------------+---------------------------------------------------------+
  5. | SELECT * FROM help         | shows this help                                         |
  6. | SELECT * FROM backends     | lists the backends and their state                      |
  7. | SET OFFLINE $backend_id    | offline backend server, $backend_id is backend_ndx's id |
  8. | SET ONLINE $backend_id     | online backend server, ...                              |
  9. | ADD MASTER $backend        | example: "add master 127.0.0.1:3306", ...               |
  10. | ADD SLAVE $backend         | example: "add slave 127.0.0.1:3306", ...                |
  11. | REMOVE BACKEND $backend_id | example: "remove backend 1", ...                        |
  12. | SELECT * FROM clients      | lists the clients                                       |
  13. | ADD CLIENT $client         | example: "add client 192.168.1.2", ...                  |
  14. | REMOVE CLIENT $client      | example: "remove client 192.168.1.2", ...               |
  15. | SELECT * FROM pwds         | lists the pwds                                          |
  16. | ADD PWD $pwd               | example: "add pwd user:raw_password", ...               |
  17. | ADD ENPWD $pwd             | example: "add enpwd user:encrypted_password", ...       |
  18. | REMOVE PWD $pwd            | example: "remove pwd user", ...                         |
  19. | SAVE CONFIG                | save the backends to config file                        |
  20. | SELECT VERSION             | display the version of Atlas                            |
  21. +----------------------------+---------------------------------------------------------+


其他引數:
  1. sql-log-slow = 10 # 類似於mysql的long_query_time,如果設定了該選項,則日誌只記錄超過該值的日誌記錄,若沒有新增這個引數選項,則表示全部記錄,單位為ms
  2. wait-timeout = 10 # Atlas會關閉超過該時間之後一直未活躍的連線,單位s
  3. tables = db_name.table_name.user_id.100 # 分表設定,其中格式為:【庫名.表名.分表欄位.子表數量】,若設定多項則用逗號分隔。注,子表必須已經存在,其中子表命名規則為:【表名_數字】,範圍為【0,子表數量-1】,即百表為table_name_0 table_name_1 ... table_name_99。




〇 測試:

為了方便看到請求是否讀寫分離,可以先在master & slave兩個例項上開啟general_log,並放入表中:
  1. SET GLOBAL log_output='TABLE';
  2. SET GLOBAL general_log=on;

master上建立一張測試表:
  1. master> CREATE TABLE test.a(id int);
  2. Query OK, 0 rows affected (0.03 sec)

然後再到客戶端(192.168.1.192)嘗試對Atlas(192.168.1.187)發起增刪改查請求:

此處寫了一個php指令碼來模擬請求:
  1. <?php
  2. $con = mysql_connect("192.168.1.187","dev","dev");
  3. if (!$con){
  4.   die('connect error: ' . mysql_error());
  5.   }

  6. mysql_select_db("my_db", $con);

  7. mysql_query("INSERT INTO test.a SELECT 1;");
  8. mysql_query("UPDATE test.a SET id=222 WHERE id=1;");
  9. mysql_query("DELETE FROM test.a WHERE id=222;");
  10. mysql_query("INSERT INTO test.a SELECT 123456;");
  11. mysql_query("SELECT count(1) FROM test.a;");

  12. mysql_close($con);
  13. ?>

此處可以透過 yum install -y php php-mysql 來安裝一下php相關依賴。

執行這個php指令碼後,可以分別檢查一下master(192.168.1.185)和從庫(192.168.1.186)的general log:
  1. master> SELECT user_host, argument
  2.     -> FROM mysql.general_log
  3.     -> WHERE user_host='dev[dev] @ [192.168.1.187]' ;
  4. +-----------------------------+-------------------------------------+
  5. | user_host                   | argument                            |
  6. +-----------------------------+-------------------------------------+
  7. | dev[dev] @ [192.168.1.187]  | INSERT INTO test.a SELECT 1         |
  8. | dev[dev] @ [192.168.1.187]   | UPDATE test.a SET id=222 WHERE id=1 |
  9. | dev[dev] @ [192.168.1.187]  | DELETE FROM test.a WHERE id=222     |
  10. | dev[dev] @ [192.168.1.187]  | INSERT INTO test.a SELECT 123456    |
  11. +-----------------------------+-------------------------------------+
  12. 4 rows in set (0.00 sec)

  13. slave> SELECT user_host, argument
  14.    -> FROM mysql.general_log
  15.    -> WHERE user_host='dev[dev] @ [192.168.1.187]' ;
  16. +-----------------------------+-----------------------------+
  17. | user_host                   | argument                    |
  18. +-----------------------------+-----------------------------+
  19. | dev[dev] @ [192.168.1.187 | SELECT count(1) FROM test.a |
  20. +-----------------------------+-----------------------------+
  21. 1 rows in set (0.00 sec)

最後再檢查一下跑完這個php指令碼後的test.a表的資料,是否和預期的一致:
  1. slave> SELECT * FROM test.a;
  2. +--------+
  3. | id     |
  4. +--------+
  5. | 123456 |
  6. +--------+
  7. 1 row in set (0.00 sec)


當然,顯然是與預期一致。
顯然Atlas作為proxy,已經將寫請求提交給master(192.168.1.185),將讀請求提交給slave(192.168.1.186)。
對於客戶端和開發人員,只需要獲取一個Atlas的伺服器地址、埠、使用者名稱及密碼便可使用讀寫分離。

Atlas也可以實現分表功能,此處可自行翻閱Atlas Home。



〇 參考文件:



作者微信公眾號(持續更新)





來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29773961/viewspace-2123060/,如需轉載,請註明出處,否則將追究法律責任。

相關文章