MySQL-MMM实现MySQL高可用
一、MMM简介
MMM(Master-Master replication manager for MySQL)是一套支持双主故障切换和双主日常管理的脚本程序。MMM使用Perl语言开发,主要用来监控和管理MySQL Master-Master(双主)复制,虽然叫做双主复制,但是业务上同一时刻只允许对一个主进行写入,另一台备选主上提供部分读服务,以加速在主主切换时刻备选主的预热,可以说MMM这套脚本程序一方面实现了故障切换的功能,另一方面其内部附加的工具脚本也可以实现多个slave的read负载均衡。
MMM提供了自动和手动两种方式移除一组服务器中复制延迟较高的服务器的虚拟ip,同时它还可以备份数据,实现两节点之间的数据同步等。由于MMM无法完全的保证数据一致性,所以MMM适用于对数据的一致性要求不是很高,但是又想最大程度的保证业务可用性的场景。对于那些对数据的一致性要求很高的业务,非常不建议采用MMM这种高可用架构。
优点:
1 稳定和成熟的开源产品,经过了时间的考验 核心技术是mysql自己的技术,只是使用脚本程序来控制,所以在原理上比较容易理解,而且管理能够更智能化。
2 安装简单,配置简单,使用简单
3 功能强大 (HA,failover,tools套件,cluster模式可以一个monitor管理多个mmm组)
缺点:
1 由于架构里只有一个写入点,所以扩展性是有限的,但是对一般中型企业够用了。
解决方案:对于大应用可以采取垂直拆分到多个mmm架构的方式,使用mmm cluster来管理。
2 对于读写分离和读负载均衡还是要程序来开发或者使用其他工具完成。
二、架构及配置环境
MySQL-MMM架构图:
mysql-mmm运行机制:
mysql-mmm安装需求
复制代码
Server n+1:
N台安装mysql的机器和1台安装mmm monitor的机器。
2*(n+1)Ips:
每个主机一个固定ip、一个虚拟IP(reader role),全局一个writer role IP
Monitor User:
一个可以在mmm monitor机器上使用的并且拥有REPLICATION,CLIENT权限的mysql用户
Agent User:
一个可以在mmm agent机器上使用的并且拥有super,replication,client,process权限的mysql用户
Replication user:
一个slaves主机上可以使用的并且有用replication slave权限的用户
Tools user:
一个mmm tools主机可以使用的,并且有用super,replication client,reload权限的mysql用户
复制代码
安装环境:
1.角***r>
2.虚拟ip规划:
3.hosts文件配置(全部机器):
192.168.1.11 master-db1
192.168.1.12 master-db2
192.168.1.13 slave-db1
192.168.1.14 slave-db2
192.168.1.15 mmm-monitor
4.其他:
1 关闭iptables
2 同步时间
3 配置yum和epel源
三、安装MySQL并配置
1.mysql安装
由于篇幅有限,安装步骤见小弟另一篇文章http://www.cnblogs.com/panwenbin-logs/p/8260931.html
2.编辑配置文件/etc/my.cnf:
master-db1
复制代码
[mysqld]
server-id = 1
datadir = /Data/apps/mysql-5.6.36/data
log-bin = /Data/apps/mysql-5.6.36/data/mysql-bin
binlog_format = ROW
relay_log = /Data/apps/mysql-5.6.36/data/relay-log
auto-increment-increment = 2
auto-increment-offset = 1
sync_binlog = 1
sync_master_info = 1
sync_relay_log = 1
sync_relay_log_info = 1
max_binlog_size = 100M
log_slave_updates = 1
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
复制代码
master-db2
复制代码
[mysqld]
server-id = 2
datadir = /Data/apps/mysql-5.6.36/data
log-bin = /Data/apps/mysql-5.6.36/data/mysql-bin
binlog_format = ROW
relay_log = /Data/apps/mysql-5.6.36/data/relay-log
auto-increment-increment = 2
auto-increment-offset = 2
sync_binlog = 1
sync_master_info = 1
sync_relay_log = 1
sync_relay_log_info = 1
max_binlog_size = 100M
log_slave_updates = 1
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
复制代码
slave-db1
复制代码
[mysqld]
server-id = 3
datadir = /Data/apps/mysql-5.6.36/data
log-bin = /Data/apps/mysql-5.6.36/data/mysql-bin
binlog_format = ROW
relay_log = /Data/apps/mysql-5.6.36/data/relay-log
sync_binlog = 1
sync_master_info = 1
sync_relay_log = 1
sync_relay_log_info = 1
max_binlog_size = 100M
log_slave_updates = 1
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
复制代码
slave-db2
复制代码
[mysqld]
server-id = 4
datadir = /Data/apps/mysql-5.6.36/data
log-bin = /Data/apps/mysql-5.6.36/data/mysql-bin
binlog_format = ROW
relay_log = /Data/apps/mysql-5.6.36/data/relay-log
sync_binlog = 1
sync_master_info = 1
sync_relay_log = 1
sync_relay_log_info = 1
max_binlog_size = 100M
log_slave_updates = 1
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
复制代码
3.重启以上四台mysql服务
service mysqld restart
4.在master-db1上创建mmm架构中需要的用户和权限
复制代码
[root@master-db1 ~]# mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.6.36-log MySQL Community Server (GPL)
.......
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> GRANT REPLICATION CLIENT ON . TO 'mmm_monitor'@'192.168.1.%' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.19 sec)
mysql> GRANT SUPER,REPLICATION CLIENT,PROCESS ON . TO 'mmm_agent'@'192.168.1.%' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.00 sec)
mysql> GRANT REPLICATION SLAVE ON . TO 'replication'@'192.168.1.%' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.01 sec)
复制代码
5.查看二进制日志位置
复制代码
mysql> FLUSH TABLES WITH READ LOCK;
Query OK, 0 rows affected (0.07 sec)
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 796 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.05 sec)
复制代码
6.不要关闭这个mysql进程连接,避免锁失效,我们另起一个ssh连接db1服务器,进行数据库备份:
[root@master-db1 ~]# mysqldump --all-databases > /tmp/database-backup.sql
7.回到刚才mysql进程,进行解锁:
mysql> UNLOCK TABLES;
Query OK, 0 rows affected (0.05 sec)
8.将database-backup.sql文件复制到其他db节点:
[root@master-db1 ~]# scp /tmp/database-backup.sql master-db2:/tmp
[root@master-db1 ~]# scp /tmp/database-backup.sql slave-db1:/tmp
[root@master-db1 ~]# scp /tmp/database-backup.sql slave-db2:/tmp
9.master-db,slave-db1,slave-db2三台主机导入sql文件,并刷新权限:
[root@master-db2 ~]# mysql < /tmp/database-backup.sql
[root@master-db2 ~]# mysql -e "FLUSH PRIVILEGES;"
四、设置MySQL主-从和主-主配置
1.在其他三台mysql上将master-db1设为主服务器
复制代码
[root@master-db2 ~]# mysql
mysql> CHANGE MASTER TO MASTER_HOST='192.168.1.11',MASTER_USER='replication',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=796;
Query OK, 0 rows affected, 2 warnings (0.11 sec)
mysql> start slave;
Query OK, 0 rows affected (0.11 sec)
mysql> show slave status\G
*** 1. row ***
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.11
Master_User: replication
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 796
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 283
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
复制代码
2.查看master-db2的master日志位置:
复制代码
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 636231 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
复制代码
3.在master-db1上操作,将master-db2设置为主:
复制代码
mysql> CHANGE MASTER TO MASTER_HOST='192.168.1.12',MASTER_USER='replication',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=636231;
Query OK, 0 rows affected, 2 warnings (0.03 sec)
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)
mysql> show slave status\G;
*** 1. row ***
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.12
Master_User: replication
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 636231
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 283
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
复制代码
五、安装MMM
1.创建Tools user
useradd -s /sbin/nologin mmmd #所有机器
2.查看mmm版本:
yum list all|grep ^mysql-mmm
mysql-mmm.noarch 2.2.1-2.el6 @epel
mysql-mmm-agent.noarch 2.2.1-2.el6 @epel
mysql-mmm-monitor.noarch 2.2.1-2.el6 epel
mysql-mmm-tools.noarch 2.2.1-2.el6 epel
3.在mmm-monitor上安装:
[root@mmm-monitor ~]# yum -y install mysql-mmm-monitor
4.在四台mysql服务器上安装:
yum -y install mysql-mmm-agent
5.编写配置文件,五台主机必须一致:
复制代码
[root@mmm-monitor ~]# vim /etc/mysql-mmm/mmm_common.conf
active_master_role writer #积极的master角色的标示,所有的db服务器要开启read_only参数,对于writer服务器监控代理会自动将read_only属性关闭。
<host master-db1=""> #master-db1的host名称
ip 192.168.1.11 #master-db1的ip
mode master #角色属性,master代表是主
peer master-db2 #与master-db1对等的服务器的host名,也就是master-db2的服务器host名
</host>
<host master-db2=""> #和master-db1的概念一样
ip 192.168.1.12
mode master
peer master-db1
</host>
<host slave-db1=""> #从库的host名,如果存在多个从库可以重复一样的配置
ip 192.168.1.13 #从的ip
mode slave #slave的角色属性代表当前host是从
</host>
<host slave-db2=""> #和slave-db1的概念一样
ip 192.168.1.14
mode slave
</host>
<role writer=""> #writer角色配置
hosts master-db1, master-db2 #能进行写操作的服务器的host名,如果不想切换写操作这里可以只配置master,这样也可以避免因为网络延时而进行write的切换,但是一旦master出现故障那么当前的MMM就没有writer了只有对外的read操作。
ips 192.168.1.250 #对外提供的写操作的虚拟IP
mode exclusive #exclusive代表只允许存在一个主,也就是只能提供一个写的IP
</role>
<role reader=""> #read角色配置
hosts master-db1, master-db2, slave-db1, slave-db2 #对外提供读操作的服务器的host名,当然这里也可以把master加进来
ips 192.168.1.251, 192.168.1.252, 192.168.1.253, 192.168.1.254 #对外提供读操作的虚拟ip,这三个ip和host不是一一对应的,并且ips也hosts的数目也可以不相同,如果这样配置的话其中一个hosts会分配两个ip
mode balanced #balanced代表负载均衡
</role>
复制代码
6.复制到其他服务器上
scp /etc/mysql-mmm/mmm_common.conf 192.168.1.11:/etc/mysql-mmm/mmm_common.conf
scp /etc/mysql-mmm/mmm_common.conf 192.168.1.12:/etc/mysql-mmm/mmm_common.conf
scp /etc/mysql-mmm/mmm_common.conf 192.168.1.13:/etc/mysql-mmm/mmm_common.conf
scp /etc/mysql-mmm/mmm_common.conf 192.168.1.14:/etc/mysql-mmm/mmm_common.conf
7.在所有的MySQL上修改mmm_agent.conf,只需要修改master-db1这里,是哪台就改成哪台,这里只给出master-db1的:
复制代码
vim /etc/mysql-mmm/mmm_agent.conf
include mmm_common.conf
The 'this' variable refers to this server. Proper operation requires
that 'this' server (db1 by default), as well as all other servers, have the
proper IP addresses set in mmm_common.conf.
this master-db1
复制代码
8.配置mmm-monitor上的mmm_mon.conf:
复制代码
[root@mmm-monitor ~]# vim /etc/mysql-mmm/mmm_mon.conf
include mmm_common.conf
# The kill_host_bin does not exist by default, though the monitor will # throw a warning about it missing. See the section 5.10 "Kill Host # Functionality" in the PDF documentation. # # kill_host_bin /usr/libexec/mysql-mmm/monitor/kill_host #</monitor> <host default=""> monitor_user mmm_monitor monitor_password 123456 </host>
debug 0
复制代码
9.启动服务:
在mmm-monitor启动:
[root@mmm-monitor ~]# chkconfig mysql-mmm-monitor on
[root@mmm-monitor ~]# service mysql-mmm-monitor start
在所有mysql服务器上启动
chkconfig mysql-mmm-agent on
service mysql-mmm-agent start
六、高可用性测试:
服务器读写采有VIP地址进行读写,出现故障时VIP会漂移到其它节点,由其它节点提供服务。
mysql-mmm故障处理机制:
1.首先查看整个集群的状态,可以看到整个集群状态正常
[root@mmm-monitor ~]# mmm_control show
master-db1(192.168.1.11) master/ONLINE. Roles: reader(192.168.1.251), writer(192.168.1.250)
master-db2(192.168.1.12) master/ONLINE. Roles: reader(192.168.1.254)
slave-db1(192.168.1.13) slave/ONLINE. Roles: reader(192.168.1.252)
slave-db2(192.168.1.14) slave/ONLINE. Roles: reader(192.168.1.253)
2.关闭master-db1上的mysql服务,模拟mysql宕机
[root@master-db1 ~]# service mysqld stop
Shutting down MySQL... [确定]
3.mmm-monitor上查看集群状态
[root@mmm-monitor ~]# mmm_control show
master-db1(192.168.1.11) master/HARD_OFFLINE. Roles:
master-db2(192.168.1.12) master/ONLINE. Roles: reader(192.168.1.254), writer(192.168.1.250)
slave-db1(192.168.1.13) slave/ONLINE. Roles: reader(192.168.1.251), reader(192.168.1.252)
slave-db2(192.168.1.14) slave/ONLINE. Roles: reader(192.168.1.253)
从显示结果可以看出master-db1的状态有ONLINE转换为HARD_OFFLINE,写VIP转移到了master-db2主机上。
4.查看slave-db1和slave-db2主从状态
复制代码
mysql> show slave status\G #slave-db1
*** 1. row ***
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.12
Master_User: replication
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 636231
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 283
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
复制代码
复制代码
mysql> show slave status\G #slave-db2
*** 1. row ***
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.12
Master_User: replication
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 636231
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 283
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
复制代码
可以看到写请求的VIP已经转移到master-db2上了,且从节点的主都指向了master-db2
5.启动master-db1的mysql服务
[root@master-db1 ~]# service mysqld start
Starting MySQL...... [确定]
6.再次查看集群状态(大概等待一分钟左右)
[root@mmm-monitor ~]# mmm_control show
master-db1(192.168.1.11) master/ONLINE. Roles: reader(192.168.1.252)
master-db2(192.168.1.12) master/ONLINE. Roles: reader(192.168.1.254), writer(192.168.1.250)
slave-db1(192.168.1.13) slave/ONLINE. Roles: reader(192.168.1.251)
slave-db2(192.168.1.14) slave/ONLINE. Roles: reader(192.168.1.253)
7.再次slave-db1和slave-db2主从状态
复制代码
mysql> show slave status\G #slave-db1
*** 1. row ***
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.12
Master_User: replication
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 636231
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 283
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
复制代码
复制代码
mysql> show slave status\G #slave-db2
*** 1. row ***
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.12
Master_User: replication
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 636231
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 283
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
复制代码
可以看到主库启动不会接管主,直到现有的主再次宕机。
回到顶部
mysql-mmm故障处理机制中总结:
1.对外提供读写的虚拟IP是由monitor程序控制。如果monitor没有启动那么db服务器不会被分配虚拟ip,但是如果已经分配好了虚拟ip,当monitor程序关闭了原先分配的虚拟ip不会立即关闭外部程序还可以连接访问(只要不重启网络),这样的好处就是对于monitor的可靠性要求就会低一些,但是如果这个时候其中的某一个db服务器故障了就无法处理切换,也就是原先的虚拟ip还是维持不变,挂掉的那台DB的虚拟ip会变的不可访问。
2.agent程序受monitor程序的控制处理write切换,从库切换等操作。如果monitor进程关闭了那么agent进程就起不到什么作用,它本身不能处理故障。
3.monitor程序负责监控db服务器的状态,包括Mysql数据库、服务器是否运行、复制线程是否正常、主从延时等;它还用于控制agent程序处理故障。
4.monitor会每隔几秒钟监控db服务器的状态,如果db服务器已经从故障变成了正常,那么monitor会自动在60s之后将其设置为online状态(默认是60s可以设为其它的值),有监控端的配置文件参数“auto_set_online”决定,群集服务器的状态有三种分别是:HARD_OFFLINE→AWAITING_RECOVERY→online
5.默认monitor会控制mmm_agent会将writer db服务器read_only修改为OFF,其它的db服务器read_only修改为ON,所以为了严谨可以在所有的服务器的my.cnf文件中加入read_only=1由monitor控制来控制writer和read,root用户和复制用户不受read_only参数的影响。
回到顶部
mysql-mmm架构总结:
(1)master-db2备选主节点宕机不影响集群的状态,就是移除了master-db2备选节点的读状态。
(2)master-db1主节点宕机,由master-db2备选主节点接管写角色,slave-db1,slave-db2指向新master2主库进行复制,slave-db1,slave-db2会自动change master到master2.
(3)如果master-db1主库宕机,master-db2复制应用又落后于master-db1时就变成了主可写状态,这时的数据主无法保证一致性。
如果master-db2,slave-db1,slave-db2延迟于master-db1主,这个时master-db1宕机,slave-db1,slave-db2将会等待数据追上master-db1后,再重新指向新的主master-db2进行复制操作,这时的数据也无法保证同步的一致性。
(4)如果采用MMM高可用架构,主,主备选节点机器配置一样,而且开启半同步进一步提高安全性或采用MariaDB/mysql5.7进行多线程从复制,提高复制的性能。
参考文档:http://mysql-mmm.org/mmm2:guide
http://mysql-mmm.org/mysql-mmm.html