Mysql - 高可用方案之MMM

一、概述

本文将介绍mysql的MMM(Master-Master replication manager for MySQL)方案。官方文档地址:https://mysql-mmm.org/start.html
MMM架构由三台mysql服务器(两主一从)和一台监控节点组成,主库只有一台能对外提供写服务,另外一台主和从只对外提供读服务。当提供写服务的主库服务器发生故障时,能自动将写的vip漂移到另外一台写库上,并将从库重新指向另一台写库,实现高可用。

写库故障发生前:

mmm1

写库故障发生后:

mmm2

二、节点介绍

本次实验采用4台虚拟机,操作系统版本Centos6.10,mysql版本5.7.25
monitor  10.40.16.60  监控  监控集群
node1    10.40.16.61  主库  提供写服务
node2    10.40.16.62  主库  提供读服务
node3    10.40.16.63  从库  提供读服务

还须预留4个vip,不用手工配置,这里先提一下,后面的安装步骤用得到
10.40.16.71  写vip
10.40.16.72  读vip
10.40.16.73  读vip
10.40.16.74  读vip


三、安装

1. 配置双主一从

其中node1与node2互为主从,node3作为node1的从。具体的复制搭建这里就省略,要是这都不会,那么该文章对你就没意思了。顺便安利一个自己写的mysql一键安装脚本https://www.cnblogs.com/ddzj01/p/10678296.html
注明:集群中使用的复制账号为repl,密码是'123456'

node1(10.40.16.61)
(root@localhost)(none)]> show slave status\G
*************************** 1. row ***************************
                Slave_IO_State: Waiting for master to send event
                   Master_Host: 10.40.16.62
                   Master_User: repl
                  
node2(10.40.16.62)
(root@localhost)[(none)]> show slave status\G
*************************** 1. row ***************************
                Slave_IO_State: Waiting for master to send event
                   Master_Host: 10.40.16.61
                   Master_User: repl

node3(10.40.16.63)
(root@localhost)[(none)]> show slave status\G
*************************** 1. row ***************************
                Slave_IO_State:
                   Master_Host: 10.40.16.61
                   Master_User: repl
                
可以看到node1和node2互为主备,node3作为node1的备


2. 下载扩展包(node1&node2&node3&monitor)

wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm
rpm -ivh epel-release-latest-6.noarch.rpm

编辑文件/etc/yum.repos.d/epel.repo

image

将该文件的第三行取消注释,第四行添加注释,如下所示

image


3. 安装MMM包

每个数据库节点(node1&node2&node3)
yum install -y mysql-mmm-agent.noarch

监控节点(monitor)
yum install -y mysql-mmm-*


4. 创建相关账号

在node1中创建以下账号

监控账号(监控数据库状态)
(root@localhost)[(none)]> grant replication client on *.* to 'mmm_monitor'@'%' identified by '123456';

代理账号(MMM代理)
(root@localhost)[(none)]> grant super, replication client, process on *.* to 'mmm_agent'@'%' identified by '123456';


5. 修改配置文件

所有中文的注释是要修改的地方,注意不要在配置文件中写任何注释
在monitor中编辑/etc/mysql-mmm/mmm_mon.conf

Snipaste_2019-09-17_17-37-16


在monitor中编辑/etc/mysql-mmm/mmm_common.conf,传给其它三个节点,内容都一致

image

scp /etc/mysql-mmm/mmm_common.conf 10.40.16.61:/etc/mysql-mmm/
scp /etc/mysql-mmm/mmm_common.conf 10.40.16.62:/etc/mysql-mmm/
scp /etc/mysql-mmm/mmm_common.conf 10.40.16.63:/etc/mysql-mmm/

 

在node1&node2&node3中编辑/etc/mysql-mmm/mmm_agent.conf,更改'this db1',与mmm_common保持一致

image


6. 启动

node1&node2&node3
[root@mysqla ~]# service mysql-mmm-agent start
[root@mysqlb ~]# service mysql-mmm-agent start
[root@mysqlc ~]# service mysql-mmm-agent start

monitor
[root@monitor ~]# service mysql-mmm-monitor start


7. 查看

在monitor中
[root@monitor ~]# mmm_control show  # 查看集群状态
image
  
[root@monitor ~]# mmm_control checks all  # 查看更加具体的信息

image


四、MMM优缺点

优点:
1. 提供读写vip
2. 提供从服务器的延迟监控,在从服务器出现大量的主从延迟或主从链路中断时,可以把这台从服务器上的读的vip,飘移到集群中其它正常的节点上
3. 提供主数据库故障转移后从服务器对新主的重新同步功能

缺点:
1. 发布时间较早,文档最后更新的时间是2012年,存在一些bug,并且不支持gtid服务功能
2. 没有读负载均衡的功能
3. 进行主从切换时,新主如果落后于旧主,容易造成新主的数据丢失。如果从库落后于旧主,从库指向新的主库的时候,也会造成从库部分数据丢失。
4. 如果从服务器的日志较新主的服务器日志新,那么就是主从不一致的,会出现事务重复提交。

 

五、实验

一、概述

