mysql-proxy代理加mysql主從實現讀寫分離
一:實驗目標
MySQL Proxy(代理) 服務概述
MySQL Proxy 實現讀寫分離
MySQL Proxy+mysql主從實現讀寫分離
二:實驗環境:
關閉防火牆
mysql-proxy服務端: xuegod62.cn IP:192.168.1.62
mysql服務器(主,負責寫)服務端:xuegod63.cn IP:192.168.1.63
mysql服務器(從,負責讀)客戶端:xuegod64.cn IP:192.168.1.64
端口: mysql-proxy 默認端口:4040
三:實驗概述
主從複製(Master-Slave)的方式來同步數據,再通過讀寫分離(MySQL-Proxy)來提升數據庫的併發負載能力 這樣的方案來進行部署實施的。
工作原理:
1:MySQL Proxy概述
MySQL Proxy是一個處於你的client端和MySQL server端之間的簡單程序,它可以監測、分析或改變它們的通信。它使用靈活,沒有限制,常見的用途包括:負載平衡,故障、查詢分析,查詢過濾和修改等等。
MySQL Proxy就是這麼一箇中間層代理,簡單的說,MySQL Proxy就是一個連接池,負責將前臺應用的連接請求轉發給後臺的數據庫,並且通過使用lua腳本,可以實現複雜的連接控制和過濾,從而實現讀寫分離和負載平衡。對於應用來說,MySQL Proxy是完全透明的,應用則只需要連接到MySQL Proxy的監聽端口即可。當然,這樣proxy機器可能成爲單點失效,但完全可以使用多個proxy機器做爲冗餘,在應用服務器的連接池配置中配置到多個proxy的連接參數即可。
MySQL Proxy更強大的一項功能是實現“讀寫分離”,基本原理是讓主數據庫處理事務性查詢,讓從庫處理SELECT查詢。數據庫複製被用來把事務性查詢導致的變更同步到集羣中的從庫。
Lua概述:
Lua 是一個小巧的腳本語言。Lua的速度是最快的。Lua由標準C編寫而成,幾乎在所有操作系統和平臺上都可以編譯,運行。Lua並沒有提供強大的庫,這是由它的定位決定的。所以Lua不適合作爲開發獨立應用程序的語言。
2:讀寫分離的好處
1)增加冗餘
2)增加了機器的處理能力
3)對於讀操作爲主的應用,使用讀寫分離是最好的場景,因爲可以確保寫的服務器壓力更小,而讀又可以接受點時間上的延遲。
3:讀寫分離提高性能之原因
1)物理服務器增加,負荷增加
2)主從只負責各自的寫和讀,極大程度的緩解X鎖和S鎖爭用
3)從庫可配置myisam引擎,提升查詢性能以及節約系統開銷
4)從庫同步主庫的數據和主庫直接寫還是有區別的,通過主庫發送來的binlog恢復數據,但是,最重要區別在於主庫向從庫發送binlog是異步的,從庫恢復數據也是異步的
5)讀寫分離適用與讀遠大於寫的場景,如果只有一臺服務器,當select很多時,update和delete會被這些select訪問中的數據堵塞,等待select結束,併發性能不高。 對於寫和讀比例相近的應用,應該部署雙主相互複製
6)可以在從庫啓動是增加一些參數來提高其讀的性能,例如--skip-innodb、--skip-bdb、--low-priority-updates以及--delay-key-write=ALL。當然這些設置也是需要根據具體業務需求來定得,不一定能用上
7)分攤讀取。假如我們有1主3從,不考慮上述1中提到的從庫單方面設置,假設現在1 分鐘內有10條寫入,150條讀取。那麼,1主3從相當於共計40條寫入,而讀取總數沒變,因此平均下來每臺服務器承擔了10條寫入和50條讀取(主庫不 承擔讀取操作)。因此,雖然寫入沒變,但是讀取大大分攤了,提高了系統性能。另外,當讀取被分攤後,又間接提高了寫入的性能。所以,總體性能提高了,說白 了就是拿機器和帶寬換性能。MySQL官方文檔中有相關演算公式:官方文檔 見6.9FAQ之“MySQL複製能夠何時和多大程度提高系統性能”
8)MySQL複製另外一大功能是增加冗餘,提高可用性,當一臺數據庫服務器宕機後能通過調整另外一臺從庫來以最快的速度恢復服務,因此不能光看性能,也就是說1主1從也是可以的。
============================================================
四:實驗代碼
1:MySQL-proxy實現讀寫分離
第一塊:安裝mysql-proxy
1:安裝mysql-proxy ---安裝前需要系統支持LUA語言環境。
[root@xuegod62 ~]# rpm -ivh /mnt/Packages/lua-5.1.4-4.1.el6.x86_64.rpm
2:在xuegod62上安裝mysql-proxy: 上傳mysql-proxy
[root@xuegod62~ ]# tar zxvf mysql-proxy-0.8.5-linux-el6-x86-64bit.tar.gz
[root@xuegod62 ~]# mv mysql-proxy-0.8.5-linux-el6-x86-64bit /usr/local/mysql-proxy
3:修改系統命令環境變量:
[root@xuegod62 ~]#export PATH=$PATH:/usr/local/mysql-proxy/bin/ #或者
[root@xuegod62 ~]# vim /etc/bashrc #在最後添加以下內容 :
PATH=$PATH:/usr/local/mysql-proxy/bin/
[root@xuegod62 ~]#source /etc/bashrc
4:mysql-proxy 腳本配置文件位置:
[root@xuegod62 ~]# ls /usr/local/mysql-proxy/share/doc/mysql-proxy/* #下有各種各樣的腳本
rw-splitting.lua #這個就是支持讀寫分離的腳本
5:修改配置文件 實現:讀寫分離
[root@xuegod62 ~]# vim /usr/local/mysql-proxy/share/doc/mysql-proxy
/rw-splitting.lua
改:
40 min_idle_connections = 2,
41 max_idle_connections = 8,
爲:
min_idle_connections = 1,
max_idle_connections = 1,
#現改爲最小1個最大1個。爲了驗證試驗效果將他改成1 .就是當有一個鏈接的時候,就實現讀寫分離的功能。爲了清晰的看到讀寫分離的效果,需要暫時關閉MySQL主從複製功能。
第二塊:搭建mysql服務器
1:xuegod63上創建數據庫和表,用於查看讀寫分離:
[root@xuegod63 ~]#yum install mysql-server -y
[root@xuegod63 ~]# service mysqld start
[root@xuegod63 ~]# mysql
mysql> create database db;
mysql> use db;
mysql> create table test(id int);
mysql> insert into test values(6363);
mysql> grant all on db.* to user1@'%' identified by '123456' ;
#給普通用戶 user1 登錄訪問數據庫權限及密碼
注:% 表示任意遠程客戶端 ,不包括localhost和本地IP地址
2:xuegod64上創建數據庫和表,用於查看讀寫分離:
[root@xuegod64 ~]# yum install mysql-server -y
[root@xuegod64 ~]# service mysqld start
[root@xuegod64 ~]# mysql
mysql> create database db;
mysql> use db;
mysql> create table test(id int);
mysql> insert into test values(6464);
mysql> grant all on db.* to user1@'%' identified by '123456' ;
3:客戶端測試普通用戶登錄mysql主從數據庫
[root@xuegod61 ~]# mysql -u user1 -p123456 -h 192.168.1.63
mysql> use db
[root@xuegod61 ~]# mysql -u user1 -p123456 -h 192.168.1.64
mysql> use db
4:啓動服務mysql-proxy服務
[root@xuegod62 ~]# ls /usr/local/mysql-proxy/bin/
mysql-binlog-dump mysql-myisam-dump mysql-proxy
[root@xuegod62 ~]# mysql-proxy --proxy-read-only-backend-addresses=192.168.1.64:3306 --proxy-backend-addresses=192.168.1.63:3306 --proxy-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua &
(1)參數說明:
--proxy-read-only-backend-addresses=192.168.1.64:3306 # 定義後端只讀服務器
--proxy-backend-addresses=192.168.1.63:3306 #定義後端只寫服務器地址
--proxy-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua & #指定lua腳本,在這裏,使用的是rw-splitting腳本,用於讀寫分離
當有多個只讀服務器時,可以寫多個以下參數:
--proxy-read-only-backend-addresses=192.168.1.66:3306 # 定義後端只讀服務器
--proxy-read-only-backend-addresses=192.168.1.65:3306 # 定義後端只讀服務器
完整的參數可以運行以下命令查看:
[root@xuegod62 ~]# mysql-proxy --help-all
-?, --help Show help options
--help-all Show all help options
(2)查看proxy是否啓動:
[root@xuegod62 ~]# netstat -antup | grep proxy
tcp 0 0 0.0.0.0:4040 0.0.0.0:* LISTEN 2991/mysql-proxy
(3)關閉mysql-proxy服務
[root@xuegod63 ~]# pkill proxy
第三塊:測試mysql-proxy讀寫功能
1:客戶端測試寫功能:
[root@xuegod61 ~]# mysql -u user1 -p123456 -P4040 -h 192.168.1.6:62
mysql> use db;
#select * from test;的時候,看到了6363,表示mysql-proxy將查看請求連接到xuegod63。mysql-proxy指定了xuegod63只具有寫的功能,所以當你插入一天新的數據的時候,你就會查看到你所插入的內容。注:出現的第一次數據都是隻寫的數據,不會是read-only的。
2:客戶端測試讀功能:再打開一個客戶端測試一下讀。
[root@xuegod61 ~]# mysql -u user1 -p123456 -P4040 -h 192.168.1.62
mysql> use db;
#這裏elect * from test;的時候,看到了44,表示mysql-proxy將查看請求連接到xuegod64。
mysql> insert into test values(6363);
mysql> select * from test; #現在是讀的動作,看不到63數據的。
#mysql-proxy指定了xuegod64只具有讀的功能,所以當你插入一個新的數據的時候,你再次查看的時候還是6464,說明你的數據是寫不進去的。
3:客戶端登錄查看:
[root@xuegod61 ~]# mysql –u user1 -p123456 -P4040 -h 192.168.1.62
mysql> show processlist;
列名稱 | 作用 |
id | 服務的一個標識 |
user | 顯示當前用戶,如果不是 root ,這個命令就只顯示你權限範圍內的 sql 語 句。 |
host | 顯示這個語句是從哪個 ip 的哪 個端口上發出的。可以用來追蹤出問題語句的用戶。 |
db | 顯示這個進程目前連接的是哪個數據庫 。 |
command | 顯示當前連接的執行的命令,一般就是休眠( sleep ),查詢( query ),連接( connect )。 |
time | 顯示這個進程目前連接的是哪個數據庫 。 |
state | 顯示使用當前連接的 sql 語句的狀態,很重要的列, state 只是語句執行中的某一個狀態,一個 sql 語句,以查詢爲例,可能需要經過 copying to tmp table ,Sorting result , Sending data 等狀態纔可以完成。 |
info | 顯示這個 sql 語句,因爲長度有限,所以長的 sql 語句就顯示不全,但是一個判斷問題語句的重要依據。 |
2:mysql+proxy+mysql主從實現讀寫分離
1:xuegod63作爲 mysql主:
[root@xuegod63 ~]# cat /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
log-bin=mysqllog
server-id=1
binlog-do-db=db
[root@xuegod63~]# mysql
mysql> grant all on *.* to user2@'%' identified by '123456'; #創建一個主從同步用戶
mysql>use db;
mysql>drop table test; #爲了保持數據完整性,刪除刪一個表。
[root@xuegod63 ~]# service mysqld restart
2:xuegod64 mysql 從配置
[root@xuegod64 ~]# cat /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
server-id=2
master-host=192.168.1.63
master-user=user2
master-password=123456
[root@xuegod64~]# mysql
mysql> grant all on *.* to user2@'%' identified by '123456';# 創建一個主從同步用戶
mysql>use db;
mysql>drop table test; #爲了保持數據完整性,刪除刪一個表。
[root@xuegod64 ~]# service mysqld restart
3:測試主從同步:
1)xuegod63服務器測試同步數據:
[root@xuegod63 ~]# mysql
mysql> use db;
mysql> create table test (id int );
mysql> insert into test values(63);
2)登錄xuegod64查看63同步過來的數據:
[root@xuegod64 ~]# mysql
mysql> use db;
4:客戶端xuegod61:測試使用mysql-proxy 能否讀到同樣的數據。
分析:在客戶端上利用普通MySQL用戶從mysql-proxy上登錄,然後插入數據,看看MySQL的主從上是否顯示。
[root@xuegod61~]# mysql -u user2 -p123456 -P4040 -h192.168.1.62
mysql>use db;
mysql> select * from test;#可以查看到test中的63記錄,說明mysql+proxy+主從讀寫分離成功。
mysql> insert into test values(64);
[root@xuegod63 ~]# mysql
mysql> use db;
#在xuegod62上登錄的mysql數據庫中,寫的數據也得到了同步。
思考:當slave宕機後,mysql-proxy是如何讀取的?
[root@xuegod64 ~]# service mysqld stop
Stopping mysqld: [ OK ]
xuegod62上測試:讀寫:
[root@xuegod62 ~]# mysql -uuser2 -p123456 -P4040 -h192.168.1.62
mysql> use db;
mysql> insert into test values(6464);
xuegod63上查看xuegod64關閉後的客戶端連接:確認讀和寫都是訪問xuegod63
[root@xuegod63 ~]# mysql
mysql> use db;
mysql> show processlist;
+----+-------+--------------------+------+-------------+------+-------------------------------------
總結:當停止掉slave數據庫,proxy的查詢就會轉移到master上,當把slave啓動後,proxy依然在讀master,當有新的鏈接進來的時候纔會重新去讀取slave的數據。有時可能需要重啓下mysql-proxy