MySQL Router是MySQL官方提供的一個輕量級MySQL中間件,用於取代之前老版本的SQL proxy。html
既然MySQL Router是一個數據庫的中間件,那麼MySQL Router必須可以分析來自前面客戶端的SQL請求是寫請求仍是讀請求,以便決定這個SQL請求是發送給master仍是slave,以及發送給哪一個master、哪一個slave。這樣,MySQL Router就實現了MySQL的讀寫分離,對MySQL請求進行了負載均衡。前端
所以,MySQL Router的前提是後端實現了MySQL的主從複製。mysql
MySQL Router很輕量級,只能經過不一樣的端口來實現簡單的讀/寫分離,且讀請求的調度算法只能使用默認的rr(round-robin),更多一點、更復雜一點的能力都不具有。因此,在實現MySQL Router時,須要自行配置好後端MySQL的高可用。高可用建議經過Percona XtraDB Cluster或MariaDB Galera或MySQL官方的group replication實現,若是實在沒有選擇,還能夠經過MHA實現。linux
因此,一個簡單的MySQL Router部署圖以下。算法
本文將使用MySQL Router分別實現後端無MySQL主從高可用情形的讀寫分離,至於爲何不實現後端有MySQL高可用的讀寫分離情形。在我看來,MySQL Router只是一個玩具,不只功能少,並且須要在應用程序代碼中指定讀/寫的不一樣端口(見後文關於配置文件的解釋),在實際環境中應該沒人會這樣用。sql
如下是實驗環境。shell
角色名 | 主機IP | MySQL版本 | 數據狀態 |
---|---|---|---|
MySQL Router | 192.168.100.21 | MySQL 5.7.22 | 無 |
master | 192.168.100.22 | MySQL 5.7.22 | 全新實例 |
slave1 | 192.168.100.23 | MySQL 5.7.22 | 全新實例 |
slave2 | 192.168.100.24 | MySQL 5.7.22 | 全新實例 |
由於後端MySQL主從複製沒有實現高可用,因此只有一個master節點負責寫操做。數據庫
全部後端MySQL節點都是剛安裝好的全新MySQL實例,因此直接開啓主從複製便可。若是是已有數據的主從複製,須要先保證它們已同步好,方法見:將slave恢復到master指定的座標。vim
二進制版MySQL Router下載地址:https://dev.mysql.com/downloads/router/
rpm倉庫:http://repo.mysql.com/yum/mysql-tools-community/el/7/x86_64/後端
此處使用二進制版的MySQL Router 2.1.6。
tar xf mysqlrouter-2.1.6-linux-glibc2.12-x86-64bit.tar.gz mv mysqlrouter-2.1.6-linux-glibc2.12-x86-64bit /usr/local/mysqlrouter
這就完了,就這麼簡單。
解壓二進制包後,解壓目錄下有如下幾個文件。
[root@s1 mr]# ls bin data include lib run share
bin目錄下只有一個二進制程序mysqlrouter,這也是MySQL Router的主程序。
share目錄下有示例配置文件和示例SysV風格的啓動腳本,可是很不幸該腳本基於debian平臺,在redhat系列上須要修改和安裝一些東西才能使用。因此後文我本身寫了一個centos下的SysV腳本。
[root@s1 mr]# ls share/doc/mysqlrouter/ License.txt README.txt sample_mysqlrouter.conf sample_mysqlrouter.init
最後,將主程序添加到PATH環境變量中。
echo "PATH=$PATH:/usr/local/mysqlrouter/bin" >/etc/profile.d/mysqlrouter.sh chmod +x /etc/profile.d/mysqlrouter.sh source /etc/profile.d/mysqlrouter.sh
如下是上述實驗環境的配置文件,這裏只有一個master節點192.168.100.22:3306
,若是有多個寫節點(master),則使用逗號分隔各節點。關於配置文件,後文會解釋。
[DEFAULT] config_folder = /etc/mysqlrouter logging_folder = /usr/local/mysqlrouter/log runtime_folder = /var/run/mysqlrouter [logger] level = INFO [routing:slaves] bind_address = 192.168.100.21:7001 destinations = 192.168.100.23:3306,192.168.100.24:3306 mode = read-only connect_timeout = 1 [routing:masters] bind_address = 192.168.100.21:7002 destinations = 192.168.100.22:3306 mode = read-write connect_timeout = 2
而後在MySQL Router所在的機器上建立上面使用的目錄。
shell> mkdir /etc/mysqlrouter /usr/local/mysqlrouter/log /var/run/mysqlrouter
這樣就能夠啓動MySQL Router來提供服務了(啓動以前,請確保後端MySQL已被配置好主從複製)。
[root@s1 mr]# mysqlrouter & [1] 16122
查看監聽狀態。這裏監聽的兩個端口7001和7002是前端鏈接MySQL Router用的,它們用來接收前端發送的SQL請求,並按照讀、寫規則,將SQL請求路由到後端MySQL主從節點。
[root@s1 mr]# netstat -tnlp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:6032 0.0.0.0:* LISTEN 1231/proxysql tcp 0 0 0.0.0.0:6033 0.0.0.0:* LISTEN 1231/proxysql tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1152/sshd tcp 0 0 192.168.100.21:7001 0.0.0.0:* LISTEN 16122/mysqlrouter tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 2151/master tcp 0 0 192.168.100.21:7002 0.0.0.0:* LISTEN 16122/mysqlrouter tcp6 0 0 :::22 :::* LISTEN 1152/sshd tcp6 0 0 ::1:25 :::* LISTEN 2151/master
查看日誌:
[root@s1 mr]# cat /usr/local/mysqlrouter/log/mysqlrouter.log 2018-07-07 10:14:29 INFO [7f8a8e253700] [routing:slaves] started: listening on 192.168.100.21:7001; read-only 2018-07-07 10:14:29 INFO [7f8a8ea54700] [routing:masters] started: listening on 192.168.100.21:7002; read-write
最後進行測試便可。測試前,先在後端Master上受權MySQL Router節點容許鏈接,它將會複製到兩個slave節點上。
mysql> grant all on *.* to root@'192.168.100.%' identified by 'P@ssword1!';
連上MySQL Router的7002端口,這個端口是負責寫的端口。因爲沒有配置主從高可用,因此,簡單測試下是否能寫便可。
[root@s1 mr]# mysql -uroot -pP@ssword1! -h192.168.100.21 -P7002 -e 'select @@server_id;' mysql: [Warning] Using a password on the command line interface can be insecure. +-------------+ | @@server_id | +-------------+ | 110 | +-------------+ [root@s1 mr]# mysql -uroot -pP@ssword1! -h192.168.100.21 -P7002 -e 'create database mytest;' mysql: [Warning] Using a password on the command line interface can be insecure. [root@s1 mr]# mysql -uroot -pP@ssword1! -h192.168.100.21 -P7002 -e 'show databases;' mysql: [Warning] Using a password on the command line interface can be insecure. +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | mytest | | performance_schema | | sys | +--------------------+
再測試下各slave節點,是否能實現rr調度算法的讀請求的負載均衡。
[root@s1 mr]# mysql -uroot -pP@ssword1! -h192.168.100.21 -P7001 -e 'select @@server_id;' mysql: [Warning] Using a password on the command line interface can be insecure. +-------------+ | @@server_id | +-------------+ | 120 | +-------------+ [root@s1 mr]# mysql -uroot -pP@ssword1! -h192.168.100.21 -P7001 -e 'select @@server_id;' mysql: [Warning] Using a password on the command line interface can be insecure. +-------------+ | @@server_id | +-------------+ | 130 | +-------------+ [root@s1 mr]# mysql -uroot -pP@ssword1! -h192.168.100.21 -P7001 -e 'show databases;' mysql: [Warning] Using a password on the command line interface can be insecure. +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | mytest | | performance_schema | | sys | +--------------------+
顯然,測試的結果一切正常。
這樣看來MySQL Router好簡單,確實好簡單。只需提供一個合理的配置文件,一切都完成了。那麼,下面解釋下MySQL Router的配置文件。
MySQL Router的配置文件也很簡單,須要配置的項很少。
mysql router默認會尋找安裝目錄下的"mysqlrouter.conf"和家目錄下的".mysqlrouter.conf"。也能夠在二進制程序mysqlrouter命令下使用"-c"或者"--config"手動指定配置文件。
MySQL router的配置文件是片斷式的,經常使用的就3個片斷:[DEFAULT]、[logger]、[routing:NAME]。片斷名稱區分大小寫,且只支持單行"#"或";"註釋,不支持行中、行尾註釋。
以上面示例的配置文件爲例。
[DEFAULT] config_folder = /etc/mysqlrouter logging_folder = /usr/local/mysqlrouter/log runtime_folder = /var/run/mysqlrouter [logger] level = INFO [routing:slaves] bind_address = 192.168.100.21:7001 destinations = 192.168.100.23:3306,192.168.100.24:3306 mode = read-only connect_timeout = 1 [routing:masters] bind_address = 192.168.100.21:7002 destinations = 192.168.100.22:3306 mode = read-write connect_timeout = 2
1.DEFAULT片斷的配置。
[DEFAULT]
片斷一般配置配置文件的目錄、日誌的目錄、MySQL router運行時的目錄(如pid文件)。
例如:
[DEFAULT] config_folder=/etc/mysqlrouter # 指定額外的配置文件目錄,該目錄下的conf文件都會被加載 logging_folder=/usr/local/mysqlrouter/log # 指定日誌目錄,日誌文件名爲mysqlrouter.log runtime_folder=/var/run/mysqlrouter # 指定運行時目錄,默認爲/run/mysqlrouter
2.logger片斷的配置。
[logger]
片斷只有一個選項,設置日誌的記錄級別。
[logger] level=debug # 有debug、info(默認)、warning、error、fatal,不區分大小寫
3.routing片斷的配置。
[routing:NAME]
是MySQL router主要部分,設置不一樣的路由實例,其中NAME能夠隨意命名。如[routing:slaves]
、[routing:masters]
。
在routing配置片斷,能夠設置的選項包括:
bind_address
和bind_port
IP:PORT
格式指定。[routing:slaves] bind_port = 7001 [routing:slaves] bind_address = 192.168.100.21 bind_port = 7001 [routing:slaves] bind_address = 192.168.100.21:7001
通常來講,經過不一樣端口實現讀/寫分離,並不是好方法,最大的緣由是須要在應用程序代碼中指定這些鏈接端口。可是,MySQL Router只能經過這種方式實現讀寫分離,因此MySQL Router拿來當玩具玩玩就好。
destinations
HOST:PORT
,HOST能夠是IP也能夠是主機名,多個轉發目標使用逗號分隔。如定義的目標列表是多個slave。[routing:slaves] bind_address = 192.168.100.21:7001 destinations = 192.168.100.23:3306,192.168.100.24:3306 [routing:masters] bind_address = 192.168.100.21:7002 destinations = 192.168.100.22:3306,192.168.100.100:3306
mode
connect_timeout
配置文件大概就這些內容,配置好後,記得先建立default片斷中涉及到的目錄。以後就能夠啓動mysql router提供讀/寫分離服務了。
MySQL Router只提供了一個主程序(bin目錄下的mysqlrouter),且該程序只能啓動,沒有中止選項,因此只能使用kill命令來殺掉進程。
MySQL Router也提供了示例啓動腳本,該腳本在位置爲$basedir/share/doc/mysqlrouter/sample_mysqlrouter.init
,可是該腳本是基於Debian平臺的,在CentOS上須要設置和安裝一些東西,因此不用它,本身寫個粗糙點的腳本便可。
shell> vim /etc/init.d/mysqlrouter #!/bin/bash # chkconfig: - 78 30 # Description: Start / Stop MySQL Router DAEMON=/usr/local/mysqlrouter proc=$DAEMON/bin/mysqlrouter DAEMON_OPTIONS="-c ${DAEMON}/mysqlrouter.conf" . /etc/init.d/functions start() { if [ -e /var/lock/subsys/mysqlrouter ]; then action "MySQL Router is working" /bin/false else $proc $DAEMON_OPTIONS & &>/dev/null retval=$? echo if [ $retval -eq 0 ]; then touch /var/lock/subsys/mysqlrouter action "Starting MySQL Router" /bin/true else echo "Starting MySQL Router Failure" fi fi } stop() { if [ -e /var/lock/subsys/mysqlrouter ]; then killall $proc retval=$? echo if [ $retval -eq 0 ]; then rm -f /var/lock/subsys/mysqlrouter action "Stoping MySQL Router" /bin/true fi else action "MySQL Router is not working" /bin/false fi } status() { if [ -e /var/lock/subsys/mysqlrouter ]; then echo "MySQL Router is running" else echo "MySQL Router is not running" fi } case "$1" in start) start sleep 1 ;; stop) stop sleep 1 ;; restart) stop start sleep 1 ;; status) status ;; *) echo "Usage: $0 {start|stop|status|restart}" retval=1 ;; esac exit $retval
而後賦予執行權限。
shell> chmod +x /etc/init.d/mysqlrouter