MySQL Proxy的幾篇文章

最近打算用MySQL的讀寫分離,從網上摘錄了幾篇。

 

MySQL主從複製(Master-Slave)與讀寫分離(MySQL-Proxy)實踐

 

原址如下:

http://heylinux.com/archives/1004.html

http://blog.csdn.net/edwzhang/article/details/8475624

Mysql作爲目前世界上使用最廣泛的免費數據庫,相信所有從事系統運維的工程師都一定接觸過。但在實際的生產環境中,由單臺Mysql作爲獨立的數據庫是完全不能滿足實際需求的,無論是在安全性,高可用性以及高併發等各個方面。

因此,一般來說都是通過 主從複製(Master-Slave)的方式來同步數據,再通過讀寫分離(MySQL-Proxy)來提升數據庫的併發負載能力 這樣的方案來進行部署與實施的。

如下圖所示:

下面是我在實際工作過程中所整理的筆記,在此分享出來,以供大家參考。

一、MySQL的安裝與配置
具體的安裝過程,建議參考我的這一篇文章:http://heylinux.com/archives/993.html
值得一提的是,我的安裝過程都是源碼包編譯安裝的,並且所有的配置與數據等都統一規劃到了/opt/mysql目錄中,因此在一臺服務器上安裝完成以後,可以將整個mysql目錄打包,然後傳到其它服務器上解包,便可立即使用。

二、MySQL主從複製
場景描述:
主數據庫服務器:192.168.10.130,MySQL已經安裝,並且無應用數據。
從數據庫服務器:192.168.10.131,MySQL已經安裝,並且無應用數據。

2.1 主服務器上進行的操作
啓動mysql服務
/opt/mysql/init.d/mysql start

通過命令行登錄管理MySQL服務器
/opt/mysql/bin/mysql -uroot -p'new-password'

授權給從數據庫服務器192.168.10.131
mysql> GRANT REPLICATION SLAVE ON *.* to 'rep1'@'192.168.10.131' identified by ‘password’;

查詢主數據庫狀態
Mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000005 | 261 | | |
+------------------+----------+--------------+------------------+

記錄下 FILE 及 Position 的值,在後面進行從服務器操作的時候需要用到。

2.2 配置從服務器
修改從服務器的配置文件/opt/mysql/etc/my.cnf
將 server-id = 1修改爲 server-id = 10,並確保這個ID沒有被別的MySQL服務所使用。

啓動mysql服務
/opt/mysql/init.d/mysql start

通過命令行登錄管理MySQL服務器
/opt/mysql/bin/mysql -uroot -p'new-password'

執行同步SQL語句
mysql> change master to
master_host=’192.168.10.130’,
master_user=’rep1’,
master_password=’password’,
master_log_file=’mysql-bin.000005’,
master_log_pos=261;

正確執行後啓動Slave同步進程
mysql> start slave;

主從同步檢查
mysql> show slave status\G
==============================================
**************** 1. row *******************
Slave_IO_State:
Master_Host: 192.168.10.130
Master_User: rep1
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000005
Read_Master_Log_Pos: 415
Relay_Log_File: localhost-relay-bin.000008
Relay_Log_Pos: 561
Relay_Master_Log_File: mysql-bin.000005
Slave_IO_Running: YES
Slave_SQL_Running: YES
Replicate_Do_DB:
……………省略若干……………
Master_Server_Id: 1
1 row in set (0.01 sec)
==============================================

其中Slave_IO_Running 與 Slave_SQL_Running 的值都必須爲YES,才表明狀態正常。

如果主服務器已經存在應用數據,則在進行主從複製時,需要做以下處理:
(1)主數據庫進行鎖表操作,不讓數據再進行寫入動作
mysql> FLUSH TABLES WITH READ LOCK;

(2)查看主數據庫狀態
mysql> show master status;

(3)記錄下 FILE 及 Position 的值。
將主服務器的數據文件(整個/opt/mysql/data目錄)複製到從服務器,建議通過tar歸檔壓縮後再傳到從服務器解壓。

(4)取消主數據庫鎖定
mysql> UNLOCK TABLES;

2.3 驗證主從複製效果

主服務器上的操作
在主服務器上創建數據庫first_db
mysql> create database first_db;
Query Ok, 1 row affected (0.01 sec)

在主服務器上創建表first_tb
mysql> create table first_tb(id int(3),name char(10));
Query Ok, 1 row affected (0.00 sec)

在主服務器上的表first_tb中插入記錄
mysql> insert into first_tb values (001,’myself’);
Query Ok, 1 row affected (0.00 sec)

在從服務器上查看
mysql> show databases;
=============================
+--------------------+
| Database |
+--------------------+
| information_schema |
| first_db |
| mysql |
| performance_schema |
| test |
+--------------------+
5 rows in set (0.01 sec)
=============================
數據庫first_db已經自動生成

mysql> use first_db
Database chaged

mysql> show tables;
=============================
+--------------------+
| Tables_in_first_db |
+--------------------+
| first_tb |
+--------------------+
1 row in set (0.02 sec)
=============================
數據庫表first_tb也已經自動創建

mysql> select * from first_tb;
=============================
+------+------+
| id | name |
+------+------+
| 1 | myself |
+------+------+
1 rows in set (0.00 sec)
=============================
記錄也已經存在

由此,整個MySQL主從複製的過程就完成了,接下來,我們進行MySQL讀寫分離的安裝與配置。

三、MySQL讀寫分離
場景描述:
數據庫Master主服務器:192.168.10.130
數據庫Slave從服務器:192.168.10.131
MySQL-Proxy調度服務器:192.168.10.132

以下操作,均是在192.168.10.132即MySQL-Proxy調度服務器 上進行的。

3.1 MySQL的安裝與配置
具體的安裝過程與上文相同。

3.2 檢查系統所需軟件包
通過 rpm -qa | grep name 的方式驗證以下軟件包是否已全部安裝。
gcc* gcc-c++* autoconf* automake* zlib* libxml* ncurses-devel* libmcrypt* libtool* flex* pkgconfig*
libevent* glib*

若缺少相關的軟件包,可通過yum -y install方式在線安裝,或直接從系統安裝光盤中找到並通過rpm -ivh方式安裝。

