以前咱們已經介紹了MySQL的高可用node
這樣咱們至少保證了咱們的服務不會由於MySQL掛掉而不能使用,不過按照以前的配置咱們訪問的時候依然訪問的是單個節點,接下來咱們就要想辦法爲節點分擔壓力了,本文介紹的方案是:使用ProxySQL實現MySQL讀寫分離mysql
ProxySQL是一個讀寫分離的中間件,開源項目,優點是強大的規則引擎、支持在線配置、支持負載均衡,詳情能夠參考官方文檔git
ProxySQL還支持prepare、query cache、鏈接池,這些特性不在本文的介紹範圍內github
這裏須要說明一下,讀寫分離方案是要看實際場景的。 若是對數據實時性要求極高,例如訂單系統,是不適合讀寫分離方案的,由於讀數據節點同步寫數據節點的數據是有必定時間差的。 固然也不是就不能用,只是針對這種場景須要單獨設置此時讀數據和寫數據使用同一節點sql
下面介紹一下ProxySQL的安裝和配置數據庫
說明一下服務器狀況:ubuntu
1. 一共三臺服務器,系統ubuntu16.04 64位
2. IP分別爲:192.168.1.22二、192.168.1.22三、192.168.1.224,均安裝了MySQL5.7
3. 222爲master節點,223和224都是slave節點
4. mha-manager裝在223上,三臺機器都裝了mha-node
複製代碼
下載安裝包服務器
wget https://github.com/sysown/proxysql/releases/download/v1.4.9/proxysql_1.4.9-dbg-ubuntu16_amd64.deb
複製代碼
安裝網絡
dpkg -i proxysql_1.4.9-dbg-ubuntu16_amd64.deb
複製代碼
啓動服務app
service proxysql start
複製代碼
ProxySQL的配置是支持兩種方式的:配置文件,數據庫
數據庫的配置方式在第一次啓動服務的時候也是基於配置文件的(/etc/proxysql.cnf),後續全部的配置都是在SQLLite中進行,而且不會更新proxysql.cnf配置文件,配置是存儲在/var/lib/proxysql/proxysql.db中
前面提到的在線配置就是基於數據庫的,因此這裏咱們就講解在數據庫中的配置方式
登陸master數據庫
mysql mysql -u root -p
複製代碼
添加帳號並受權
GRANT ALL ON *.* TO 'proxysql'@'192.168.1.%' IDENTIFIED BY 'proxysql';
GRANT SELECT ON *.* TO 'monitor'@'192.168.1.%' IDENTIFIED BY 'monitor';
複製代碼
要先建立兩個數據庫帳號用於後續配置,其中proxysql用於操做數據庫,monitor用於監控
proxysql管理端口默認是6032,默認的用戶名密碼都是admin。
mysql -uadmin -padmin -h127.0.0.1 -P6032
複製代碼
mysql> show databases;
+-----+---------------+-------------------------------------+
| seq | name | file |
+-----+---------------+-------------------------------------+
| 0 | main | |
| 2 | disk | /var/lib/proxysql/proxysql.db |
| 3 | stats | |
| 4 | monitor | |
| 5 | stats_history | /var/lib/proxysql/proxysql_stats.db |
| 6 | myhgm | |
+-----+---------------+-------------------------------------+
6 rows in set (0.00 sec)
複製代碼
main:默認數據庫,存放用戶驗證、路由規則等信息。咱們要作的配置都是針對這個庫的
disk:持久化到硬盤的配置
stats:proxysql運行抓取的統計信息,如各命令的執行次數、查詢執行時間等
monitor:monitor模塊收集的信息,db的健康狀況、各類檢查等
複製代碼
mysql> show tables;
+--------------------------------------------+
| tables |
+--------------------------------------------+
| debug_levels |
| global_variables |
| mysql_collations |
| mysql_group_replication_hostgroups |
| mysql_query_rules |
| mysql_query_rules_fast_routing |
| mysql_replication_hostgroups |
| mysql_servers |
| mysql_users |
| proxysql_servers |
| runtime_checksums_values |
| runtime_global_variables |
| runtime_mysql_group_replication_hostgroups |
| runtime_mysql_query_rules |
| runtime_mysql_query_rules_fast_routing |
| runtime_mysql_replication_hostgroups |
| runtime_mysql_servers |
| runtime_mysql_users |
| runtime_proxysql_servers |
| runtime_scheduler |
| scheduler |
+--------------------------------------------+
21 rows in set (0.00 sec)
複製代碼
global_variables:各類變量,包括監聽的端口、管理帳號、是否禁用monitor等,詳情能夠參考[官方文檔](https://github.com/sysown/proxysql/wiki/Global-variables)
mysql_*:mysql開頭的表就是咱們配置要操做的表,具體都是幹什麼的仍是看官方文檔吧,介紹的很細,後面我會針對讀寫分離的配置作介紹
runtime_*:runtime開頭的表是運行時讀的表,不能經過DML語句修改,咱們針對mysql開頭的表作完配置修改以後,要執行**load mysql xxx to runtime**以將對應的配置加載到運行時環境
注意:當執行完load語句將配置加載到運行時環境後,還要執行**save mysql xxx to disk**將配置存到硬盤上,以便下次重啓時加載,若是忘記執行,當重啓時本次修改的配置會丟失
複製代碼
咱們一共有三個節點(一個master兩個slave),要進行讀寫分離,這裏咱們將master設爲寫節點,兩個slave設爲讀節點
mysql> insert into mysql_servers(hostgroup_id,hostname,port,weight,max_connections,max_replication_lag,comment) values(1000,'192.168.1.222',3306,1,1000,10,'write group');
Query OK, 1 row affected (0.00 sec)
mysql> insert into mysql_servers(hostgroup_id,hostname,port,weight,max_connections,max_replication_lag,comment) values(2000,'192.168.1.223',3306,1,1000,10,'read group');
Query OK, 1 row affected (0.00 sec)
mysql> insert into mysql_servers(hostgroup_id,hostname,port,weight,max_connections,max_replication_lag,comment) values(2000,'192.168.1.224',3306,1,1000,10,'read group');
Query OK, 1 row affected (0.00 sec)
mysql> select * from mysql_servers;
+--------------+---------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+-------------+
| hostgroup_id | hostname | port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+---------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+-------------+
| 1000 | 192.168.1.222 | 3306 | ONLINE | 1 | 0 | 1000 | 10 | 0 | 0 | write group |
| 2000 | 192.168.1.223 | 3306 | ONLINE | 1 | 0 | 1000 | 10 | 0 | 0 | read group |
| 2000 | 192.168.1.224 | 3306 | ONLINE | 1 | 0 | 1000 | 10 | 0 | 0 | read group |
+--------------+---------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+-------------+
3 rows in set (0.00 sec)
複製代碼
hostgroup_id:一個角色一個id,該表的主鍵是hostgroup_id+hostname+port
hostname:db實例IP
port:db實例端口
weight:權重,若是有多個相同角色的實例,會優先選擇權重高的
status:狀態
-ONLINE 正常
-SHUNNED 臨時被剔除
-OFFLINE_SOFT 軟離線狀態,再也不接受新的鏈接,已創建的鏈接會等待
-OFFLINE_HARD 離線,不接收新鏈接, 已創建的鏈接也會強制斷開(宕機或者網絡不可用)
max_connections:最大鏈接數
max_replication_lag:容許的最大延遲
複製代碼
mysql> INSERT INTO mysql_users(username,password,default_hostgroup) VALUES ('proxysql','proxysql',1000);
Query OK, 1 row affected (0.01 sec)
mysql> select * from mysql_users;
+----------+----------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+
| username | password | active | use_ssl | default_hostgroup | default_schema | schema_locked | transaction_persistent | fast_forward | backend | frontend | max_connections |
+----------+----------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+
| proxysql | proxysql | 1 | 0 | 1000 | NULL | 0 | 1 | 0 | 1 | 1 | 10000 |
+----------+----------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+
1 row in set (0.01 sec)
複製代碼
mysql> set mysql-monitor_username='monitor';
Query OK, 1 row affected (0.00 sec)
mysql> set mysql-monitor_password='monitor';
Query OK, 1 row affected (0.00 sec)
複製代碼
讀寫分離規則
mysql> insert into mysql_query_rules(rule_id,active,match_digest,destination_hostgroup,apply)values(1,1,'^SELECT.*FOR UPDATE$',1000,1);
Query OK, 1 row affected (0.00 sec)
mysql> insert into mysql_query_rules(rule_id,active,match_digest,destination_hostgroup,apply)values(2,1,'^SELECT',2000,1);
Query OK, 1 row affected (0.00 sec)
mysql> select rule_id,active,match_digest,destination_hostgroup,apply from mysql_query_rules;
+---------+--------+----------------------+-----------------------+-------+
| rule_id | active | match_digest | destination_hostgroup | apply |
+---------+--------+----------------------+-----------------------+-------+
| 1 | 1 | ^SELECT.*FOR UPDATE$ | 1000 | 1 |
| 2 | 1 | ^SELECT | 2000 | 1 |
+---------+--------+----------------------+-----------------------+-------+
2 rows in set (0.00 sec)
複製代碼
咱們的mysql集羣是基於MHA的,master掛掉以後,slave會提高爲新的master,這個時候咱們但願proxysql的規則自動變動,在mysql_servers中增長一條記錄,將新的master的hostname和port添加到寫的hostgroup中
proxysql是支撐這種配置的,根據mysql_replication_hostgroups中的數據,proxysql經過檢測到各server的read_only值來自動爲server設置hostgroup_id
mysql> insert into mysql_replication_hostgroups (writer_hostgroup,reader_hostgroup,comment) values(1000,2000,'Reading and Writing Separation');
Query OK, 1 row affected (0.00 sec)
mysql> select * from runtime_mysql_replication_hostgroups;
+------------------+------------------+--------------------------------+
| writer_hostgroup | reader_hostgroup | comment |
+------------------+------------------+--------------------------------+
| 1000 | 2000 | Reading and Writing Separation |
+------------------+------------------+--------------------------------+
1 row in set (0.01 sec)
複製代碼
mysql> load mysql users to runtime;
Query OK, 0 rows affected (0.00 sec)
mysql> load mysql servers to runtime;
Query OK, 0 rows affected (0.00 sec)
mysql> load mysql query rules to runtime;
Query OK, 0 rows affected (0.00 sec)
mysql> load mysql variables to runtime;
Query OK, 0 rows affected (0.00 sec)
mysql> load admin variables to runtime;
Query OK, 0 rows affected (0.00 sec)
複製代碼
mysql> save mysql users to disk;
Query OK, 0 rows affected (0.15 sec)
mysql> save mysql servers to disk;
Query OK, 0 rows affected (0.33 sec)
mysql> save mysql query rules to disk;
Query OK, 0 rows affected (0.36 sec)
mysql> save mysql variables to disk;
Query OK, 96 rows affected (0.09 sec)
mysql> save admin variables to disk;
Query OK, 32 rows affected (0.09 sec)
複製代碼
到此讀寫分離的相關配置就大功告成了!以後咱們的應用能夠經過配置中配置proxysql用戶鏈接proxysql服務操做咱們的mysql集羣
mysql -uproxysql -pproxysql -h 127.0.0.1 -P 6033
複製代碼