Mysql+mmm+proxy
測試
2008
年9月8日
16:38
動機:proxy實現讀寫分離
MMM
使Replication方案具備HA
下面先看從網上摘抄的一段說明。
引言
Master-Slave
的數據庫機構解決了不少問題,特別是read/write比較高的web2.0應用:
1
、寫操做所有在Master結點執行,並由Slave數據庫結點定時(默認60s)讀取Master的bin-log
2
、將衆多的用戶讀請求分散到更多的數據庫節點,從而減輕了單點的壓力
這是對Replication的最基本陳述,這種模式的在系統Scale-out方案中頗有引力(若有必要,數據能夠先進行Sharding,再使用replication)。
它的缺點是:
1
、Slave實時性的保障,對於實時性很高的場合可能須要作一些處理
本文主要討論的是如何解決第2個缺點。
Master-Master Replication
1
、使用兩個MySQL數據庫db01,db02,互爲Master和Slave,即:
一邊db01做爲db02的master,一旦有數據寫向db01時,db02定時從db01更新
另外一邊db02也做爲db01的master,一旦有數據寫向db02時,db01也定時從db02得到更新
(
這不會致使循環,MySQL Slave默認不會記錄Master同步過來的變化)
2
、但從AppServer的角度來講,同時只有一個結點db01扮演Master,另一個結點db02扮演Slave,不能同時兩個結點扮演Master。即AppSever老是把write操做分配某個數據庫(db01),除非db01 failed,被切換。
3
、若是扮演Slave的數據庫結點db02 Failed了:
a)
此時appServer要可以把全部的read,write分配給db01,read操做再也不指向db02
b)
一旦db02恢復過來後,繼續充當Slave角色,並告訴AppServer能夠將read分配給它了
4
、若是扮演Master的數據庫結點db01 Failed了
a)
此時appServer要可以把全部的寫操做從db01切換分配給db02,也就是切換Master由db02充當
b)db01
恢復過來後,充當Slave的角色,Master由db02繼續扮演
難點:
3
、4要如何自動進行?
Master-Master with n Slaves Replication
這比上一個還要複雜,即:
當一個Master Fail時,全部的Slave再也不從原來失敗的那個Master(db01)獲取更新日誌,而應該「自動」切換到最新充當Master角色的數據庫db02。
MMM
,a greate project!
MMM
的基本信息請參考它的網站(見後"參考資料")
MMM
有3個重要的器件:
1
、mmmd_mon - monitoring script which does all monitoring work and makes all decisions about roles moving and so on.
2
、mmmd_agent - remote servers management agent script, whichprovides monitoring node with simple set of remote services to makeservers management easier, more flexible abd highly portable.
3
、mmm_control - simple script dedicated to management of the mmmd_mon processes by commands.
每個MySQL服務器器結點須要運行mmmd_agent,同時在另外的一個機器上(能夠是獨立的一臺機器,也能夠是和AppServer共享同一個服務器)運行mmmd_mon。造成1 * mmmd_mon + n * mmmd_agent的部署架構。
MMM
利用了虛擬IP的技術:1個網卡能夠同時使用多個IP。
(
因此使用MMM時,須要2*n+1個IP,n爲mysql數據庫結點個數,包括master,slave)
當有數據庫結點fail時,mmmd_mon檢測不到mmmd_agent的心跳或者對應的MySQL服務器的狀態,mmmd_mon將進行決定,並下指令給某個正常的數據庫結點的mmmd_agent,使得該mmmd_agent「篡位」使用(注)剛纔fail的那個結點的虛擬IP,使得虛擬IP實際從指向fail的那個機器自動轉爲此時的這個正常機器。
注:據Qieqie猜想是將得到的虛擬IP設置給網卡,也只能這樣了,改天測試驗證一下。
repeat:
MMM
對MySQL Master-Slave Replication絕對是一個頗有益的補充!
總體架構的原理:
Webclient
數據請求至proxy—proxy進行讀寫分發-轉至mmm機制-在檢測存活的機器進行讀與寫操做。在此以前這些機器與爲master/slave.
本文測試環境以下:
主機名
|
IP
|
Port
|
App
|
目錄
|
備註
|
Node1
|
192.168.1.2
|
3306
|
mysql
|
/var/lib/mysql
|
數據庫服務器1
|
Node2
|
192.168.1.3
|
3306
|
mysql
|
/var/lib/mysql
|
數據庫服務器2
|
Mon
|
192.168.1.4
|
3306
|
Mysql
|
/var/lib/mysql
|
數據庫管理服務器
|
Proxy
|
192.168.1.5
|
4040
|
Proxy
|
|
數據庫代理(NLB)
|
node1 node2
數據庫服務器replication雙向 master-master 虛擬機有限,只能開4臺,由於node1與node2即作讀又作寫。
配置步驟:
Node1 node2 replication
雙向 master-master
Node1 node2
安裝mmm並配置mmm_regent.conf
Mon
安裝mmm並配置mmm_mon.conf
proxy
安裝mysql-proxy
1、配置node1 node2數據庫服務器replication雙向 master-master
1
、配置node1 同步
Mkdir /var/log/mysql
Chown mysql.mysql /var/log/mysql
my.cnf at db1 should have following options:
server-id =
|
1
|
log_bin =
|
mysql-bin
|
master_host
|
192.168.1.2
|
master_port
|
3306
|
master_user
|
replication
|
master_password
|
slave
|
mysql> grant replication slave on *.* to 'replication'@'%' identified by 'slave';
show slave status\G;
的結果:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
2
、配置node2同步
Mkdir /var/log/mysql
Chown mysql.mysql /var/log/mysql
my.cnf at db1 should have following options:
server-id =
|
2
|
log_bin =
|
mysql-bin
|
master_host
|
192.168.1.3
|
master_port
|
3306
|
master_user
|
replication
|
master_password
|
slave
|
mysql> grant replication slave on *.* to 'replication'@'%' identified by 'slave';
show slave status\G;
的結果:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
2、安裝部署MMM
目標主機:
Node1
|
192.168.1.2
|
Node2
|
192.168.1.3
|
Mon
|
192.168.1.4
|
1
、安裝mon主機軟件包
前提:
--
|
Algorithm-Diff-1.1902.tar.gz
|
--
|
Proc-Daemon-0.03.tar.gz
|
RPM
|
mysql-server-5.0.22-2.1
|
RPM
|
mysql-5.0.22-2.1
|
RPM
|
perl-DBD-MySQL-3.0007-1.fc6
|
--
|
mmm-1.0.tar.bz2
|
先安裝2個perl的包:
--
|
Algorithm-Diff-1.1902.tar.gz
|
--
|
Proc-Daemon-0.03.tar.gz
|
perl
包的安裝過程都是:
perl Makefile.PL
make
make test
make install
安裝mmm:
./install.pl
2
、安裝node1 node2 agent軟件包(使用agent功能)
mmm-1.0.tar.bz2
安裝mmm:
./install.pl
三臺主機安裝以上軟件後進行配置過程
三:node1 node2 的agent配置過程
$cd /usr/local/mmm/etc
$cp examples/mmm_agent.conf.examples ../mmm_agent.conf
node1
配置文件所須要修改的地方以下
cluster_interface eth0
--配置IP所用的網卡
# Define current server id this db1
this db1
mode master
# For masters peer db2
Peer db2
# Cluster hosts addresses and access params
host db1
ip 192.168.1.2
port 3306
user rep_agent
password RepAgent
host db2
ip 192.168.1.3
port 3306
user rep_agent
password RepAgent
Node2
配置文件所須要修改的地方以下
# Cluster interface
cluster_interface eth0
--配置IP所用的網卡
# Define current server id this db1
this db2
mode master
# For masters peer db2
Peer db1
# Cluster hosts addresses and access params
host db1
ip 192.168.1.2
port 3306
user rep_agent
password RepAgent
host db2
ip 192.168.1.3
port 3306
user rep_agent
password RepAgent
設置權限(node1/node2)
GRANT ALL PRIVILEGES on *.* to 'rep_monitor'@'%' identified by 'RepMonitor';
4、修改mon主機的配置文件 所須要修改的地方以下:
文件位置:/usr/local/mmm/etc/mmm_mon.conf
# Cluster interface
cluster_interface eth0
----配置IP所用的網卡
# Cluster hosts addresses and access params
host db1
|
數據庫名
|
ip 192.168.1.2
|
node1 ip
|
port 3306
|
node1 port
|
user rep_monitor
|
node1
用戶(供mon監控使用,該用戶須要在db上添加)
|
password RepMonitor
|
對應密碼
|
mode master
|
模式
|
peer db2
|
slave
指定
|
host db2
|
意義同上
|
ip 192.168.1.3
|
|
port 3306
|
|
user rep_monitor
|
|
password RepMonitor
|
|
mode master
|
|
peer db1
|
|
#
後續若有添加需求,請按照上面格式填寫
active_master_role writer
role reader
mode balanced
|
模式爲均攤
|
servers db1,db2
|
規則覆蓋db1 db2(若有更多slave 繼續填寫,別忘了ip)
|
ip 192.168.1.7
,192.168.1.8
|
對應ip 虛擬的IP
|
# Mysql Writer role
role writer
|
寫規則
|
mode exclusive
|
模式爲獨佔
|
servers db1,db2
|
規則負載db1 db2
|
ip 192.168.1.9
|
兩臺數據庫公用一個ip爲寫,採用HA模式,默認db1使用,db1下線db2接管此ip
|
五:測試MMM
在db1/db2上啓動agent功能
/usr/local/mmm/scripts/init.d/mmm_agent start
在mon上啓動mon功能
/usr/local/mmm/scripts/init.d/mmm_mon start
並對mon進行檢測
# mmm_control set_online db1
# mmm_control set_online db2
# mmm_control show
查看分配狀況
正常狀況下:
# mmm_control show
Servers status:
db1(192.168.1.2): master/ONLINE. Roles: reader(192.168.1.7;), writer(192.168.1.9;)
db2(192.168.1.3): master/ONLINE. Roles: reader(192.168.1.8;)
stop 192.168.1.3
# mmm_control show
Servers status:
db1(192.168.1.2): master/ONLINE. Roles: reader(192.168.1.7;), writer(192.168.1.9;)
db2(192.168.1.3): master/REPLICATION_FAIL. Roles: None
檢測出1.3出了故障.
等一會..進行了切換!由於讀寫是輪循的.這時寫切到了3
# mmm_control show
Servers status:
db1(192.168.1.2): master/ONLINE. Roles: reader(192.168.1.7;)
db2(192.168.1.3): master/ONLINE. Roles: reader(192.168.1.8;), writer(192.168.1.9;)
Telnet
任何一個虛擬IP 3306都是通的
5、mysql_proxy與mysql MMM集成的必要性
1
、實現mysql數據庫層的負載均衡
2
、數據庫節點實現HA動態切換
3
、讀寫分離,下降主數據庫負載
6、安裝mysql proxy
1
、下載proxy代碼包
從svn上獲取最新代碼
2
、安裝
編譯好的版本安裝方法以下:
# tar zxf mysql-proxy-0.6.0-linux-rhas4-x86.tar.gz
# cd mysql-proxy-0.6.0-linux-rhas4-x86
#
能夠看到有2個目錄
# ls
sbin share
# mv sbin/mysql-proxy /usr/local/sbin/
# ls share
mysql-proxy tutorial-constants.lua tutorial-packets.lua tutorial-rewrite.lua tutorial-warnings.lua tutorial-basic.lua tutorial-inject.lua tutorial-query-time.lua tutorial-states.lua
#
將lua腳本放到/usr/local/share下,以備他用
# mv share/mysql-proxy /usr/local/share/
#
刪除符號鏈接等垃圾代碼
# strip /usr/local/sbin/mysql-proxy
proxy
與MMM集成
鏈接接管
|
Proxy 192.168.1.5
|
4040
|
讀操做
|
Db1 192.168.1.7:3306
Db2 192.168.1.8:3306
|
|
寫操做
|
Db1/db2 192.168.1.9
默認db1先用,db1當機,db2接管
|
|
mysql-proxy --proxy-read-only-backend-addresses=192.168.1.7:3306 --proxy-read-only-backend-addresses=192.168.1.8:3306 --proxy-backend-addresses=192.168.1.9:3306 --proxy-lua-script=/usr/local/share/mysql-proxy/rw-splitting.lua &
如今解釋一下:
--proxy-backend-addresses=192.168.1.9:3306
指定mysql寫主機的端口
--proxy-read-only-backend-addresses=192.168.1.7:3306
指定只讀的mysql主機端口
--proxy-read-only-backend-addresses=192.168.1.8:3306
指定另外一個只讀的mysql主機端口
--proxy-lua-script=/usr/local/share/mysql-proxy/rw-splitting.lua
指定lua腳本,在這裏,使用的是rw-splitting腳本,用於讀寫分離
完整的參數能夠運行如下命令查看:
mysql-proxy --help-all
運行如下命令啓動/中止/重啓mysql proxy:
# /etc/init.d/mysql-proxy start
# /etc/init.d/mysql-proxy stop
# /etc/init.d/mysql-proxy restart
Ps -ef | grep mysql-proxy
7、測試結果
將web server 如apache 中部署的網站,數據庫鏈接地址改成----〉proxy的ip端口爲4040
1
、往數據庫db1裏寫入數據,查看2個數據庫同步狀況
2
、使用mon服務器mmm_control show 查看狀態
簡單的測試能夠鏈接proxy 4040 查看讀寫狀況
方法我就再也不詳細寫了。
編譯過程有可能會遇到一些錯誤。下面是錯誤的總結:
1
)如在make 階段出錯
(1)
類、、、、make: *** [dbdimp.o] 錯誤 1
多半是庫文件的問題,(--cflags=-I/usr/local/mysql/include/mysq 細查,少個「y"
(2)類 LD_RUN_PATH="/usr/lib/mysql:/lib:/usr/lib" gcc
-o blib/arch/auto/DBD/mysql/mysql.so -shared
-L/usr/local/lib dbdimp.o mysql.o -L/usr/lib/mysql
-lmysqlclient -lm -L/usr/lib/gcc-lib/i386-redhat-linux/2.96
-lgcc -lz
/usr/bin/ld: cannot find -lz
collect2: ld returned 1 exit status
make: *** [blib/arch/auto/DBD/mysql/mysql.so] Error 1
與壓縮包有關。可用 ldconfig -p | grep libz
ldconfig -p | grep libgz
查找,若有並指定路徑!不然安裝 libz-devel/ibgz-devel/zlib-devel/ gzlib-devel
2)
在make test 階段出錯:
(1)
類: install_driver(mysql) failed: Can't load
'/usr/lib/perl5/site_perl/i586-linux/auto/DBD/mysql/mysql.so'
for module DBD::mysql: File not found at
/usr/lib/perl5/i586-linux/5.00404/DynaLoader.pm line 166
與 /usr/lib/mysql/libmysqlclient.a有關 (cp libmysqlclient.a /us/lib)
(2)
類: t/00base............install_driver(mysql) failed: Can't load
'../blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql:
../blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: _umoddi3
at /usr/local/perl-5.005/lib/5.005/i586-linux-thread/DynaLoader.pm
line 168.
與libgcc.a 有關 (cp /usr/lib/gcc/i386-redhat-linux/4.1.1/libgcc.a /usr/local/lib/
(3)
類:Can't load libmysqlclient.so.15 、、、、
(cp libmysqlclient.so.15 /us/lib)
----------------------------------------
$perl Makefile.PL --libs="-L/usr/local/mysql/lib/mysql -lmysqlclient -L/usr/lib -lz " --cflags=-I/usr/local/mysql/include/mysql --mysql_config=/usr/local/mysql/bin/mysql_config --testhost=127.0.0.1--testsocket=/usr/local/mysql/tmp/mysql.sock --testdb=test --testuser=abc --testpassword=abc
------------------
$
; make; make test ;sudo make install;
-------------------------------