ProxySQL實(shí)現(xiàn)MySQL讀寫分離

之前我們已經(jīng)介紹了MySQL的高可用

這樣我們至少保證了我們的服務(wù)不會(huì)因?yàn)镸ySQL掛掉而不能使用,不過按照之前的配置我們?cè)L問的時(shí)候依然訪問的是單個(gè)節(jié)點(diǎn),接下來我們就要想辦法為節(jié)點(diǎn)分擔(dān)壓力了,本文介紹的方案是:使用ProxySQL實(shí)現(xiàn)MySQL讀寫分離

ProxySQL是一個(gè)讀寫分離的中間件,開源項(xiàng)目,優(yōu)勢(shì)是強(qiáng)大的規(guī)則引擎、支持在線配置、支持負(fù)載均衡,詳情可以參考官方文檔

ProxySQL還支持prepare、query cache、連接池,這些特性不在本文的介紹范圍內(nèi)

這里需要說明一下,讀寫分離方案是要看實(shí)際場(chǎng)景的。
如果對(duì)數(shù)據(jù)實(shí)時(shí)性要求極高,例如訂單系統(tǒng),是不適合讀寫分離方案的,因?yàn)樽x數(shù)據(jù)節(jié)點(diǎn)同步寫數(shù)據(jù)節(jié)點(diǎn)的數(shù)據(jù)是有一定時(shí)間差的。
當(dāng)然也不是就不能用,只是針對(duì)這種場(chǎng)景需要單獨(dú)設(shè)置此時(shí)讀數(shù)據(jù)和寫數(shù)據(jù)使用同一節(jié)點(diǎn)

下面介紹一下ProxySQL的安裝和配置

說明一下服務(wù)器情況:

1. 一共三臺(tái)服務(wù)器,系統(tǒng)ubuntu16.04 64位
2. IP分別為:192.168.1.222、192.168.1.223、192.168.1.224,均安裝了MySQL5.7
3. 222為master節(jié)點(diǎn),223和224都是slave節(jié)點(diǎn)
4. mha-manager裝在223上,三臺(tái)機(jī)器都裝了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

啟動(dòng)服務(wù)

service proxysql start

ProxySQL配置

ProxySQL的配置是支持兩種方式的:配置文件,數(shù)據(jù)庫

數(shù)據(jù)庫的配置方式在第一次啟動(dòng)服務(wù)的時(shí)候也是基于配置文件的(/etc/proxysql.cnf),后續(xù)所有的配置都是在SQLLite中進(jìn)行,并且不會(huì)更新proxysql.cnf配置文件,配置是存儲(chǔ)在/var/lib/proxysql/proxysql.db中

前面提到的在線配置就是基于數(shù)據(jù)庫的,所以這里我們就講解在數(shù)據(jù)庫中的配置方式

1. 創(chuàng)建服務(wù)賬號(hào)和monitor賬號(hào)

登錄master數(shù)據(jù)庫

mysql mysql -u root -p

添加賬號(hào)并授權(quán)

GRANT ALL ON *.* TO 'proxysql'@'192.168.1.%' IDENTIFIED BY 'proxysql';
GRANT SELECT ON *.* TO 'monitor'@'192.168.1.%' IDENTIFIED BY 'monitor';

要先創(chuàng)建兩個(gè)數(shù)據(jù)庫賬號(hào)用于后續(xù)配置,其中proxysql用于操作數(shù)據(jù)庫,monitor用于監(jiān)控

2. 登錄到proxysql管理端

proxysql管理端口默認(rèn)是6032,默認(rèn)的用戶名密碼都是admin。

mysql -uadmin -padmin -h127.0.0.1 -P6032

3. 查看數(shù)據(jù)庫信息

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:默認(rèn)數(shù)據(jù)庫,存放用戶驗(yàn)證、路由規(guī)則等信息。我們要做的配置都是針對(duì)這個(gè)庫的
disk:持久化到硬盤的配置
stats:proxysql運(yùn)行抓取的統(tǒng)計(jì)信息,如各命令的執(zhí)行次數(shù)、查詢執(zhí)行時(shí)間等
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:各種變量,包括監(jiān)聽的端口、管理賬號(hào)、是否禁用monitor等,詳情可以參考[官方文檔](https://github.com/sysown/proxysql/wiki/Global-variables)
mysql_*:mysql開頭的表就是我們配置要操作的表,具體都是干什么的還是看官方文檔吧,介紹的很細(xì),后面我會(huì)針對(duì)讀寫分離的配置做介紹
runtime_*:runtime開頭的表是運(yùn)行時(shí)讀的表,不能通過DML語句修改,我們針對(duì)mysql開頭的表做完配置修改之后,要執(zhí)行**load mysql xxx to runtime**以將對(duì)應(yīng)的配置加載到運(yùn)行時(shí)環(huán)境
注意:當(dāng)執(zhí)行完load語句將配置加載到運(yùn)行時(shí)環(huán)境后,還要執(zhí)行**save mysql xxx to disk**將配置存到硬盤上,以便下次重啟時(shí)加載,如果忘記執(zhí)行,當(dāng)重啟時(shí)本次修改的配置會(huì)丟失

5. 添加DB實(shí)例

我們一共有三個(gè)節(jié)點(diǎn)(一個(gè)master兩個(gè)slave),要進(jìn)行讀寫分離,這里我們將master設(shè)為寫節(jié)點(diǎn),兩個(gè)slave設(shè)為讀節(jié)點(diǎn)

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:一個(gè)角色一個(gè)id,該表的主鍵是hostgroup_id+hostname+port
hostname:db實(shí)例IP
port:db實(shí)例端口
weight:權(quán)重,如果有多個(gè)相同角色的實(shí)例,會(huì)優(yōu)先選擇權(quán)重高的
status:狀態(tài)
    -ONLINE 正常
    -SHUNNED 臨時(shí)被剔除
    -OFFLINE_SOFT 軟離線狀態(tài),不再接受新的連接,已建立的連接會(huì)等待
    -OFFLINE_HARD 離線,不接收新連接, 已建立的連接也會(huì)強(qiáng)制斷開(宕機(jī)或者網(wǎng)絡(luò)不可用)
max_connections:最大連接數(shù)
max_replication_lag:允許的最大延遲

6. 添加服務(wù)賬號(hào)

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. 設(shè)置監(jiān)控賬號(hào)

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. 添加規(guī)則

讀寫分離規(guī)則

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會(huì)提升為新的master,這個(gè)時(shí)候我們希望proxysql的規(guī)則自動(dòng)變更,在mysql_servers中增加一條記錄,將新的master的hostname和port添加到寫的hostgroup中

proxysql是支撐這種配置的,根據(jù)mysql_replication_hostgroups中的數(shù)據(jù),proxysql通過檢測(cè)到各server的read_only值來自動(dòng)為server設(shè)置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. 將配置加載到運(yùn)行時(shí)

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)

到此讀寫分離的相關(guān)配置就大功告成了!之后我們的應(yīng)用可以通過配置中配置proxysql用戶連接proxysql服務(wù)操作我們的mysql集群

mysql -uproxysql -pproxysql -h 127.0.0.1 -P 6033
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容