3.3 編譯安裝lua
MySQL-Proxy的讀寫分離主要是通過rw-splitting.lua腳本實現的,因此需要安裝lua。

lua可通過以下方式獲得
從http://www.lua.org/download.html下載源碼包

從rpm.pbone.net搜索相關的rpm包
download.fedora.redhat.com/pub/fedora/epel/5/i386/lua-5.1.4-4.el5.i386.rpm
download.fedora.redhat.com/pub/fedora/epel/5/x86_64/lua-5.1.4-4.el5.x86_64.rpm

這裏我們建議採用源碼包進行安裝
cd /opt/install
wget http://www.lua.org/ftp/lua-5.1.4.tar.gz
tar zvfx lua-5.1.4.tar.gz
cd lua-5.1.4

vi src/Makefile
在 CFLAGS= -O2 -Wall $(MYCFLAGS) 這一行記錄里加上-fPIC,更改爲 CFLAGS= -O2 -Wall -fPIC $(MYCFLAGS) 來避免編譯過程中出現錯誤。

make linux
make install

cp etc/lua.pc /usr/lib/pkgconfig/
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/lib/pkgconfig

3.4 安裝配置MySQL-Proxy
MySQL-Proxy可通過以下網址獲得:
http://mysql.cdpa.nsysu.edu.tw/Downloads/MySQL-Proxy/

推薦採用已經編譯好的二進制版本,因爲採用源碼包進行編譯時,最新版的MySQL-Proxy對automake,glib以及libevent的版本都有很高的要求,而這些軟件包都是系統的基礎套件,不建議強行進行更新。
並且這些已經編譯好的二進制版本在解壓後都在統一的目錄內,因此建議選擇以下版本:
32位RHEL5平臺:
http://mysql.cdpa.nsysu.edu.tw/Downloads/MySQL-Proxy/mysql-proxy-0.8.1-linux-rhel5-x86-32bit.tar.gz
64位RHEL5平臺:
http://mysql.cdpa.nsysu.edu.tw/Downloads/MySQL-Proxy/mysql-proxy-0.8.1-linux-rhel5-x86-64bit.tar.gz

測試平臺爲RHEL5 32位,因此選擇32位的軟件包
wget http://mysql.cdpa.nsysu.edu.tw/Downloads/MySQL-Proxy/mysql-proxy-0.8.1-linux-rhel5-x86-32bit.tar.gz

tar xzvf mysql-proxy-0.8.1-linux-rhel5-x86-32bit.tar.gz
mv mysql-proxy-0.8.1-linux-rhel5-x86-32bit /opt/mysql-proxy

創建mysql-proxy服務管理腳本
mkdir /opt/mysql-proxy/init.d/

vim mysql-proxy

01 #!/bin/sh
02 #
03 # mysql-proxy This script starts and stops the mysql-proxy daemon
04 #
05 # chkconfig: - 78 30
06 # processname: mysql-proxy
07 # description: mysql-proxy is a proxy daemon to mysql
08  
09 # Source function library.
10 . /etc/rc.d/init.d/functions
11  
12 #PROXY_PATH=/usr/local/bin
13 PROXY_PATH=/opt/mysql-proxy/bin
14  
15 prog="mysql-proxy"
16  
17 # Source networking configuration.
18 . /etc/sysconfig/network
19  
20 # Check that networking is up.
21 [ ${NETWORKING} = "no" ] && exit 0
22  
23 # Set default mysql-proxy configuration.
24 #PROXY_OPTIONS="--daemon"
25 PROXY_OPTIONS="--admin-username=root --admin-password=password --proxy-read-only-backend-addresses=192.168.10.131:3306 --proxy-backend-addresses=192.168.10.130:3306  --admin-lua-script=/opt/mysql-proxy/lib/mysql-proxy/lua/admin.lua --proxy-lua-script=/opt/mysql-proxy/scripts/rw-splitting.lua"
26 PROXY_PID=/opt/mysql-proxy/run/mysql-proxy.pid
27  
28 # Source mysql-proxy configuration.
29 if [ -f /etc/sysconfig/mysql-proxy ]; then
30         . /etc/sysconfig/mysql-proxy
31 fi
32  
33 PATH=$PATH:/usr/bin:/usr/local/bin:$PROXY_PATH
34  
35 # By default it's all good
36 RETVAL=0
37  
38 # See how we were called.
39 case "$1" in
40   start)
41         # Start daemon.
42         echo -n $"Starting $prog: "
43         $NICELEVEL $PROXY_PATH/mysql-proxy $PROXY_OPTIONS --daemon --pid-file=$PROXY_PID --user=mysql --log-level=warning --log-file=/opt/mysql-proxy/log/mysql-proxy.log
44         RETVAL=$?
45         echo
46         if [ $RETVAL = 0 ]; then
47                 touch /var/lock/subsys/mysql-proxy
48         fi
49        ;;
50   stop)
51         # Stop daemons.
52         echo -n $"Stopping $prog: "
53         killproc $prog
54         RETVAL=$?
55         echo
56         if [ $RETVAL = 0 ]; then
57                 rm -f /var/lock/subsys/mysql-proxy
58                 rm -f $PROXY_PID
59         fi
60        ;;
61   restart)
62         $0 stop
63         sleep 3
64         $0 start
65        ;;
66   condrestart)
67        [ -e /var/lock/subsys/mysql-proxy ] && $0 restart
68       ;;
69   status)
70         status mysql-proxy
71         RETVAL=$?
72        ;;
73   *)
74         echo "Usage: $0 {start|stop|restart|status|condrestart}"
75         RETVAL=1
76        ;;
77 esac
78  
79 exit $RETVAL

腳本參數詳解:
==============================================
PROXY_PATH=/opt/mysql-proxy/bin //定義mysql-proxy服務二進制文件路徑

PROXY_OPTIONS="--admin-username=root \ //定義內部管理服務器賬號
--admin-password=password \ //定義內部管理服務器密碼
--proxy-read-only-backend-addresses=192.168.10.131:3306 \ //定義後端只讀從服務器地址
--proxy-backend-addresses=192.168.10.130:3306 \ //定義後端主服務器地址
--admin-lua-script=/opt/mysql-proxy/lib/mysql-proxy/lua/admin.lua \ //定義lua管理腳本路徑
--proxy-lua-script=/opt/mysql-proxy/scripts/rw-splitting.lua" \ //定義lua讀寫分離腳本路徑

PROXY_PID=/opt/mysql-proxy/run/mysql-proxy.pid //定義mysql-proxy PID文件路徑

$NICELEVEL $PROXY_PATH/mysql-proxy $PROXY_OPTIONS \
--daemon \ //定義以守護進程模式啓動
--keepalive \ //使進程在異常關閉後能夠自動恢復
--pid-file=$PROXY_PID \ //定義mysql-proxy PID文件路徑
--user=mysql \ //以mysql用戶身份啓動服務
--log-level=warning \ //定義log日誌級別,由高到低分別有(error|warning|info|message|debug)
--log-file=/opt/mysql-proxy/log/mysql-proxy.log //定義log日誌文件路徑
==============================================

cp mysql-proxy /opt/mysql-proxy/init.d/
chmod +x /opt/mysql-proxy/init.d/mysql-proxy

mkdir /opt/mysql-proxy/run
mkdir /opt/mysql-proxy/log

mkdir /opt/mysql-proxy/scripts

配置並使用rw-splitting.lua讀寫分離腳本
最新的腳本我們可以從最新的mysql-proxy源碼包中獲取
cd /opt/install

wget http://mysql.cdpa.nsysu.edu.tw/Downloads/MySQL-Proxy/mysql-proxy-0.8.1.tar.gz

tar xzvf mysql-proxy-0.8.1.tar.gz
cd mysql-proxy-0.8.1
cp lib/rw-splitting.lua /opt/mysql-proxy/scripts

修改讀寫分離腳本rw-splitting.lua
修改默認連接,進行快速測試,不修改的話要達到連接數爲4時才啓用讀寫分離
vim /opt/mysql-proxy/scripts/rw-splitting.lua
=============================
-- connection pool
if not proxy.global.config.rwsplit then
proxy.global.config.rwsplit = {
min_idle_connections = 1, //默認爲4
max_idle_connections = 1, //默認爲8
is_debug = false
}
end
=============================

修改完成後,啓動mysql-proxy
/opt/mysql-proxy/init.d/mysql-proxy start

3.5 測試讀寫分離效果
創建用於讀寫分離的數據庫連接用戶
登陸主數據庫服務器192.168.10.130,通過命令行登錄管理MySQL服務器
/opt/mysql/bin/mysql -uroot -p'new-password'
mysql> GRANT ALL ON *.* TO 'proxy1'@'192.168.10.132' IDENTIFIED BY 'password';
由於我們配置了主從複製功能,因此從數據庫服務器192.168.10.131上已經同步了此操作。

爲了清晰的看到讀寫分離的效果,需要暫時關閉MySQL主從複製功能
登陸從數據庫服務器192.168.10.131,通過命令行登錄管理MySQL服務器
/opt/mysql/bin/mysql -uroot -p'new-password'

關閉Slave同步進程
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)

連接MySQL-Proxy
/opt/mysql/bin/mysql -uproxy1 -p'password' -P4040 -h192.168.10.132

登陸成功後,在first_db數據的first_tb表中插入兩條記錄
mysql> use first_db;
Database changed
mysql> insert into first_tb values (007,’first’);
Query Ok, 1 row affected (0.00 sec)
mysql> insert into first_tb values (110,’second’);
Query Ok, 1 row affected (0.00 sec)

查詢記錄
mysql> select * from first_tb;
=============================
+------+------+
| id | name |
+------+------+
| 1 | myself |
+------+------+
1 rows in set (0.00 sec)
=============================
通過讀操作並沒有看到新記錄

mysql> quit
退出MySQL-Proxy

下面,分別登陸到主從數據庫服務器,對比記錄信息
首先,檢查主數據庫服務器
mysql> select * from first_tb;
=============================
+------+------+
| id | name |
+------+------+
| 1 | myself |
+------+------+
| 007 | first |
+------+------+
| 110 | second |
+------+------+
3 rows in set (0.00 sec)
=============================
兩條新記錄都已經存在

然後,檢查從數據庫服務器
mysql> select * from first_tb;
=============================
+------+------+
| id | name |
+------+------+
| 1 | myself |
+------+------+
1 rows in set (0.00 sec)
=============================
沒有新記錄存在

由此驗證,我們已經實現了MySQL讀寫分離,目前所有的寫操作都全部在Master主服務器上,用來避免數據的不同步;
另外,所有的讀操作都分攤給了其它各個Slave從服務器上,用來分擔數據庫壓力。

經驗分享:
1.當MySQL主從複製在 show slave status\G 時出現Slave_IO_Running或Slave_SQL_Running 的值不爲YES時,需要首先通過 stop slave 來停止從服務器,然後再執行一次本文 2.1與2.2 章節中的步驟即可恢復,但如果想儘可能的同步更多的數據,可以在Slave上將master_log_pos節點的值在之前同步失效的值的基礎上增大一些,然後反覆測試,直到同步OK。因爲MySQL主從複製的原理其實就是從服務器讀取主服務器的binlog,然後根據binlog的記錄來更新數據庫。

2.MySQL-Proxy的rw-splitting.lua腳本在網上有很多版本,但是最準確無誤的版本仍然是源碼包中所附帶的lib/rw-splitting.lua腳本,如果有lua腳本編程基礎的話,可以在這個腳本的基礎上再進行優化;

3.MySQL-Proxy實際上非常不穩定,在高併發或有錯誤連接的情況下,進程很容易自動關閉,因此打開--keepalive參數讓進程自動恢復是個比較好的辦法,但還是不能從根本上解決問題,因此通常最穩妥的做法是在每個從服務器上安裝一個MySQL-Proxy供自身使用,雖然比較低效但卻能保證穩定性;

4.一主多從的架構並不是最好的架構,通常比較優的做法是通過程序代碼和中間件等方面,來規劃,比如設置對錶數據的自增id值差異增長等方式來實現兩個或多個主服務器,但一定要注意保證好這些主服務器數據的完整性,否則效果會比多個一主多從的架構還要差;

5.MySQL-Cluster 的穩定性也不是太好;

