簡介
MMM(Master-Master replication manager for MySQL)是一套支持雙主故障切換和雙主日常管理的腳本程序。MMM使用Perl語言開發,主要用來監控和管理MySQL Master-Master(雙主)復制,雖然叫做雙主復制,但是業務上同一時刻只允許對一個主進行寫入,另一台備選主上提供部分讀服務,以加速在主主切換時刻備選主的預熱,可以說MMM這套腳本程序一方面實現了故障切換的功能,另一方面其內部附加的工具腳本也可以實現多個slave的read負載均衡。
MMM提供了自動和手動兩種方式移除一組服務器中復制延遲較高的服務器的虛擬ip,同時它還可以備份數據,實現兩節點之間的數據同步等。由於MMM無法完全的保證數據一致性,所以MMM適用於對數據的一致性要求不是很高,但是又想最大程度的保證業務可用性的場景。對於那些對數據的一致性要求很高的業務,非常不建議采用MMM這種高可用架構。
MMM項目來自 Google:http://code.google.com/p/mysql-master-master
官方網站為:http://mysql-mmm.org
下面我們通過一個實際案例來充分了解MMM的內部架構,如下圖所示。
具體的配置信息如下所示:
角色 ip地址 主機名字 server-id monitoring 192.168.0.30 db2 - master1 192.168.0.60 db1 1 master2 192.168.0.50 db2 2 slave1 192.168.0.40 db3 3
業務中的服務ip信息如下所示:
ip地址 角色 描述 192.168.0.108 write 應用程序連接該ip對主庫進行寫請求 192.168.0.88 read 應用程序連接該ip進行讀請求 192.168.0.98 read 應用程序連接該ip進行讀請求
具體的配置步驟如下:
(1)主機配置
配置/etc/hosts,在所有主機中,添加所有的主機信息:
[root@192.168.0.30 ~]# cat /etc/hosts 192.168.0.60 db1 192.168.0.50 db2 192.168.0.40 db3 [root@192.168.0.30 ~]#
(2)首先在3台主機上安裝mysql和搭建復制(192.168.0.60和192.168.0.50互為主從,192.168.0.40為192.168.0.60的從)具體的復制搭建這里就省略,要是這都不會,那么該文章對你就沒意思了。然后在每個mysql的配置文件中加入以下內容,注意server_id 不能重復。
db1(192.168.0.60)上:
server-id = 1 log_slave_updates = 1 auto-increment-increment = 2 auto-increment-offset = 1
db2(192.168.0.50)上:
server-id = 2 log_slave_updates = 1 auto-increment-increment = 2 auto-increment-offset = 2
db3(192.168.0.40)上:
server-id = 3 log_slave_updates = 1
上面的id不一定要按順序來,只要沒有重復即可。
(3)安裝MMM所需要的Perl模塊(所有服務器)執行該腳本,也可以安裝epel源,然后yum -y install mysql-mmm*來安裝MMM:
rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm yum -y install mysql-mmm*
[root@192.168.0.60 ~]# cat install.sh #!/bin/bash wget http://xrl.us/cpanm --no-check-certificate mv cpanm /usr/bin chmod 755 /usr/bin/cpanm cat > /root/list << EOF install Algorithm::Diff install Class::Singleton install DBI install DBD::mysql install File::Basename install File::stat install File::Temp install Log::Dispatch install Log::Log4perl install Mail::Send install Net::ARP install Net::Ping install Proc::Daemon install Thread::Queue install Time::HiRes EOF for package in `cat /root/list` do cpanm $package done [root@192.168.0.60 ~]#
(4)
下載mysql-mmm軟件,在所有服務器上安裝:
[root@192.168.0.60 ~]# wget http://mysql-mmm.org/_media/:mmm2:mysql-mmm-2.2.1.tar.gz
[root@192.168.0.60 ~]# mv :mmm2:mysql-mmm-2.2.1.tar.gz mysql-mmm-2.2.1.tar.gz [root@192.168.0.60 ~]# tar xf mysql-mmm-2.2.1.tar.gz [root@192.168.0.60 ~]# cd mysql-mmm-2.2.1 [root@192.168.0.60 mysql-mmm-2.2.1]# make install
mysql-mmm安裝后的主要拓撲結構如下所示(注意:yum安裝的和源碼安裝的路徑有所區別):
目錄 介紹 /usr/lib/perl5/vendor_perl/5.8.8/MMM MMM使用的主要perl模塊 /usr/lib/mysql-mmm MMM使用的主要腳本 /usr/sbin MMM使用的主要命令的路徑 /etc/init.d/ MMM的agent和monitor啟動服務的目錄 /etc/mysql-mmm MMM配置文件的路徑,默認所以的配置文件位於該目錄下 /var/log/mysql-mmm 默認的MMM保存日志的位置
到這里已經完成了MMM的基本需求,接下來需要配置具體的配置文件,其中mmm_common.conf,mmm_agent.conf為agent端的配置文件,mmm_mon.conf為monitor端的配置文件。
(5)配置agent端的配置文件,需要在db1,db2,db3上分別配置。
在db1主機上配置agent配置文件:
[root@192.168.0.60 ~]# cd /etc/mysql-mmm/ [root@192.168.0.60 mysql-mmm]# cat mmm_common.conf active_master_role writer <host default> cluster_interface eth1 pid_path /var/run/mmm_agentd.pid bin_path /usr/lib/mysql-mmm/ replication_user repl replication_password 123456 agent_user mmm_agent agent_password mmm_agent </host> <host db1> ip 192.168.0.60 mode master peer db2 </host> <host db2> ip 192.168.0.50 mode master peer db1 </host> <host db3> ip 192.168.0.40 mode slave </host> <role writer> hosts db1, db2 ips 192.168.0.108 mode exclusive </role> <role reader> hosts db2, db3 ips 192.168.0.88, 192.168.0.98 mode balanced </role> [root@192.168.0.60 mysql-mmm]#
其中replication_user用於檢查復制的用戶,agent_user為agent的用戶,mode標明是否為主或者備選主,或者從庫。mode exclusive主為獨占模式,同一時刻只能有一個主,<role write>中hosts表示目前的主庫和備選主的真實主機ip或者主機名,ips為對外提供的虛擬機ip地址,<role readr>中hosts代表從庫真實的ip和主機名,ips代表從庫的虛擬ip地址。
由於db2和db3兩台主機也要配置agent配置文件,我們直接把mmm_common.conf從db1拷貝到db2和db3兩台主機的/etc/mysql-mmm下。
注意:monitor主機要需要:
scp /etc/mysql-mmm/mmm_common.conf db2:/etc/mysql-mmm/
scp /etc/mysql-mmm/mmm_common.conf db3:/etc/mysql-mmm/
分別在db1,db2,db3三台主機的/etc/mysql-mmm配置mmm_agent.conf文件,分別用不同的字符標識,注意這三台機器的this db1這塊要想,比如本環境中,db1要配置this db1,db2要配置為this db2,而db3要配置為this db3。
在db1(192.168.0.60)上:
[root@192.168.0.60 ~]# cat /etc/mysql-mmm/mmm_agent.conf include mmm_common.conf this db1 [root@192.168.0.60 ~]#
在db2(192.168.0.50)上:
[root@192.168.0.50 ~]# cat /etc/mysql-mmm/mmm_agent.conf include mmm_common.conf this db2 [root@192.168.0.50 ~]#
在db3(192.168.0.40)上:
[root@192.168.0.40 ~]# cat /etc/mysql-mmm/mmm_agent.conf include mmm_common.conf this db3 [root@192.168.0.40 ~]#
在db2(192.168.0.30)配置monitor的配置文件:
[root@192.168.0.30 ~]# cat /etc/mysql-mmm/mmm_mon.conf include mmm_common.conf <monitor> ip 127.0.0.1 pid_path /var/run/mysql-mmm/mmm_mond.pid bin_path /usr/libexec/mysql-mmm status_path /var/lib/mysql-mmm/mmm_mond.status ping_ips 192.168.0.40,192.168.0.50,192.168.0.60 auto_set_online 60 </monitor> <host default> monitor_user mmm_monitor monitor_password mmm_monitor </host> debug 0 [root@192.168.0.30 ~]#
這里只在原有配置文件中的ping_ips添加了整個架構被監控主機的ip地址,而在<host default>中配置了用於監控的用戶。
(6)創建監控用戶,這里需要創建3個監控用戶,具體描述如下:
用戶名 描述 權限
monitor user MMM的monitor端監控所有的mysql數據庫的狀態用戶 REPLICATION CLIENT
agent user 主要是MMM客戶端用於改變的master的read_only狀態用戶 SUPER,REPLICATION CLIENT,PROCESS
repl 用於復制的用戶 REPLICATION SLAVE
在3台服務器(db1,db2,db3)進行授權,因為我之前的主主復制,以及主從已經是ok的,所以我在其中一台服務器執行就ok了。用於復制的賬號之前已經有了,所以這里就授權兩個賬號。
mysql> GRANT SUPER, REPLICATION CLIENT, PROCESS ON *.* TO 'mmm_agent'@'192.168.0.%' IDENTIFIED BY 'mmm_agent'; Query OK, 0 rows affected (0.08 sec) mysql> GRANT REPLICATION CLIENT ON *.* TO 'mmm_monitor'@'192.168.0.%' IDENTIFIED BY 'mmm_monitor'; Query OK, 0 rows affected (0.00 sec) mysql> flush privileges; Query OK, 0 rows affected (0.03 sec) mysql>
如果是從頭到尾從新搭建,則加上另外一個復制賬戶(分別在3台服務器都需要執行這3條SQL):
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.0.%' IDENTIFIED BY '123456';
(7)啟動agent服務。
最后分別在db1,db2,db3上啟動agent,並在db2(192.168.0.30)上啟動monitor程序:
[root@192.168.0.60 ~]# /etc/init.d/mysql-mmm-agent start Daemon bin: '/usr/sbin/mmm_agentd' Daemon pid: '/var/run/mmm_agentd.pid' Starting MMM Agent daemon... Ok [root@192.168.0.60 ~]#
[root@192.168.0.50 ~]# /etc/init.d/mysql-mmm-agent start Starting MMM Agent Daemon: [ OK ] [root@192.168.0.50 ~]#
因為我有些使用yum安裝的,所以啟動信息有些不一樣。^_^
[root@192.168.0.40 ~]# /etc/init.d/mysql-mmm-agent start Starting MMM Agent Daemon: [ OK ] [root@192.168.0.40 ~]#
啟動monitor:
[root@192.168.0.30 ~]# /etc/init.d/mysql-mmm-monitor start Starting MMM Monitor Daemon: [ OK ] [root@192.168.0.30 ~]#
其中agent的日志存放在/var/log/mysql-mmm/mmm_agentd.log,monitor日志放在/var/log/mysql-mmm/mmm_mond.log,啟動過程中有什么問題,通常日志都會有詳細的記錄。
(8)在monitor主機上檢查集群主機的狀態:
[root@192.168.0.30 ~]# mmm_control checks all db2 ping [last change: 2014/04/18 00:29:01] OK db2 mysql [last change: 2014/04/18 00:29:01] OK db2 rep_threads [last change: 2014/04/18 00:29:01] OK db2 rep_backlog [last change: 2014/04/18 00:29:01] OK: Backlog is null db3 ping [last change: 2014/04/18 00:29:01] OK db3 mysql [last change: 2014/04/18 00:29:01] OK db3 rep_threads [last change: 2014/04/18 00:29:01] OK db3 rep_backlog [last change: 2014/04/18 00:29:01] OK: Backlog is null db1 ping [last change: 2014/04/18 00:29:01] OK db1 mysql [last change: 2014/04/18 00:29:01] OK db1 rep_threads [last change: 2014/04/18 00:29:01] OK db1 rep_backlog [last change: 2014/04/18 00:29:01] OK: Backlog is null [root@192.168.0.30 ~]#
(9)在monitor主機上檢查集群環境在線狀況:
[root@192.168.0.30 ~]# mmm_control show db1(192.168.0.60) master/ONLINE. Roles: writer(192.168.0.108) db2(192.168.0.50) master/ONLINE. Roles: reader(192.168.0.88) db3(192.168.0.40) slave/ONLINE. Roles: reader(192.168.0.98) [root@192.168.0.30 ~]#
(10)online(上線)所有主機:
我這里主機已經在線了,如果沒有在線,可以使用下面的命令將相關主機online
[root@192.168.0.30 ~]# mmm_control set_online db1 OK: This host is already ONLINE. Skipping command. [root@192.168.0.30 ~]#
提示主機已經在線,已經跳過命令執行了。
到這里整個集群就配置完成了。從輸出中可以看到虛擬ip 192.168.0.108已經順利添加到主機192.168.0.60上作為主對外提供寫服務,虛擬ip 192.168.0.88添加到主機192.168.0.50上對外提供讀服務,而虛擬ip 192.168.0.98添加到192.168.0.40上對外提供讀服務。
MMM高可用測試
我們已經完成高可用環境的搭建了,下面我們就可以做MMM的HA測試咯。首先查看整個集群的狀態,可以看到整個集群狀態正常。
[root@192.168.0.30 ~]# mmm_control show db1(192.168.0.60) master/ONLINE. Roles: writer(192.168.0.108) db2(192.168.0.50) master/ONLINE. Roles: reader(192.168.0.88) db3(192.168.0.40) slave/ONLINE. Roles: reader(192.168.0.98) [root@192.168.0.30 ~]#
模擬db2(192.168.0.50 )宕機,手動停止mysql服務,觀察monitor日志:
[root@192.168.0.30 ~]# tail -f /var/log/mysql-mmm/mmm_mond.log 2014/04/18 00:55:53 FATAL State of host 'db2' changed from ONLINE to HARD_OFFLINE (ping: OK, mysql: not OK)
從日志發現db2的狀態有ONLINE轉換為HARD_OFFLINE
重新查看集群的最新狀態:
[root@192.168.0.30 ~]# mmm_control show db1(192.168.0.60) master/ONLINE. Roles: writer(192.168.0.108) db2(192.168.0.50) master/HARD_OFFLINE. Roles: db3(192.168.0.40) slave/ONLINE. Roles: reader(192.168.0.88), reader(192.168.0.98) [root@192.168.0.30 ~]#
重啟db2,可以看到db2由HARD_OFFLINE轉到AWAITING_RECOVERY。這里db2再次接管讀請求。
[root@192.168.0.30 ~]# mmm_control show db1(192.168.0.60) master/ONLINE. Roles: writer(192.168.0.108) db2(192.168.0.50) master/ONLINE. Roles: reader(192.168.0.88) db3(192.168.0.40) slave/ONLINE. Roles: reader(192.168.0.98) [root@192.168.0.30 ~]#
模擬db1主庫宕機:
查看集群狀態:
[root@192.168.0.30 ~]# mmm_control show db1(192.168.0.60) master/HARD_OFFLINE. Roles: db2(192.168.0.50) master/ONLINE. Roles: reader(192.168.0.88), writer(192.168.0.108) db3(192.168.0.40) slave/ONLINE. Roles: reader(192.168.0.98) [root@192.168.0.30 ~]#
查看MMM日志:
[root@192.168.0.30 ~]# tail -f /var/log/mysql-mmm/mmm_mond.log 2014/04/18 01:09:20 FATAL State of host 'db1' changed from ONLINE to HARD_OFFLINE (ping: OK, mysql: not OK)
從上面可以發現,db1由以前的ONLINE轉化為HARD_OFFLINE,移除了寫角色,因為db2是備選主,所以接管了寫角色,db3指向新的主庫db2,應該說db3實際上找到了db2的sql現在的位置,即db2 show master返回的值,然后直接在db3上change master to到db2。
db1,db2,db3之間為一主兩從的復制關系,一旦發生db2,db3延時於db1時,這個時刻db1 mysql宕機,db3將會等待數據追上db1后,再重新指向新的主db2,進行change master to db2操作,在db1宕機的過程中,一旦db2落后於db1,這時發生切換,db2變成了可寫狀態,數據的一致性將會無法保證。
總結:
MMM不適用於對數據一致性要求很高的環境。但是高可用完全做到了。
參考資料: