MySQL 高可用架构之MMM - yayun
简介
MMM(Master-MasterreplicationmanagerforMySQL)是一套支持双主故障切换和双主日常管理的脚本程序。MMM使用Perl语言开发,主要用来监控和管理MySQLMaster-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
monitoring192.168.0.30db2-
master1192.168.0.60db11
master2192.168.0.50db22
slave1192.168.0.40db33
业务中的服务ip信息如下所示:
ip地址角色描述
192.168.0.108write应用程序连接该ip对主库进行写请求
192.168.0.88read应用程序连接该ip进行读请求
192.168.0.98read应用程序连接该ip进行读请求
具体的配置步骤如下:
(1)主机配置
配置/etc/hosts,在所有主机中,添加所有的主机信息:
[[email protected]~]#cat/etc/hosts
192.168.0.60db1
192.168.0.50db2
192.168.0.40db3
(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-yinstallmysql-mmm*来安装MMM:
rpm-ivhhttp://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
yum-yinstallmysql-mmm*
[[email protected]~]#catinstall.sh
#!/bin/bash
wgethttp://xrl.us/cpanm--no-check-certificate
mvcpanm/usr/bin
chmod755/usr/bin/cpanm
cat>/root/list<<EOF
installAlgorithm::Diff
installClass::Singleton
installDBI
installDBD::mysql
installFile::Basename
installFile::stat
installFile::Temp
installLog::Dispatch
installLog::Log4perl
installMail::Send
installNet::ARP
installNet::Ping
installProc::Daemon
installThread::Queue
installTime::HiRes
EOF
forpackagein`cat/root/list`
do
cpanm$package
done
(4)
下载mysql-mmm软件,在所有服务器上安装:
[[email protected]~]#wgethttp://mysql-mmm.org/_media/:mmm2:mysql-mmm-2.2.1.tar.gz
[[email protected]~]#mv:mmm2:mysql-mmm-2.2.1.tar.gzmysql-mmm-2.2.1.tar.gz
[[email protected]~]#tarxfmysql-mmm-2.2.1.tar.gz
[[email protected]~]#cdmysql-mmm-2.2.1
[[email protected]]#makeinstall
mysql-mmm安装后的主要拓扑结构如下所示(注意:yum安装的和源码安装的路径有所区别):
目录介绍
/usr/lib/perl5/vendor_perl/5.8.8/MMMMMM使用的主要perl模块
/usr/lib/mysql-mmmMMM使用的主要脚本
/usr/sbinMMM使用的主要命令的路径
/etc/init.d/MMM的agent和monitor启动服务的目录
/etc/mysql-mmmMMM配置文件的路径,默认所以的配置文件位于该目录下
/var/log/mysql-mmm默认的MMM保存日志的位置
到这里已经完成了MMM的基本需求,接下来需要配置具体的配置文件,其中mmm_common.conf,mmm_agent.conf为agent端的配置文件,mmm_mon.conf为monitor端的配置文件。
(5)配置agent端的配置文件,需要在db1,db2,db3上分别配置。
在db1主机上配置agent配置文件:
[[email protected]~]#cd/etc/mysql-mmm/
[[email protected]]#catmmm_common.conf
active_master_rolewriter
<hostdefault>
cluster_interfaceeth1
pid_path/var/run/mmm_agentd.pid
bin_path/usr/lib/mysql-mmm/
replication_userrepl
replication_password123456
agent_usermmm_agent
agent_passwordmmm_agent
</host>
<hostdb1>
ip192.168.0.60
modemaster
peerdb2
</host>
<hostdb2>
ip192.168.0.50
modemaster
peerdb1
</host>
<hostdb3>
ip192.168.0.40
modeslave
</host>
<rolewriter>
hostsdb1,db2
ips192.168.0.108
modeexclusive
</role>
<rolereader>
hostsdb2,db3
ips192.168.0.88,192.168.0.98
modebalanced
</role>
其中replication_user用于检查复制的用户,agent_user为agent的用户,mode标明是否为主或者备选主,或者从库。modeexclusive主为独占模式,同一时刻只能有一个主,<rolewrite>中hosts表示目前的主库和备选主的真实主机ip或者主机名,ips为对外提供的虚拟机ip地址,<rolereadr>中hosts代表从库真实的ip和主机名,ips代表从库的虚拟ip地址。
由于db2和db3两台主机也要配置agent配置文件,我们直接把mmm_common.conf从db1拷贝到db2和db3两台主机的/etc/mysql-mmm下。
注意:monitor主机要需要:
scp/etc/mysql-mmm/mmm_common.confdb2:/etc/mysql-mmm/
scp/etc/mysql-mmm/mmm_common.confdb3:/etc/mysql-mmm/
分别在db1,db2,db3三台主机的/etc/mysql-mmm配置mmm_agent.conf文件,分别用不同的字符标识,注意这三台机器的thisdb1这块要想,比如本环境中,db1要配置thisdb1,db2要配置为thisdb2,而db3要配置为thisdb3。
在db1(192.168.0.60)上:
[[email protected]~]#cat/etc/mysql-mmm/mmm_agent.conf
includemmm_common.conf
thisdb1
在db2(192.168.0.50)上:
[[email protected]~]#cat/etc/mysql-mmm/mmm_agent.conf
includemmm_common.conf
thisdb2
在db3(192.168.0.40)上:
[[email protected]~]#cat/etc/mysql-mmm/mmm_agent.conf
includemmm_common.conf
thisdb3
在db2(192.168.0.30)配置monitor的配置文件:
[[email protected]~]#cat/etc/mysql-mmm/mmm_mon.conf
includemmm_common.conf
<monitor>
ip127.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_ips192.168.0.40,192.168.0.50,192.168.0.60
auto_set_online60
</monitor>
<hostdefault>
monitor_usermmm_monitor
monitor_passwordmmm_monitor
</host>
debug0
这里只在原有配置文件中的ping_ips添加了整个架构被监控主机的ip地址,而在<hostdefault>中配置了用于监控的用户。
(6)创建监控用户,这里需要创建3个监控用户,具体描述如下:
用户名描述权限
monitoruserMMM的monitor端监控所有的mysql数据库的状态用户REPLICATIONCLIENT
agentuser主要是MMM客户端用于改变的master的read_only状态用户SUPER,REPLICATIONCLIENT,PROCESS
repl用于复制的用户REPLICATIONSLAVE
在3台服务器(db1,db2,db3)进行授权,因为我之前的主主复制,以及主从已经是ok的,所以我在其中一台服务器执行就ok了。用于复制的账号之前已经有了,所以这里就授权两个账号。
mysql>GRANTSUPER,REPLICATIONCLIENT,PROCESSON*.*TO'mmm_agent'@'192.168.0.%'IDENTIFIEDBY'mmm_agent';
QueryOK,0rowsaffected(0.08sec)
mysql>GRANTREPLICATIONCLIENTON*.*TO'mmm_monitor'@'192.168.0.%'IDENTIFIEDBY'mmm_monitor';
QueryOK,0rowsaffected(0.00sec)
mysql>flushprivileges;
QueryOK,0rowsaffected(0.03sec)
mysql>
如果是从头到尾从新搭建,则加上另外一个复制账户(分别在3台服务器都需要执行这3条SQL):
GRANTREPLICATIONSLAVEON*.*TO'repl'@'192.168.0.%'IDENTIFIEDBY'123456';
(7)启动agent服务。
最后分别在db1,db2,db3上启动agent,并在db2(192.168.0.30)上启动monitor程序:
[[email protected]~]#/etc/init.d/mysql-mmm-agentstart
Daemonbin:'/usr/sbin/mmm_agentd'
Daemonpid:'/var/run/mmm_agentd.pid'
StartingMMMAgentdaemon...Ok
[[email protected]~]#/etc/init.d/mysql-mmm-agentstart
StartingMMMAgentDaemon:[OK]
因为我有些使用yum安装的,所以启动信息有些不一样。^_^
[[email protected]~]#/etc/init.d/mysql-mmm-agentstart
StartingMMMAgentDaemon:[OK]
启动monitor:
[[email protected]~]#/etc/init.d/mysql-mmm-monitorstart
StartingMMMMonitorDaemon:[OK]
其中agent的日志存放在/var/log/mysql-mmm/mmm_agentd.log,monitor日志放在/var/log/mysql-mmm/mmm_mond.log,启动过程中有什么问题,通常日志都会有详细的记录。
(8)在monitor主机上检查集群主机的状态:
[[email protected]~]#mmm_controlchecksall
db2ping[lastchange:2014/04/1800:29:01]OK
db2mysql[lastchange:2014/04/1800:29:01]OK
db2rep_threads[lastchange:2014/04/1800:29:01]OK
db2rep_backlog[lastchange:2014/04/1800:29:01]OK:Backlogisnull
db3ping[lastchange:2014/04/1800:29:01]OK
db3mysql[lastchange:2014/04/1800:29:01]OK
db3rep_threads[lastchange:2014/04/1800:29:01]OK
db3rep_backlog[lastchange:2014/04/1800:29:01]OK:Backlogisnull
db1ping[lastchange:2014/04/1800:29:01]OK
db1mysql[lastchange:2014/04/1800:29:01]OK
db1rep_threads[lastchange:2014/04/1800:29:01]OK
db1rep_backlog[lastchange:2014/04/1800:29:01]OK:Backlogisnull
(9)在monitor主机上检查集群环境在线状况:
[[email protected]~]#mmm_controlshow
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)
(10)online(上线)所有主机:
我这里主机已经在线了,如果没有在线,可以使用下面的命令将相关主机online
[[email protected]~]#mmm_controlset_onlinedb1
OK:ThishostisalreadyONLINE.Skippingcommand.
提示主机已经在线,已经跳过命令执行了。
到这里整个集群就配置完成了。从输出中可以看到虚拟ip192.168.0.108已经顺利添加到主机192.168.0.60上作为主对外提供写服务,虚拟ip192.168.0.88添加到主机192.168.0.50上对外提供读服务,而虚拟ip192.168.0.98添加到192.168.0.40上对外提供读服务。
MMM高可用测试
我们已经完成高可用环境的搭建了,下面我们就可以做MMM的HA测试咯。首先查看整个集群的状态,可以看到整个集群状态正常。
[[email protected]~]#mmm_controlshow
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)
模拟db2(192.168.0.50)宕机,手动停止mysql服务,观察monitor日志:
[[email protected]~]#tail-f/var/log/mysql-mmm/mmm_mond.log
2014/04/1800:55:53FATALStateofhost'db2'changedfromONLINEtoHARD_OFFLINE(ping:OK,mysql:notOK)
从日志发现db2的状态有ONLINE转换为HARD_OFFLINE
重新查看集群的最新状态:
[[email protected]~]#mmm_controlshow
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)
重启db2,可以看到db2由HARD_OFFLINE转到AWAITING_RECOVERY。这里db2再次接管读请求。
[[email protected]~]#mmm_controlshow
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)
模拟db1主库宕机:
查看集群状态:
[[email protected]~]#mmm_controlshow
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)
查看MMM日志:
[[email protected]~]#tail-f/var/log/mysql-mmm/mmm_mond.log
2014/04/1801:09:20FATALStateofhost'db1'changedfromONLINEtoHARD_OFFLINE(ping:OK,mysql:notOK)
从上面可以发现,db1由以前的ONLINE转化为HARD_OFFLINE,移除了写角色,因为db2是备选主,所以接管了写角色,db3指向新的主库db2,应该说db3实际上找到了db2的sql现在的位置,即db2showmaster返回的值,然后直接在db3上changemasterto到db2。
db1,db2,db3之间为一主两从的复制关系,一旦发生db2,db3延时于db1时,这个时刻db1mysql宕机,db3将会等待数据追上db1后,再重新指向新的主db2,进行changemastertodb2操作,在db1宕机的过程中,一旦db2落后于db1,这时发生切换,db2变成了可写状态,数据的一致性将会无法保证。
总结:
MMM不适用于对数据一致性要求很高的环境。但是高可用完全做到了。
参考资料:
http://mysql-mmm.org/mmm2:guide
http://www.cnblogs.com/gomysql/p/3671896.html