6.Amoeba for MySQL 是一款優秀的中間件軟件,同樣可以實現讀寫分離,負載均衡等功能,並且穩定性要大大超過MySQL-Proxy,建議大家用來替代MySQL-Proxy,甚至MySQL-Cluster。

 

詳解Mysql Proxy Lua讀寫分離設置

 

原址如下:

http://mobile.51cto.com/iphone-287937.htm

Mysql Proxy Lua讀寫分離設置是本文要介紹的內容,主要是來了解Mysql ProxyMysql 分離設置,爲了未來MySQL讀寫分離的需要, 先行對MySQL官方的Mysql Proxy產品進行了初步測試. 以下是測試過程,二進制版Mysql Proxy可以去下載。

1、設置說明

  1. Master服務器: 192.168.41.196  
  2. Slave服務器: 192.168.41.197  
  3. Proxy服務器: 192.168.41.203 

2、安裝Mysql Proxy

在Proxy服務器上安裝即可. 如果源碼方式安裝, 需提前安裝pkg-config,libevent,glibc,lua等依賴包, 非常麻煩, 建議直接使用二進制版.

  1. # cd /u01/software/mysql  
  2. # tar -zxvf Mysql Proxy-0.8.1-linux-rhel5-x86-32bit.tar.gz -C /usr/local  
  3. # cd /usr/local  
  4. # ln -s Mysql Proxy-0.8.1-linux-rhel5-x86-32bit Mysql Proxy  
  5. # vi + ~/.bash_profile  
  6. export PATH=$PATH:/usr/local/Mysql Proxy/bin/  
  7. # . ~/.bash_profile 

3、Mysql Proxy選項說明

  1. # Mysql Proxy help-all 

管理功能選項:

  1. admin-address=host:port 指定一個mysqo-proxy的管理端口, 缺省是4041;  
  2. admin-username=<string> username to allow to log in  
  3. admin-password=<string> password to allow to log in  
  4. admin-lua-script=<filename> script to execute by the admin plugin 

代理功能選項:

  1. -P, proxy-address=<host:port> 是Mysql Proxy 服務器端的監聽端口, 缺省是4040;  
  2. -r, proxy-read-only-backend-addresses=<host:port> 只讀Slave的地址和端口, 缺省爲不設置;  
  3. -b, proxy-backend-addresses=<host:port> 遠程Master地址和端口, 可設置多個做failover和load balance, 缺省是127.0.0.1:3306;  
  4. proxy-skip-profiling 關閉查詢分析功能, 缺省是打開的;  
  5. proxy-fix-bug-25371 修正 mysql的libmysql版本大於5.1.12的一個#25371號bug;  
  6. -s, proxy-lua-script=<file> 指定一個Lua腳本來控制Mysql Proxy的運行和設置, 這個腳本在每次新建連接和腳本發生修改的的時候將重新調用; 

其他選項:

  1. defaults-file=<file>配置文件, 可以把Mysql Proxy的參數信息置入一個配置文件裏;  
  2. daemon Mysql Proxy以守護進程方式運行  
  3. pid-file=file 設置Mysql Proxy的存儲PID文件的路徑  
  4. keepalive try to restart the proxy if it crashed, 保持連接啓動進程會有2個, 一號進程用來監視二號進程, 如果二號進程死掉自動重啓proxy. 

4、數據庫準備工作

(1)安裝半同步補丁(建議)

讀寫分離不能迴避的問題之一就是延遲, 可以考慮Google提供的SemiSyncReplication補丁.

(2)給用戶授權

在Master/Slave建立一個測試用戶, 因爲以後客戶端發送的SQL都是通過Mysql Proxy服務器來轉發, 所以要確保可以從Mysql Proxy服務器上登錄MySQL主從庫.

  1. mysql> grant all privileges on *.* to 'u_test'@'192.168.41.203' identified by 'xxx' with grant option; 

(3)在Master建立測試表

  1. mysql> create table db_test.t_test (col varchar(10));  
  2. mysql> insert into db_test.t_test values ('testA');  
  3. mysql> select * from db_test.t_test;  
  4. +-+  
  5. | col   |  
  6. +-+  
  7. | testA |  
  8. +-+ 

5、Mysql Proxy啓動

(1)修改讀寫分離lua腳本

默認最小4個最大8個以上的客戶端連接纔會實現讀寫分離, 現改爲最小1個最大2個:

  1. # vi +40 /usr/local/Mysql Proxy/share/doc/Mysql Proxy/rw-splitting.lua  
  2.  connection pool  
  3. if not proxy.global.config.rwsplit then  
  4.         proxy.global.config.rwsplit = {  
  5.                 min_idle_connections = 1,  
  6.                 max_idle_connections = 2,  
  7.                 is_debug = true   
  8.         }         
  9. end 

這是因爲Mysql Proxy會檢測客戶端連接, 當連接沒有超過min_idle_connections預設值時, 不會進行讀寫分離, 即查詢操作會發生到Master上.

(2)啓動Mysql Proxy

建議使用配置文件的形式啓動, 注意配置文件必須是660權限, 否則無法啓動. 如果有多個Slave的話, proxy-read-only-backend-addresses參數可以配置多個以逗號分隔的IP:Port從庫列表.

  1. # killall Mysql Proxy   
  2. # vi /etc/Mysql Proxy.cnf  
  3. [Mysql Proxy]  
  4. admin-username=wangnc 
  5. admin-password=iamwangnc 
  6. admin-lua-script=/usr/local/Mysql Proxy/lib/Mysql Proxy/lua/admin.lua  
  7. proxy-backend-addresses=192.168.41.196:3351  
  8. proxy-read-only-backend-addresses=192.168.41.197:3351  
  9. proxy-lua-script=/usr/local/Mysql Proxy/share/doc/Mysql Proxy/rw-splitting.lua  
  10. log-file=/var/tmp/Mysql Proxy.log  
  11. log-level=debug 
  12. daemon=true 
  13. keepalive=true 
  14. # chmod 660 /etc/Mysql Proxy.cnf  
  15. # Mysql Proxy defaults-file=/etc/Mysql Proxy.cnf  
  16. # ps -ef | grep Mysql Proxy | grep -v grep  
  17. root      1869     1  0 18:16 ?        00:00:00 /usr/local/Mysql Proxy/libexec/Mysql Proxy defaults-file=/etc/Mysql Proxy.cnf  
  18. root      1870  1869  0 18:16 ?        00:00:00 /usr/local/Mysql Proxy/libexec/Mysql Proxy defaults-file=/etc/Mysql Proxy.cnf  
  19. # tail -50f /var/tmp/Mysql Proxy.log 

6、客戶端連接測試

(1)先停止Slave的複製進程

  1. mysql> stop slave; 

(2)連接Proxy端口, 插入數據

  1. # mysql -uu_test -pxxx -h192.168.41.203 -P4040 -Ddb_test  
  2. mysql> insert into db_test.t_test values ('testB');  
  3. mysql> select * from db_test.t_test;  
  4. +-+  
  5. | col   |  
  6. +-+  
  7. | testA |  
  8. | testB |  
  9. +-+ 

(3)多開幾個客戶端, 連接Proxy端口, 查詢數據

  1. # mysql -uu_test -pxxx -h192.168.41.203 -P4040 -Ddb_test  
  2. mysql> select * from db_test.t_test;  
  3. +-+  
  4. | col   |  
  5. +-+  
  6. | testA |  
  7. +-+ 

如果查詢不到上步新插入的數據, 說明連接到了Slave, 讀寫分離成功. 在同一線程再插入數據並驗證:

  1. mysql> insert into db_test.t_test values ('testC');  
  2. mysql> select * from db_test.t_test;  
  3. +-+  
  4. | col   |  
  5. +-+  
  6. | testA |  
  7. +-+ 

發現insert操作成功, 但是select不出剛插入的數據, 說明同一線程也讀寫分離成功. 從日誌中可以驗證:

  1. # tail -50f /var/tmp/Mysql Proxy.log  
  2. ...  
  3. [read_query] 192.168.41.203:45481  
  4.   current backend   = 0 
  5.   client default db = db_test 
  6.   client username   = u_test 
  7.   query             = select * from db_test.t_test  
  8.   sending to backend : 192.168.41.197:3351  
  9.     is_slave         : true  
  10.     server default db: db_test  
  11.     server username  : u_test  
  12.     in_trans        : false  
  13.     in_calc_found   : false  
  14.     COM_QUERY       : true  
  15. [read_query] 192.168.41.203:45481  
  16.   current backend   = 0 
  17.   client default db = db_test 
  18.   client username   = u_test 
  19.   query             = insert into db_test.t_test values ('testC')  
  20.   sending to backend : 192.168.41.196:3351  
  21.     is_slave         : false  
  22.     server default db: db_test  
  23.     server username  : u_test  
  24.     in_trans        : false  
  25.     in_calc_found   : false  
  26.     COM_QUERY       : true 

(4)測試完畢後, 啓動Slave的複製進程

  1. mysql> start slave; 

7、正式環境說明

1、Mysql Proxy當前還只是個測試版, MySQL官方還不建議用到生產環境中;

2、Mysql Proxy的rw-splitting.lua腳本在網上有很多版本, 但是最準確無誤的版本仍然是源碼包中所附帶的rw-splitting.lua腳本, 如果有lua腳本編程基礎的話, 可以在這個腳本的基礎上再進行優化;

3、Mysql Proxy實際上非常不穩定, 在高併發或有錯誤連接的情況下, 進程很容易自動關閉, 因此打開keepalive參數讓進程自動恢復是個比較好的辦法, 但還是不能從根本上解決問題, 因此通常最穩妥的做法是在每個從服務器上安裝一個Mysql Proxy供自身使用, 雖然比較低效但卻能保證穩定性;

4、Amoeba for MySQL是一款優秀的中間件軟件, 同樣可以實現讀寫分離, 負載均衡等功能, 並且穩定性要大大超過Mysql Proxy, 建議大家用來替代Mysql Proxy, 甚至MySQL-Cluster.

 

mysql的讀寫分離amoeba

原址如下:

http://freeze.blog.51cto.com/1846439/860111

 

此文凝聚筆者不少心血請尊重筆者勞動,轉載請註明出處http://freeze.blog.51cto.com/ 

  一、關於讀寫分離

  1. 讀寫分離(Read/Write Splitting),基本的原理是讓主數據庫處理事務性增、改、刪操作(INSERT、UPDATE、DELETE),而從數據庫處理SELECT查詢操作。數據庫複製被用來把事務性操作導致的變更同步到集羣中的從數據庫。 

 

二、同類產品比較 

  1. 雖然大多數都是從程序裏直接實現讀寫分離的,但對於分佈式的部署和水平和垂直分割,一些代理的類似中間件的軟件還是挺實用的,Amoeba for Mysql 與MySQL Proxy比較 在MySQL proxy 6.0版本 上面如果想要讀寫分離並且 讀集羣、寫集羣 機器比較多情況下,用mysql proxy 需要相當大的工作量,目前mysql proxy沒有現成的 lua腳本。mysql proxy根本沒有配置文件, lua腳本就是它的全部,當然lua是相當方便的。那麼同樣這種東西需要編寫大量的腳本才能完成一 個複雜的配置。而Amoeba for Mysql只需要進行相關的配置就可以滿足需求。 
 
三、關於Amoeba
 
  1. Amoeba(變形蟲)項目,該開源框架於2008年 開始發佈一款 Amoeba for Mysql軟件。這個軟件致力於MySQL的分佈式數據庫前端代理層,它主要在應用層訪問MySQL的 時候充當SQL路由功能,專注於分佈式數據庫代理層(Database Proxy)開發。座落與 Client、DB Server(s)之間,對客戶端透明。具有負載均衡、高可用性、SQL 過濾、讀寫分離、可路由相關的到目標數據庫、可併發請求多臺數據庫合併結果。 通過Amoeba你能夠完成多數據源的高可用、負載均衡、數據切片的功能,目前Amoeba已在很多 企業的生產線上面使用。 

 

四、Amoeba的安裝

4.1下載 

  1. wget http://nchc.dl.sourceforge.net/project/amoeba/Amoeba%20for%20mysql/2.x/amoeba-mysql-binary-2.1.0-RC5.tar.gz 

4.2安裝amoeba 

  1. mkdir /usr/local/amoeba 
  2. #mv amoeba-mysql-binary-2.1.0-RC5.tar.gz /usr/local/amoeba 
  3. #tar  xvf amoeba-mysql-binary-2.1.0-RC5.tar.gz  

