之前我們已經(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