MySQL讀寫分離概念
MYSQL讀寫分離的原理其實就是讓Master數據庫處理事務性增、刪除、修改、更新操作(CREATE、INSERT、UPDATE、DELETE),而讓Slave數據庫處理SELECT操作,MYSQL讀寫分離前提是基於MYSQL主從複製,這樣可以保證在Master上修改數據,Slave同步之後,WEB應用可以讀取到Slave端的數據。
讀寫分離實現方式
實現MYSQL讀寫分離可以基於第三方插件,也可以通過開發修改代碼實現,具體實現的讀寫分離的常見方式有如下四種:
Amoeba讀寫分離;
MySQL-Proxy讀寫分離;
Mycat讀寫分離;
proxy。它集中地響應WEB應用的請求,依據用戶事先設置的規則,將SQL請求發送到特定的數據庫上執行,基於此可以實現負載均衡、讀寫分離、高可用性等需求。
Mysql-Proxy是MySQL官方提供的mysql中間件服務,支持無數客戶端連接,同時後端可連接若干臺Mysql-Server服務器,MYSQL-Proxy自身基於MySQL協議,連接MYSQL-Proxy的客戶端無需修改任何設置, 跟正常連接MYSQL Server沒有區別,無需修改程序代碼。
基於mysql-proxy實現讀寫分離
工作原理圖解
下載proxy centos7.4+mysql5.5
proxy可以選擇和mysql部署在同一臺服務器,也可以選擇單獨部署在另一臺獨立服務器。
proxy: 192.168.179.101
master: 192.168.179.100
slave: 192.168.179.99
下載mysql-proxy:
[root@localhost ~]#
wget http://mirrors.163.com/mysql/Downloads/MySQL-Proxy/mysql-proxy-0.8.4-linuxel6-x86-64bit.tar.gz
[root@localhost src]# ls
debug kernels mysql-proxy-0.8.4-linux-el6-x86-64bit.tar.gz
[root@localhost src]# tar xf mysql-proxy-0.8.4-linux-el6-x86-64bit.tar.gz
[root@localhost src]# mv mysql-proxy-0.8.4-linux-el6-x86-64bit /usr/local/
[root@localhost local]# mv mysql-proxy-0.8.4-linux-el6-x86-64bit mysql-proxy
[root@localhost local]# cd mysql-proxy/
[root@localhost mysql-proxy]# ls --可以看到已經是二進制的包,不需要編譯安裝
bin include lib libexec licenses share
配置proxy環境變量
[root@localhost ~]# echo "export PATH=/usr/local/mysql-proxy/bin:$PATH" > /etc/profile.d/mysql-proxy.sh
[root@localhost ~]# . /etc/profile.d/mysql-proxy.sh --執行腳本來配置root用戶環境變量
[root@localhost ~]# echo $PATH
/usr/local/mysql-proxy/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
啓動MYSQL-Proxy中間件
[root@localhost ~]# useradd -r mysql-proxy --添加mysql-proxy系統用戶,這個用戶是需要在主庫授權用來讀寫分離的
[root@localhost ~]#
mysql-proxy --daemon --log-level=debug --user=mysql-proxy --keepalive --log-file=/var/log/mysql-proxy.log --plugins="proxy" --proxy-backend-addresses="192.168.179.99:3306" --proxy-read-only-backend-addresses="192.168.179.100:3306" --proxy-lua-script="/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua" --plugins=admin --admin-username="admin" --admin-password="admin" --admin-lua-script="/usr/local/mysql-proxy/lib/mysql-proxy/lua/admin.lua"
啓動的相關參數
Mysql-Proxy的相關參數詳解如下:
--help-all :獲取全部幫助信息;
--proxy-address=host:port :代理服務監聽的地址和端口,默認爲4040;
--admin-address=host:port :管理模塊監聽的地址和端口,默認爲4041;
--proxy-backend-addresses=host:port :後端寫的mysql服務器的地址和端口;
--proxy-read-only-backend-addresses=host:port :後端只讀的mysql服務器的地址和端口;
--proxy-lua-script=file_name :完成mysql代理功能的Lua腳本;
--daemon :以守護進程模式啓動mysql-proxy;
--keepalive :在mysql-proxy崩潰時嘗試重啓之;
--log-file=/path/to/log_file_name :日誌文件名稱;
--log-level=level :日誌級別;
--log-use-syslog :基於syslog記錄日誌;
--plugins=plugin :在mysql-proxy啓動時加載的插件;
--user=user_name :運行mysql-proxy進程的用戶;
--defaults-file=/path/to/conf_file_name :默認使用的配置文件路徑,其配置段使用[mysqlproxy]標識;
--proxy-skip-profiling :禁用profile;
--pid-file=/path/to/pid_file_name :進程文件名;
[root@localhost ~]# netstat -tpln | grep 40 --出現兩個端口4040 4041才證明服務正常啓動 如果只有4040殺掉進程pkill mysql-proxy 再重啓服務,執行上面的語句
4040端口是給數據端口,即數據的讀寫都是通過該端口 4041是管理端口的,可以查看讀寫狀態
tcp 0 0 0.0.0.0:4040 0.0.0.0:* LISTEN 1830/mysql-proxy
tcp 0 0 0.0.0.0:4041 0.0.0.0:* LISTEN 1830/mysql-proxy .
通過proxy查看讀寫分離狀態
基於4041端口MySQL-Proxy查看讀寫分離狀態,登錄4041管理端口 :
[root@localhost ~]# yum install mariadb -y 先下載mysql的客戶端工具就可以使用mysql命令了來登入到4041管理端口了
[root@localhost ~]# mysql -h192.168.179.101 -uadmin -padmin -P4041 --通過之前proxy配置的用戶admin通過4041端口來登入到mysql proxy的頁面
MySQL [(none)]> select * from backends; --可以看到主庫是可讀可寫的,從庫是隻讀的
+-------------+----------------------+---------+------+------+-------------------+
| backend_ndx | address | state | type | uuid | connected_clients |
+-------------+----------------------+---------+------+------+-------------------+
| 1 | 192.168.179.99:3306 | unknown | rw | NULL | 0 |
| 2 | 192.168.179.100:3306 | unknown | ro | NULL | 0 |
+-------------+----------------------+---------+------+------+-------------------+
這時可以看到後端數據庫信息,只是狀態爲unknown,表示還沒有客戶端連接,可以通過4040代理端口通過查詢數據等操作激活。
在master主庫上192.168.179.99授權proxy用戶
授權proxy,授權proxy用戶,這個用戶是要給到前端開發人員的,對數據庫具有讀寫功能
mysql> grant all on *.* to "mysql-proxy"@"192.168.179.101" identified by "123456";
Query OK, 0 rows affected (0.01 sec)
允許mysql-proxy用戶從192.168.179.101上來登入到主庫或者從庫來進行對數據庫所有操作
mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)
mysql> select user,host from mysql.user; --在主庫授權完可以看到在從庫上也是授權了,因爲同步所以就不需要再到從庫上再次授權,
+-------------+-----------------------+
| user | host |
+-------------+-----------------------+
| root | 127.0.0.1 |
| jfedu | 192.168.179.100 |
| mysql-proxy | 192.168.179.101 |
通過proxy代理創建數據庫,驗證寫是走主庫
通過4040代理端口插入數據,該sql語句會走master,於是可以激活master狀態:
[root@localhost ~]# mysql -h192.168.179.101 -umysql-proxy -p123456 -P4040
MySQL [(none)]> create database students charset utf8; --這是寫操作
Query OK, 1 row affected (0.00 sec)
在4041管理端口,再次查看
[root@localhost ~]# mysql -h192.168.179.101 -uadmin -padmin -P4041 --再次登入mysql proxy終端查看
MySQL [(none)]> select * from backends; --可以看到主庫已經激活了up
+-------------+----------------------+---------+------+------+-------------------+
| backend_ndx | address | state | type | uuid | connected_clients |
+-------------+----------------------+---------+------+------+-------------------+
| 1 | 192.168.179.99:3306 | up | rw | NULL | 0 |
| 2 | 192.168.179.100:3306 | unknown | ro | NULL | 0 |
+-------------+----------------------+---------+------+------+-------------------+
通過代理查詢數據是走從庫
通過proxy創建了一張表,然後插入數據,查詢該表
MySQL [students]> select * from t1;
+------+----------+
| id | name |
+------+----------+
| 1 | xiaoming |
+------+----------+
1 row in set (0.00 sec)
可以看到通過4040代理端口查詢數據,該sql語句會走slave,於是可以激活slave狀態
MySQL [(none)]> select * from backends;
+-------------+----------------------+---------+------+------+-------------------+
| backend_ndx | address | state | type | uuid | connected_clients |
+-------------+----------------------+---------+------+------+-------------------+
| 1 | 192.168.179.99:3306 | up | rw | NULL | 0 |
| 2 | 192.168.179.100:3306 | up | ro | NULL | 0 |
+-------------+----------------------+---------+------+------+-------------------+
2 rows in set (0.00 sec)
或者換種方式驗證查詢的數據是不是來自從庫
mysql> insert into t1 values(2,"xiaohua"); --在從庫插入數據,這個時候主庫是沒有該條數據的
Query OK, 1 row affected (0.01 sec)
mysql> select * from t1; --從庫查詢數據
+------+----------+
| id | name |
+------+----------+
| 1 | xiaoming |
| 2 | xiaohua |
+------+----------+
2 rows in set (0.00 sec)
[root@localhost ~]# mysql -h192.168.179.101 -umysql-proxy -p123456 -P4040 -e "select * from students.t1" --再去通過proxy查詢,可以看到xiaohua數據是來源於從庫的,可以看到讀操作的數據來源於從庫
+------+----------+
| id | name |
+------+----------+
| 1 | xiaoming |
| 2 | xiaohua |
+------+----------+
[root@localhost ~]# mysql -h192.168.179.101 -umysql-proxy -p123456 -P4040 --通過proxy插入數據向t1插入數據
MySQL [(none)]> use students;
Database changed
MySQL [students]> insert into t1 values(3,"lihua");
Query OK, 1 row affected (0.01 sec)
mysql> select * from t1; --在主庫查詢
+------+----------+
| id | name |
+------+----------+
| 1 | xiaoming |
| 3 | lihua |
+------+----------+
mysql> select * from t1; --從庫查看數據,可以看到通過proxy插入主庫的數據同步到了從庫
+------+----------+
| id | name |
+------+----------+
| 1 | xiaoming |
| 2 | xiaohua |
| 3 | lihua |
+------+----------+
如果主庫宕機了,是不能提供寫操作的,只能進行讀操作,不能將從庫切換爲主庫,如果需要實現自動切換需要使用mycat來實現