4.3安裝JDK 

  1. 因爲Amoeba是java開發的,需要JDK支持。 Amoeba框架是基於Java SE1.5開發的,建議使用Java SE 1.5版本。 
  2.  
  3. % java -version 
  4. java version "1.6.0_18" 
  5. Java(TM) SE Runtime Environment (build 1.6.0_18-b07) 
  6. Java HotSpot(TM) Client VM (build 16.0-b13, mixed mode, sharing) 
  7. 目前Amoeba經驗證在JavaTM SE 1.5和Java SE 1.6能正常運行,(可能包括其他未經驗證的版本)。 如果你的機器上沒有安裝JavaTM環境,可以訪問http://www.oracle.com/technetwork/java/javase/downloads/index.html進行下載。可以根據你的操作系統等詳情安裝JavaTM環境。 
  8.  
  9. 去oracle官網下載jdk安裝包後,安裝jdk 
  10.  
  11. # chmod 755 jdk-6u25-linux-i586.bin 
  12. # ./jdk-6u25-linux-i586.bin 
  13. # mv jdk1.6.0_25/ /usr/local/jdk 
  14. 聲明路徑,修改/etc/profile,在末尾加上以下代碼 
  15.  
  16. export AMOEBA_HOME=/usr/local/amoeba 
  17. export JAVA_HOME=/usr/local/jdk 
  18. export PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$AMOEBA_HOME/bin 


 五、Amoeba配置

  1. cd /usr/local/amoeba/conf 主要配置以下2個配置文件:  
  2. dbServers.xml  #定義連接數據庫信息 
  3. amoeba.xml     #定義讀寫分離節點管理信息 

5.1 配置dbServers.xml

  1. <?xml version="1.0" encoding="gbk"?> 
  2.  
  3. <!DOCTYPE amoeba:dbServers SYSTEM "dbserver.dtd"> 
  4. <amoeba:dbServers xmlns:amoeba="http://amoeba.meidusa.com/"> 
  5.  
  6.                 <!--  
  7.                         Each dbServer needs to be configured into a Pool, 
  8.                          such as 'multiPool' dbServer    
  9.                 --> 
  10.  
  11.         <dbServer name="abstractServer" abstractive="true"> 
  12.                 <factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory"> 
  13.                         <property name="manager">${defaultManager}</property> 
  14.                         <property name="sendBufferSize">64</property> 
  15.                         <property name="receiveBufferSize">128</property> 
  16.  
  17.                         <!-- mysql port --> 
  18.                         <property name="port">3306</property>         __ ** ##後端數據庫端口**__ 
  19.  
  20.                         <!-- mysql schema --> 
  21.                         <property name="schema">test</property>        __ ** ##後端數據庫默認庫**__ 
  22.                         <!--  mysql password 
  23.                         <property name="password">password</property> 
  24.                         --> 
  25.                 </factoryConfig> 
  26.  
  27.                 <poolConfig class="com.meidusa.amoeba.net.poolable.PoolableObjectPool"> 
  28.                         <property name="maxActive">500</property> 
  29.                         <property name="maxIdle">500</property> 
  30.                         <property name="minIdle">10</property> 
  31.                         <property name="minEvictableIdleTimeMillis">600000</property> 
  32.                         <property name="timeBetweenEvictionRunsMillis">600000</property> 
  33.                         <property name="testOnBorrow">true</property> 
  34.                         <property name="testWhileIdle">true</property> 
  35.                 </poolConfig> 
  36.         </dbServer> 
  37.   
  38.         <dbServer name="master"  parent="abstractServer">                          __ ** ##定義主的寫的節點**__ 
  39.                 <factoryConfig> 
  40.                         <property name="ipAddress">192.168.1.1</property>      __ ** ##主masterIP**__ 
  41.                         <property name="user">test1</property>                 __ ** ##與主mysql通信,連接數據庫的帳號,以下是密碼**__ 
  42.                         <property name="password">test1</property> 
  43.                 </factoryConfig> 
  44.         </dbServer> 
  45.  
  46.         <dbServer name="slave"  parent="abstractServer"> 
  47.                 <factoryConfig> 
  48.                         <property name="ipAddress">192.168.1.2</property> 
  49.                         <property name="user">test2</property>                 __ ** ##與從mysql通信,連接數據庫的帳號,以下是密碼**__ 
  50.                         <property name="password">test2</property> 
  51.                 </factoryConfig> 
  52.         </dbServer> 
  53.  
  54.         <dbServer name="server1" virtual="true"> 
  55.                 <poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">    __ ** ##定義寫的池,把master節點加入**__ 
  56.                         <property name="loadbalance">1</property> 
  57.                         <property name="poolNames">master</property> 
  58.                 </poolConfig> 
  59.         </dbServer> 
  60.  
  61.         <dbServer name="server2" virtual="true"> 
  62.                 <poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">    __ ** ##定義讀的池,把slave節點加入**__ 
  63.                         <property name="loadbalance">1</property> 
  64.                         <property name="poolNames">slave</property> 
  65.                 </poolConfig> 
  66.         </dbServer> 
  67. </amoeba:dbServers> 

5.2 配置amoeba.xml

  1. <?xml version="1.0" encoding="gbk"?> 
  2. <amoeba:configuration xmlns:amoeba="http://amoeba.meidusa.com/"> 
  3.  
  4.         <proxy> 
  5.  
  6.                 <!-- service class must implements com.meidusa.amoeba.service.Service --> 
  7.                         <!-- port --> 
  8.                          <property name="port">6666</property>                   __ ** ##定義amoeba讀寫分離proxy對外代理的端口**__ 
  9.                         <!-- bind ipAddress --> 
  10.                         <!--  
  11.                         <property name="ipAddress">127.0.0.1</property> 
  12.                          --> 
  13.  
  14.                         <property name="manager">${clientConnectioneManager}</property> 
  15.  
  16.                         <property name="connectionFactory"> 
  17.                                         <property name="sendBufferSize">128</property> 
  18.                                         <property name="receiveBufferSize">64</property> 
  19.                                 </bean> 
  20.                         </property> 
  21.  
  22.                         <property name="authenticator"> 
  23.                                          <property name="user">dbproxy</property>     __ ** ##定義proxy的管理帳號密碼,客戶端和程序只需要連接proxy的帳號密碼即可,相當於中間接封裝**__ 
  24.                                         <property name="password">123456</property> 
  25.  
  26.                                         <property name="filter"> 
  27.                                                 </bean> 
  28.                                         </property> 
  29.                                 </bean> 
  30.                         </property> 
  31.  
  32.                 </service> 
  33.  
  34.                 <!-- server class must implements com.meidusa.amoeba.service.Service --> 
  35.                         <!-- port --> 
  36.                         <!--  default value: random number 
  37.                         <property name="port">9066</property> 
  38.                         --> 
  39.                         <!-- bind ipAddress --> 
  40.                         <property name="ipAddress">127.0.0.1</property> 
  41.                         <property name="daemon">true</property> 
  42.                         <property name="manager">${clientConnectioneManager}</property> 
  43.                         <property name="connectionFactory"> 
  44.                 <runtime class="com.meidusa.amoeba.mysql.context.MysqlRuntimeContext"> 
  45.                         <!-- proxy server net IO Read thread size --> 
  46.                         <property name="readThreadPoolSize">20</property> 
  47.  
  48.                         <!-- proxy server client process thread size --> 
  49.  
  50.                         <!-- per connection cache prepared statement size  --> 
  51.                         <property name="statementCacheSize">500</property> 
  52.  
  53.                         <!-- query timeout( default: 60 second , TimeUnit:second) --> 
  54.                         <property name="queryTimeout">60</property> 
  55.                 </runtime> 
  56.  
  57.         </proxy> 
  58.  
  59.         <!--  
  60.                 Each ConnectionManager will start as thread 
  61.                 manager responsible for the Connection IO read , Death Detection 
  62.         --> 
  63.         <connectionManagerList> 
  64.                         <!--  
  65.                           default value is avaliable Processors  
  66.                         <property name="processors">5</property> 
  67.                          --> 
  68.                 </connectionManager> 
  69.  
  70.                         <!--  
  71.                           default value is avaliable Processors  
  72.                         <property name="processors">5</property> 
  73.                          --> 
  74.                 </connectionManager> 
  75.         </connectionManagerList> 
  76.  
  77.                 <!-- default using file loader --> 
  78.         <dbServerLoader class="com.meidusa.amoeba.context.DBServerConfigFileLoader"> 
  79.                 <property name="configFile">${amoeba.home}/conf/dbServers.xml</property> 
  80.         </dbServerLoader> 
  81.  
  82.         <queryRouter class="com.meidusa.amoeba.mysql.parser.MysqlQueryRouter"> 
  83.                 <property name="ruleLoader"> 
  84.                         <bean class="com.meidusa.amoeba.route.TableRuleFileLoader"> 
  85.                                 <property name="ruleFile">${amoeba.home}/conf/rule.xml</property> 
  86.                                 <property name="functionFile">${amoeba.home}/conf/ruleFunctionMap.xml</property> 
  87.                         </bean> 
  88.                 </property> 
  89.                 <property name="sqlFunctionFile">${amoeba.home}/conf/functionMap.xml</property> 
  90.                 <property name="LRUMapSize">1500</property> 
  91.                 <property name="defaultPool">server1</property>                   __ ** ##定義默認的池,一些除了SELECT\UPDATE\INSERT\DELETE的語句都會在defaultPool執行。**__ 
  92.                 <property name="writePool">server1</property>                      __ ** ##定義寫的池**__ 
  93.                 <property name="readPool">server2</property>                      __ ** ##定義讀的池**__ 
  94.                 <property name="needParse">true</property> 
  95.         </queryRouter> 
  96. </amoeba:configuration> 

六、啓動Amoeba

  1. /usr/local/amoeba/bin/amoeba start & 
  2. 開機自動啓動可加入到 /etc/rc.local內 
  3. echo "/usr/local/amoeba/bin/amoeba start &" >> /etc/rc.local 

七、日誌排錯

  1. 日誌文件在/usr/local/amoeba/log下   

 

   PS:amoeba雖然是JAVA寫的,看似效率不高,但功能異常強大,支持讀寫分離,表和庫級別的讀寫分離,數據庫水平分割,垂直分割,還有集羣。是淘寶的得力作品。喜歡的童鞋可以嘗試下。mysql-proxy 只是輕量級的讀寫分離程序,雖然C寫的,但是驅動是需要lua的腳本跑,而且在高併發下經常掛掉。程序還忽略了一些字符設定,如果數據庫不是同一編碼還會出現亂碼,amoeba就不存在。就簡單介紹到這裏吧。

 

 使用Amoeba for mysql實現mysql讀寫分離

原址如下:

http://www.centos.bz/2012/05/amoeba-for-mysql/

 

Amoeba for MySQL致力於MySQL的分佈式數據庫前端代理層,它主要在應用層訪問MySQL的時候充當query 路由功能,專注 分佈式數據庫 proxy 開發。座落與Client、DB Server(s)之間。對客戶端透明。具有負載均衡、高可用性、Query過濾、讀寫分離、可路由相關的query到目標數據庫、可併發請求多臺數據庫合併結果。 在Amoeba上面你能夠完成多數據源的高可用、負載均衡、數據切片的功能。目前在很多企業的生產線上面使用。
www.centos.bz這裏使用Amoeba for mysql來實現mysql的讀寫分離,起到緩解主數據庫服務器的壓力,下面是實現這一方案的架構圖:

mysql主從複製配置

因爲讀寫分離,所以一臺負責mysql的寫操作,另一臺負責mysql的讀操作,所以我們這裏使用mysql的主從複製再合適不過了。關於這一配置,請移步:
http://www.centos.bz/2011/07/linux-mysql-replication-sync-configure/

java環境配置

Amoeba框架是基於Java SE1.5開發的,建議使用Java SE 1.5版本。目前Amoeba經驗證在JavaTM SE 1.5和Java SE 1.6能正常運行,(可能包括其他未經驗證的版本)。
Java SE 1.6下載地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk-6u32-downloads-1594644.html
我這裏下載jdk-6u32-linux-i586-rpm.bin。
下載完成後執行sh jdk-6u32-linux-i586-rpm.bin開始安裝,將會安裝到/usr/java/jdk1.6.0_32目錄。

