ProxySQL實現MySQL讀寫分離

以前咱們已經介紹了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
複製代碼

ProxySQL安裝

下載安裝包服務器

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配置

ProxySQL的配置是支持兩種方式的:配置文件,數據庫

數據庫的配置方式在第一次啓動服務的時候也是基於配置文件的(/etc/proxysql.cnf),後續全部的配置都是在SQLLite中進行,而且不會更新proxysql.cnf配置文件,配置是存儲在/var/lib/proxysql/proxysql.db中

前面提到的在線配置就是基於數據庫的,因此這裏咱們就講解在數據庫中的配置方式

1. 建立服務帳號和monitor帳號

登陸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用於監控

2. 登陸到proxysql管理端

proxysql管理端口默認是6032,默認的用戶名密碼都是admin。

mysql -uadmin -padmin -h127.0.0.1 -P6032
複製代碼

3. 查看數據庫信息

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的健康狀況、各類檢查等
複製代碼

4. 查看配置表

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**將配置存到硬盤上,以便下次重啓時加載,若是忘記執行,當重啓時本次修改的配置會丟失
複製代碼

5. 添加DB實例

咱們一共有三個節點(一個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:容許的最大延遲
複製代碼

6. 添加服務帳號

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)
複製代碼

7. 設置監控帳號

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)
複製代碼

8. 添加規則

讀寫分離規則

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)
複製代碼

9. 完善配置

咱們的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)
複製代碼

10. 將配置加載到運行時

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)
複製代碼

11. 將配置保存到硬盤

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
複製代碼
相關文章
相關標籤/搜索