上一篇博客中(https://www.cnblogs.com/ddzj01/p/11535796.html)介绍了如何搭建MMM架构,本文将通过实验介绍MMM架构的优缺点。


二、优点

1. 写vip转移

关掉node1的mysql,看集群会发生什么变化
[root@mysqla ~]# service mysql stop

在monitor查看集群状态
[root@monitor ~]# mmm_control show
image
  
在node3中查看
(root@localhost)[(none)]> show slave status\G
image

可以看到写vip(10.40.16.71)已经漂移到node2,并且node3重新指向了node2

 

2. 读vip漂移

启动node1的mysql
[root@mysqla ~]# service mysql start

在monitor查看集群状态(可能需要等接近一分钟才能看到下面的状态)
如果长时间是AWAITING_RECOVERY状态,可以去日志中查看原因/var/log/mysql-mmm/mmm_mond.log,确认都没有问题可以使用手工将节点上线"mmm_control set_online db1"
[root@monitor ~]# mmm_control show
image

可以看到node1又重新加到集群中了,并且有一个读vip已经漂移到node1上了

关闭node3(从库)的mysql
[root@mysqlc ~]# service mysql stop

在monitor查看集群状态
[root@monitor ~]# mmm_control show
image
  
可以看到node3(从库)的读vip漂移到了node1上,node3(从库)没有任何读vip了
  

3. 读延迟

启动node3(从库)的mysql
[root@mysqlc ~]# service mysql start

在monitor查看集群状态
[root@monitor ~]# mmm_control show
image

在monitor中编辑/etc/mysql-mmm/mmm_mon.conf
添加max_backlog参数,这个参数指的是集群中从库落后于主库多长时间,就将从库上面的读vip摘除。默认是60。
image

在monitor上重启进程
[root@monitor ~]# service mysql-mmm-monitor restart

在node3(从库)将数据库锁住
(root@localhost)[(none)]> flush tables with read lock;

在node2(主库)对数据库随便做点修改
(root@localhost)[test1]> insert into t1 values(20);

在node3(从库)查看从库状态
(root@localhost)[(none)]> show slave status\G
image
可以看到从库已经落后了13秒了
                
在monitor查看状态
[root@monitor ~]# mmm_control checks all
image
可以看到node3显示ERROR: Backlog is too big

[root@monitor ~]# mmm_control show
image
可以看到node3的读vip又飘走了。


三、缺点

1. 新主如果落后于旧主,故障切换时,容易造成新主的数据丢失

这个好理解,mysql主从采用的是异步架构,主库的日志如果还没有传到从库上就已经down了,从库就丢失这部分事务了。MMM这种架构也不例外。

 

2. 事务重复提交的问题

在monitor中编辑/etc/mysql-mmm/mmm_mon.conf,将max_backlog参数删除
image

在monitor上重启进程
[root@monitor ~]# service mysql-mmm-monitor restart

在node3(从库)将数据库锁释放
(root@localhost)[(none)]> unlock tables;

在monitor查看状态
[root@monitor ~]# mmm_control show

现在承担写角色的是节点2

先把node1的sql_thread停掉,模拟node1落后于node2的情况(这种情况是指node1已经接收到node2的日志,但是还没有应用)
(root@localhost)[test1]> stop slave sql_thread;

在node2上插入一条数据
(root@localhost)[test1]> insert into t1 values(20);

然后把node2的msyql关闭
[root@mysqlb ~]# service mysql stop

在monitor查看状态
[root@monitor ~]# mmm_control show
image
可以看到写vip飘到node1上了

再重启node1的slave进程
(root@localhost)[test1]> stop slave;
(root@localhost)[test1]> start slave;

再来查看node1和node3上t1这张表的数据
node1
(root@localhost)[test1]> select * from t1;
image

node3
(root@localhost)[test1]> select * from t1;
image

(root@localhost)[test1]> show slave status\G
image
可以看到新主变成node1,但是node3上面20却有两条,出现了事务重复提交的情况。

 

3. 从库丢失事务的情况

先把node2的msyql打开
[root@mysqlb ~]# service mysql start

在monitor查看状态
[root@monitor ~]# mmm_control show
image

在node1把t1表truncate
(root@localhost)[test1]> truncate table t1;

把node3的sql_thread停掉,模拟node3落后于node1的情况(这种情况是指node3已经接收到node1的日志,但是还没有应用)
(root@localhost)[test1]> stop slave sql_thread;

在node1上插入一条数据
(root@localhost)[test1]> insert into t1 values(10);

把node1的msyql关闭
[root@mysqlb ~]# service mysql stop

再重启node3的slave进程
(root@localhost)[test1]> stop slave;
(root@localhost)[test1]> start slave;

查看node3的复制状态
(root@localhost)[test1]> show slave status\G
image
可以看到节点重新指向了node2

查看各节点的t1数据
node2
(root@localhost)[test1]> insert into t1 values(20);

(root@localhost)[test1]> select * from t1;
image

node3
(root@localhost)[test1]> select * from t1;
image

可以看到现在是同步了,但是此时从库已经丢失了原主库的事务,即10这条数据。


四、总结

MMM这种高可用架构比较老了,从库的数据一致性很难保证,所以在生产上尽量不要使用这种架构。后面将给大家介绍mysql的另一种高可用架构MHA。

posted @ 2021-05-20 14:38  da0h1  阅读(354)  评论(0编辑  收藏  举报