Amoeba的安裝

Amoeba下載地址:http://sourceforge.net/projects/amoeba/
下面是安裝步驟:

  1. cd /tmp
  2. mkdir /usr/local/amoeba
  3. wget http://softlayer.dl.sourceforge.net/project/amoeba/Amoeba%20for%20mysql/2.x/amoeba-mysql-binary-2.1.0-RC5.tar.gz
  4. tar xzf amoeba-mysql-binary-2.1.0-RC5.tar.gz -C /usr/local/amoeba

配置用戶環境變量

  1. vi ~/.bash_profile

設置爲:

  1. PATH=$PATH:$HOME/bin:/usr/local/amoeba/bin
  2. JAVA_HOME=/usr/java/jdk1.6.0_32
  3.  
  4. export JAVA_HOME
  5. export PATH

立即生效:

  1. source  ~/.bash_profile

Amoeba for mysql配置

配置Amoeba for mysql的讀寫分離主要涉及兩個文件:
1、/usr/local/amoeba/conf/dbServers.xml
此文件定義由Amoeba代理的數據庫如何連接,比如最基礎的:主機IP、端口、Amoeba使用的用戶名和密碼等等。
2、/usr/local/amoeba/conf/amoeba.xml
此文件定義了Amoeba代理的相關配置。

dbServers.xml文件配置

abstractServer配置:

  1. <dbServer name="abstractServer" abstractive="true">
  2.                 <factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory">
  3.                         <property name="manager">${defaultManager}</property>
  4.                         <property name="sendBufferSize">64</property>
  5.                         <property name="receiveBufferSize">128</property>
  6.  
  7.                         <!-- mysql port -->
  8.                         <property name="port">3306</property>
  9.  
  10.                         <!-- mysql schema -->
  11.                         <property name="schema">dbname</property>
  12.  
  13.                         <!-- mysql user -->
  14.                         <property name="user">root</property>
  15.  
  16.                         <!--  mysql password -->
  17.                         <property name="password">root</property>
  18.  
  19.                 </factoryConfig>
  20.  
  21.                 <poolConfig class="com.meidusa.amoeba.net.poolable.PoolableObjectPool">
  22.                         <property name="maxActive">500</property>
  23.                         <property name="maxIdle">500</property>
  24.                         <property name="minIdle">10</property>
  25.                         <property name="minEvictableIdleTimeMillis">600000</property>
  26.                         <property name="timeBetweenEvictionRunsMillis">600000</property>
  27.                         <property name="testOnBorrow">true</property>
  28.                         <property name="testWhileIdle">true</property>
  29.                 </poolConfig>
  30.         </dbServer>

此部分定義真實mysql服務器的端口,數據庫名稱,mysql用戶及密碼。
主從數據庫定義:

  1. <dbServer name="Master"  parent="abstractServer">
  2.                 <factoryConfig>
  3.                         <!-- mysql ip -->
  4.                         <property name="ipAddress">192.168.0.1</property>
  5.                 </factoryConfig>
  6.         </dbServer>
  7. <dbServer name="Slave1"  parent="abstractServer">
  8.                 <factoryConfig>
  9.                         <!-- mysql ip -->
  10.                         <property name="ipAddress">192.168.0.2</property>
  11.                 </factoryConfig>
  12.         </dbServer>
  13. <dbServer name="Slave2"  parent="abstractServer">
  14.                 <factoryConfig>
  15.                         <!-- mysql ip -->
  16.                         <property name="ipAddress">192.168.0.3</property>
  17.                 </factoryConfig>
  18.         </dbServer>
  19.         <dbServer name="virtualSlave" virtual="true">
  20.                 <poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
  21.                         <!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->
  22.                         <property name="loadbalance">1</property>
  23.  
  24.                         <!-- Separated by commas,such as: server1,server2,server1 -->
  25.                         <property name="poolNames">Slave1,Slave2</property>
  26.                 </poolConfig>
  27.         </dbServer>

此部分定義主服務器,從服務器,及從服務器連接池。這裏只定義數據庫地址,它們的用戶及密碼就是上面的abstractServer裏的設置。注意用來連接真實mysql服務器的用戶必須擁有遠程連接權限。

amoeba.xml配置

amoeba連接驗證配置:

  1. <property name="authenticator">
  2.                                 <bean class="com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator">
  3.  
  4.                                         <property name="user">root</property>
  5.                                         
  6.                                         <property name="password">root</property>
  7.  
  8.                                         <property name="filter">
  9.                                                 <bean class="com.meidusa.amoeba.server.IPAccessController">
  10.                                                         <property name="ipFile">${amoeba.home}/conf/access_list.conf</property>
  11.                                                 </bean>
  12.                                         </property>
  13.                                 </bean>
  14.                         </property>

這裏定義連接amoeba時用來驗證的用戶及密碼。
讀寫分離配置:

  1. <property name="defaultPool">Master</property>
  2.                 <property name="writePool">Master</property>
  3.                 <property name="readPool">virtualSlave</property>

defaultPool:配置了默認的數據庫節點,一些除了SELECTUPDATEINSERTDELETE的語句都會在defaultPool執行。
writePool :配置了數據庫寫庫,通常配爲Master,如這裏就配置爲之前定義的Master數據庫。
readPool :配置了數據庫讀庫,通常配爲Slave或者Slave組成的數據庫池,如這裏就配置之前的virtualSlave數據庫池。

amoeba啓動

啓動命令:

  1. amoeba start

此命令以前臺的方式啓動,會輸出啓動時的信息,檢查沒有錯誤信息後,中斷,並後臺運行:

  1. amoeba start &

FAQ

1、無法正常連接?
首先根據執行amoeba start輸出的信息排除配置文件沒有問題,之後確認mysql用戶是否有遠程連接的權限,然後檢查網站的數據庫配置文件是否設置正確。
2、如何配置網站數據庫連接文件?
默認的端口應該爲8066,用戶及密碼在amoeba.xml裏設置。
參考:http://docs.hexnova.com/amoeba/single-dbserver.html
http://docs.hexnova.com/amoeba/rw-splitting.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章