暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL高可用集群-MMM

程序猿集锦 2021-06-24
1659

微信搜索“coder-home”或扫一扫下面的二维码,关注公众号,

第一时间了解更多干货分享,还有各类视频教程资源。扫描它,带走我


  • 前言

  • 集群 VS 高可用

  • MMM高可用架构

    • 什么是MMM

    • MMM架构的优点

    • MMM架构的缺点

  • 如何搭建MMM高可用架构

    • 搭建双主双从的MySQL集群

      • 准备MySQL数据库环境

      • 创建主从同步的数据库用户

      • 历史数据的同步

      • 开启组从同步

      • 配置主与主的同步

    • 安装MMM

      • 修改apt-get源

      • 下载MMM

      • 编译安装MMM

    • 创建MMM使用的MySQL用户

    • 修改MMM的配置文件

    • 启动MMM服务

    • 验证VIP访问数据库

    • 验证MMM的高可用

  • 总结


前言

MySQL的高可用有很多种,有我们经常说的MMM架构、MHA架构、MGR架构。在这一篇文章中我们先讨论MMM架构的高可用,后续在分析MHA和MGR,其中的MGR有点类似于percona推出的PXC集群

集群 VS 高可用

在MySQL数据库中,什么是集群?什么是高可用?最早我理解的是只要有了读写分离的组从集群架构,就是拥有高可用的架构了。现在想想,当初的想法是多么的天真。MySQL集群和MySQL的高可用是两个概念,我们不能把他们混为一谈。

集群是指你多台MySQL数据库实例,有一个可以提供写,多个提供读、或者有多个可以写,多个可以读。比如我们配置了读写分离的一主多从的集群架构,或者双主多从的集群架构。此时,我们只是有了MySQL的集群,在读写性能上有锁提升,但是此时并不是一个高可用的MySQL架构。

高可用是指在任意一个时刻,我们的MySQL都可以提供读写的服务,不会因为某一个MySQL数据库实例宕机而导致MySQL数据不能正常读写,此时才是高可用。从某种意义上来说,高可用要在集群的基础上才可以实现,也就是说,要想高可用,必须先把集群搭建起来。有了MySQL的集群,才可以谈论MySQL的高可用,没有MySQL的集群,谈MySQL的高可用犹如空中楼阁。

拿我们前面说的双主多从的MySQL集群架构来说,两个主在同一个时间点,若只有一个主对外提供写的服务,此时如果其中一个主宕机,另外一个主可以顶替原先的主对外提供写的服务,同时其他的从可以把同步的数据源切换到新的主上面来,这样的一个集群就是一个高可用的架构。

有了MySQL的集群,并不一定就有MySQL的高可用。但是如果有了MySQL的高可用,那么此时它一定是一个MySQL集群。高可用需要在集群的基础上来配合其他组件才能实现。


MMM高可用架构


什么是MMM

所谓的MMM只是:Multi-Master Replication Manager for MySQL,取其中的三个M开头的单词简写。它是mysql多主复制管理器,基于perl实现,关于mysql主主复制配置的监控、故障转移和管理的一套可伸缩的脚本套件(在任何时候只有一个节点可以被写入),MMM也能对从服务器进行读负载均衡,所以可以用它来在一组用于复制的服务器启动虚拟ip,除此之外,它还有实现数 据备份、节点之间重新同步功能的脚本。

MySQL本身没有提供replication failover的解决方案,通过MMM方案 能实现服务器的故障转移,从而实现mysql的高可用。MMM不仅能提供浮动IP的功能,如果当前的主服务器挂掉后,会将你后端的从服务器自动转向新的主服务器进行同步复制,不用手工更改同步配置。

从字面来理解就是它有两个master节点,并且实现了这两个master节点的高可用。它的架构如下所示:



MMM主要功能,由下面三个脚本提供:

  • mmm_mond 负责所有的监控工作的监控守护进程,决定节点的移除(mmm_mond进程定 时心跳检测,失败则将write ip浮动到另外一台master)

  • mmm_agentd 运行在mysql服务器上的代理守护进 程,通过简单远程服务集提供给监控节点

  • mmm_control 通过命令行管理mmm_mond进程 在整个监管过程中, 需要在mysql中添加相关授权用户,授权的用户包括一个mmm_monitor用户和一个mmm_agent用户,如果想使用mmm的备份工具则还要添加一个mmm_tools用户。

MMM架构的优点

  • 可以兼容不同系列的MySQL来做高可用。比如有MySQL官方社区版本,有percona版本的,有MariaDB版本的MySQL。这样的集群可以可以使用MMM架构来做高可用。

  • 高可用性,扩展性好,出现故障自动切换,对于主主同步,在同一时间只提供一台数据库写操作,保证 的数据的一致性。

  • 当主服务器挂掉以后,另一个主立即接管,其他的从服务器能自动切换,不用人工干预。


MMM架构的缺点

  • 是一种比较老的MySQL高可用实现方式,因为社区不活跃,所以目前已经没有人在维护这个组件了。

  • 只能基于日之点的主从复制集群架构来做高可用,不支持基于GTID的主从复制集群架构。这也是因为社区活跃,没有维护这个组件导致不支持GTID。

  • 数据不能保证100%的一致性,这个是以为它在做故障转移的时候实现的方式所导致的。如果对于数据需要强一致性,则不能选择MMM高可用架构,可以考虑MHA高可用架构。

  • monitor节点是单点,不过这个可以结合keepalived或者haertbeat做成高可用。

  • 至少三个节点,2个master,1个slave,对主机的数量有要求,

  • 在读写非常繁忙的业务系统下表现不是很稳定,可能会出现复制延时、切换失效等问题。

  • MMM方案并不太适应于对数据安全性要求很高,并且读、写 繁忙的环境中。

  • 需要实现读写分离,还需要在前端编写读写分离程序,或者结合数据库中间件如mycat来解决。


如何搭建MMM高可用架构

要想实现MMM高可用架构,我们先来搭建一个双主双从的MySQL集群,然后在这个集群的基础上来完成MMM高可用的架构。

我们准备搭建的MySQL-MMM高可用架构的网络拓扑如下所示:需要注意的是其中的VIP,这几个IP不需要我们自己创建,MMM服务会自动的在各个节点分配这些VIP。其中的绿色字体read vip,它并不会严格的按照我们下图中分配是主机来分配,而是随机的将这4个read vip分布到4个数据库节点上,但是红色字体的write vip只会在master1或master2上面随着master1和master2节点宕机和恢复来回切换。

搭建双主双从的MySQL集群


准备MySQL数据库环境

我们使用docker来启动4个MySQL容器,作为双主双从的四个MySQL数据库实例。容器镜像的名称为mysql:5.7.31
,这个镜像是docker hub上面MySQL官方提供的镜像,它是基于Debian buster
版本制作的MySQL容器镜像。所以,我们的MySQL数据库服务器,可以任务是一个minimal版本的Debian系统。

为了方便管理,我们先创建一个docker虚拟网段,然后在启动四个MySQL数据库的时候,指定数据库服务器的IP地址并且使用这个网段。创建网段的命令如下:


docker network create --subnet=172.20.0.0/24 mysql-ha-mmm-network

我们使用下面的四条命令,启动4个MySQL数据库实例。这里我们把每一个数据库的my.cnf
配置文件已经在本地配置好,然后通过数据卷的方式挂载到MySQL容器中,这样我们启动的MySQL数据库实例就会按照我们配置的my.cnf
配置文件来启动并配置我们的MySQL数据库实例。


# 启动master1节点
docker run --net=mysql-ha-mmm-network --hostname master1.mysql --ip 172.20.0.11 --cap-add NET_ADMIN --name mysql-ha-mmm-master1 -d -v Users/coder-home/docker_mysql_ha/mmm/master1:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root -e TZ="Asia/Shanghai" -p 33011:3306 mysql:5.7.31

# 启动slave1节点
docker run --net=mysql-ha-mmm-network --hostname slave1.mysql --ip 172.20.0.12 --cap-add NET_ADMIN --name mysql-ha-mmm-slave1 -d -v Users/coder-home/docker_mysql_ha/mmm/slave1:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root -e TZ="Asia/Shanghai" -p 33012:3306 mysql:5.7.31

# 启动master2节点
docker run --net=mysql-ha-mmm-network --hostname master2.mysql --ip 172.20.0.21 --cap-add NET_ADMIN --name mysql-ha-mmm-master2 -d -v Users/coder-home/docker_mysql_ha/mmm/master2:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root -e TZ="Asia/Shanghai" -p 33021:3306 mysql:5.7.31

# 启动slave2节点
docker run --net=mysql-ha-mmm-network --hostname slave2.mysql --ip 172.20.0.22 --cap-add NET_ADMIN --name mysql-ha-mmm-slave2 -d -v Users/coder-home/docker_mysql_ha/mmm/slave2:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root -e TZ="Asia/Shanghai" -p 33022:3306 mysql:5.7.31

这里解释一下docker run
后面几个重要的参数和含义。

  • --net=mysql-ha-mmm-network:指定容器运行的时候使用的网段。

  • --hostname slave2.mysql:指定容器的主机名称。

  • --ip 172.20.0.22:指定容器使用的IP地址。

  • --cap-add NET_ADMIN:默认容器运行的时候,没有增加额外的Linux的功能,这里我们要增加上NET_ADMIN的功能,否则我们不能再启动后的容器内使用ifconfig命令增加虚拟IP。否则会有如下错误提示:


root@test:/etc/network# ifconfig eth0:0 192.168.1.100 up
SIOCSIFADDR: Operation not permitted
SIOCSIFFLAGS: Operation not permitted
SIOCSIFFLAGS: Operation not permitted
root@test:/etc/network#
  • --name mysql-ha-mmm-slave2:指定容器的名称为mysql-ha-mmm-slave2
    ,后面我们在停止或重启容器的时候,可以通过这个名称来操作容器。

  • -d:以demon进程的方式运行容器。

  • -v Users/coder-home/docker_mysql_ha/mmm/slave2:/etc/mysql/conf.d:把本地的/Users/coder-home/docker_mysql_ha/mmm/slave2
    目录挂载到容器中的/etc/mysql/conf.d
    目录下。

  • -e MYSQL_ROOT_PASSWORD=root:向容器内传入参数,我们指定MySQL数据库root用户的密码也为root。

  • -e TZ="Asia/Shanghai":向容器内传入参数,这里我们指定的容器中使用的系统的时区为上海时间。

  • -p 33022:3306:我们指定容器中的3306端口,映射到我们本地为33022。这样我们在本地访问MySQL服务的时候,就可以通过33022端口来访问。

  • mysql:5.7.31:这个是我们要运行的容器的名称和版本。如果本地没有这个容器名称和版本,则会从docker hub中自动拉取这个镜像名称和版本到本地,然后再启动这个镜像。

容器启动后,我们可以查看启动后的结果如下:


➜  ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5207089da9a5 mysql:5.7.31 "docker-entrypoint.s…" About a minute ago Up About a minute 33060/tcp, 0.0.0.0:33022->3306/tcp mysql-ha-mmm-slave2
1c8ff5960272 mysql:5.7.31 "docker-entrypoint.s…" About a minute ago Up About a minute 33060/tcp, 0.0.0.0:33021->3306/tcp mysql-ha-mmm-master2
d8d646ba25f1 mysql:5.7.31 "docker-entrypoint.s…" About a minute ago Up About a minute 33060/tcp, 0.0.0.0:33012->3306/tcp mysql-ha-mmm-slave1
d3d75d9cd930 mysql:5.7.31 "docker-entrypoint.s…" About a minute ago Up About a minute 33060/tcp, 0.0.0.0:33011->3306/tcp mysql-ha-mmm-master1
➜ ~

下面我们查看每一个MySQL数据库容器的host文件中的IP地址:

  • master1的host文件如下:


➜ ~ docker exec -it mysql-ha-mmm-master1 bin/bash
root@master1:/# cat etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.20.0.11 master1.mysql master1
root@master1:/#
  • master2的host文件如下:


➜  ~ docker exec -it mysql-ha-mmm-master2 bin/bash
root@master2:/# cat etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.20.0.21 master2.mysql master2
root@master2:/#
  • slave1的host文件如下:


➜  ~ docker exec -it mysql-ha-mmm-slave1 bin/bash
root@slave1:/# cat etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.20.0.12 slave1.mysql slave1
root@slave1:/#
  • slave2的host文件如下:


➜  ~ docker exec -it mysql-ha-mmm-slave2 bin/bash
root@slave2:/# cat etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.20.0.22 slave2.mysql slave2
root@slave2:/#

上面我们启动的四个MySQL数据库实例,我们还需要一个监控节点,下面启动一个监控节点,用于安装MMM的监控服务。

为了和其他环境一致,这里我们也使用上面MySQL的镜像。如下是启动一个新的MySQL容器,这个容器,我们不在挂载MySQL的my.cnf配置文件了,因为这个MySQL数据库我们不会使用,我们只是在这个容器中安装MMM的监控服务,我们此时把这个MySQL数据库容器当成一个Debian版本的虚拟机来使用。


# 启动监控节点
docker run --net=mysql-ha-mmm-network --hostname monitor.mysql --ip 172.20.0.10 --cap-add NET_ADMIN --name mysql-ha-mmm-monitor -d -e MYSQL_ROOT_PASSWORD=root -e TZ="Asia/Shanghai" -p 33010:3306 mysql:5.7.31

查看这个监控节点的host文件如下:


➜  ~ docker exec -it mysql-ha-mmm-monitor bin/bash
root@monitor:~# cat etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.20.0.10 monitor.mysql monitor
root@monitor:~#


创建主从同步的数据库用户

在组从同步的时候,从需要使用一个指定的用户去连接到主上面同步主上面的binlog日志。所以,我们需要在我们的主上面创建好这样的一个用户。因为在master1宕机之后,MMM组件会将master2提升为新的主库,所以需要在master1和master2上面都创建一个这样的用户,也就是下的命令需要在两个master节点上都执行一下。


create user 'repl_user'@'172.20.0.%' identified by 'repl_user';
grant replication slave on *.* to 'repl_user'@'172.20.0.%';


历史数据的同步

如果我们并不是基于一个新的集群环境来搭建,而是基于一个已经运行了一段时间的MySQL数据库来做集群,此时我们需要把选定的master节点上面的数据,先使用mysqldump
命令导出为.sql
文件,然后再把这个.sql
文件导入到所有的slave节点上去。然后在可以开始下面的任务。

在master上面执行的导出的命令示例如下:


mysqldump -uroot -proot \
--master-data=2 \
--single-transaction \
--flush-logs \
--triggers \
--routines \
--events \
-B mydb1 > mydb1.sql

在所有的slave节点上执行的导入数据的命令示例如下:


mysql -uroot -proot < mydb1.sql

但是,我们是基于一个崭新的环境来做的,不涉及到历史数据的问题。所以,这一步我们可以省略。


开启组从同步

在所有的slave上面执行如下命令,此时的binlog文件和日志点的位置,可以在master1上面使用show master status
命令查看,或者查看导出数据的时候,生成的.sql
文件。在master1节点上执行mysqldump
导出命令的时候,我们指定的--master-data=2
,这个参数会在导出的.sql
文件中标记当前master1节点上binlog日志的文件名称和日志偏移量。


change master to master_host='172.20.0.11', master_user='repl_user', master_password='repl_user', MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=1034;

开启组从同步:


start slave;

查看同步状态:


mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.20.0.11
Master_User: repl_user
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 1034
Relay_Log_File: mysql-relay.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 1034
Relay_Log_Space: 523
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 11
Master_UUID: 047bcc07-7424-11eb-96b4-0242ac14000b
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)

mysql>


配置主与主的同步

上面我们配置好了master1->slave1,master1->slave2
的同步。我们还需要在master1和master2直接配置互相同步对方。

现在master2上面配置master1作为它的主库。参考上面slave1和slave2上面的配置。执行如下命令:


change master to master_host='172.20.0.11', MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=1034;

start slave user='repl_user' password='repl_user';

show slave status\G

然后再配置master2到master1的同步。此时我们需要查看一下master2上面的binlog日志名称和日志偏移量是多少。使用如下命令查看:


mysql> show master status\G
*************************** 1. row ***************************
File: mysql-bin.000003
Position: 623
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)

mysql>

然后我们登录到master1上面,执行如下命令,配置master2作为master1的主库。


change master to master_host='172.20.0.21', MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=623;

start slave user='repl_user' password='repl_user';

show slave status\G

验证双主双从同步的效果如下:

安装MMM


修改apt-get源

在下载MMM之前,我们先修改一下apt-get
源,然后更新一下apt-get
源。如下所示,因为此时的容器中,没有vim
命令,所以我们使用echo "xxx" >/etc/apt/sources.list
的方式去更新apt-get
的源。


echo "
deb http://mirrors.aliyun.com/debian/ buster main non-free contrib
deb http://mirrors.aliyun.com/debian-security buster/updates main
deb http://mirrors.aliyun.com/debian/ buster-updates main non-free contrib
deb http://mirrors.aliyun.com/debian/ buster-backports main non-free contrib

deb-src http://mirrors.aliyun.com/debian-security buster/updates main
deb-src http://mirrors.aliyun.com/debian/ buster main non-free contrib
deb-src http://mirrors.aliyun.com/debian/ buster-updates main non-free contrib
deb-src http://mirrors.aliyun.com/debian/ buster-backports main non-free contrib
"
> etc/apt/sources.list

注意,在更新镜像源的时候,要根据自己的Debian系统的版本,我的Debian系统的版本是buster
版本,所以你要根据自己的系统版本网上找到对应的镜像地址。接着,我们更新一下系统。


root@master1:/etc/apt# apt-get update
Get:1 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB]
Get:2 http://repo.mysql.com/apt/debian buster InRelease [21.5 kB]
Get:3 http://mirrors.ustc.edu.cn/debian buster InRelease [122 kB]
Get:4 http://security.debian.org/debian-security buster/updates/main amd64 Packages [267 kB]
Get:5 http://mirrors.ustc.edu.cn/debian buster-updates InRelease [51.9 kB]
Get:6 http://mirrors.ustc.edu.cn/debian buster/main amd64 Packages [7907 kB]
Get:7 http://repo.mysql.com/apt/debian buster/mysql-5.7 amd64 Packages [5693 B]
Get:8 http://mirrors.ustc.edu.cn/debian buster-updates/main amd64 Packages [9504 B]
Fetched 8450 kB in 10s (871 kB/s)
Reading package lists... Done
root@master1:/etc/apt#

更新完成之后,我们先安装一下我们经常用到的几个命令:


apt-get install net-tools wget vim make cmake inetutils-ping iproute2 iproute2-doc -y


下载MMM

推荐使用源码来安装,这样可以在任何Linux系统版本上面进行安装,例如:Ubuntu、Debian、CentOS、Redhat等等。不用因为系统版本的问题找对应的rpm
包,找对应的deb
包。

通过如下步骤来获取MMM的源码。

登录Debian的官方网站:https://www.debin.org,然后点击跟多关于下载与软件介绍的连接。

此时我们会进入如下页面:https://www.debian.org/intro/index#software,然后点击软件包连接。

接着,我们会进入如下页面:https://www.debian.org/distrib/packages#search_packages,根据选项输入mysql-mmm
,点击搜索按钮。

点击上面的搜索按钮后,进入如下页面:https://packages.debian.org/search?keywords=mysql-mmm&searchon=names&suite=oldstable&section=all,然后我们点击页面中的Debian系统的版本,选择jessie
版本,因为mysql-mmm
是比较老的一种MySQL考可用架构,在最新的Debian系统中,已经没有这样的软件包了,所以我们选择老版本的jessie
版本,这个版本中包含mysql-mmm
的源码。

点击完成jessie
之后,进入如下页面:https://packages.debian.org/search?suite=jessie&searchon=names&keywords=mysql-mmm,此时我们已经搜索到了mysql-mmm
的软件。点击其中任何一个链接,进入详细页面。

进入如下的页面:https://packages.debian.org/jessie/mysql-mmm-tools,我们选择下载源码文件。

或者我们可以右键复制下载地址:http://deb.debian.org/debian/pool/main/m/mysql-mmm/mysql-mmm_2.2.1.orig.tar.gz,使用wget命令下载源码到MySQL服务器上。


wget http://deb.debian.org/debian/pool/main/m/mysql-mmm/mysql-mmm_2.2.1.orig.tar.gz

如果要下载.deb文件,可以点击上面图片中的硬件架构下面的all
连接,进入下面页面后,选择对应的距离我们最近镜像地址,我选择的为ftp.cn.debian.org
这个镜像地址,然后复制下载链接地址,使用wget下载即可。这里贴出如下的下载示例:


wget http://ftp.cn.debian.org/debian/pool/main/m/mysql-mmm/mysql-mmm-tools_2.2.1-1.1_all.deb
wget http://ftp.cn.debian.org/debian/pool/main/m/mysql-mmm/mysql-mmm-monitor_2.2.1-1.1_all.deb
wget http://ftp.cn.debian.org/debian/pool/main/m/mysql-mmm/mysql-mmm-common_2.2.1-1.1_all.deb
wget http://ftp.cn.debian.org/debian/pool/main/m/mysql-mmm/mysql-mmm-agent_2.2.1-1.1_all.deb

编译安装MMM

我们是使用的MySQL的容器镜像来启动的MySQL集群,而这个从docker hub上面拉取的MySQL5.7官方版本的镜像是基于Debian系统来制作的,所以我们此次安装MMM软件需要基于Debian系统来安装。

下载好的mysql-mmm
如下所示:


root@test:~# ls -lstr
total 60
56 -rw-r--r-- 1 root root 55278 Feb 21 16:22 mysql-mmm_2.2.1.orig.tar.gz
4 drwxr-xr-x 2 root root 4096 Feb 21 16:24 deb
root@test:~#

解压并且安装,但是在安装MMM之前,先安装一下它的依赖包,使用如下命令来安装:


apt-get install liblog-log4perl-perl libmailtools-perl liblog-dispatch-perl libclass-singleton-perl libproc-daemon-perl libalgorithm-diff-perl libdbi-perl libdbd-mysql-perl -y

安装MMM的命令和过程如下:


root@test:~# tar -zxf mysql-mmm_2.2.1.orig.tar.gz
root@test:~# ls -lstr
total 64
4 drwxr-xr-x 6 root root 4096 May 7 2010 mysql-mmm-2.2.1
56 -rw-r--r-- 1 root root 55278 Feb 21 16:22 mysql-mmm_2.2.1.orig.tar.gz
4 drwxr-xr-x 2 root root 4096 Feb 21 16:24 deb
root@test:~# cd mysql-mmm-2.2.1/
root@test:~/mysql-mmm-2.2.1# make install
mkdir -p usr/share/perl5/MMM usr/lib/mysql-mmm usr/sbin var/log/mysql-mmm etc etc/mysql-mmm etc/init.d/
cp -r lib/Common/ usr/share/perl5/MMM
[ -f etc/mysql-mmm/mmm_common.conf ] || cp etc/mysql-mmm/mmm_common.conf etc/mysql-mmm/
mkdir -p usr/lib/mysql-mmm/agent/
cp -r lib/Agent/ usr/share/perl5/MMM
cp -r bin/agent/* usr/lib/mysql-mmm/agent/
cp -r etc/init.d/mysql-mmm-agent etc/init.d/
cp sbin/mmm_agentd usr/sbin
[ -f etc/mysql-mmm/mmm_agent.conf ] || cp etc/mysql-mmm/mmm_agent.conf etc/mysql-mmm/
mkdir -p usr/lib/mysql-mmm/monitor/
cp -r lib/Monitor/ usr/share/perl5/MMM
cp -r bin/monitor/* usr/lib/mysql-mmm/monitor/
cp -r etc/init.d/mysql-mmm-monitor etc/init.d/
cp sbin/mmm_control sbin/mmm_mond usr/sbin
[ -f etc/mysql-mmm/mmm_mon.conf ] || cp etc/mysql-mmm/mmm_mon.conf etc/mysql-mmm/
mkdir -p usr/lib/mysql-mmm/tools/
cp -r lib/Tools/ usr/share/perl5/MMM
cp -r bin/tools/* usr/lib/mysql-mmm/tools/
cp sbin/mmm_backup sbin/mmm_clone sbin/mmm_restore usr/sbin
[ -f etc/mysql-mmm/mmm_tools.conf ] || cp etc/mysql-mmm/mmm_tools.conf etc/mysql-mmm/
root@test:~/mysql-mmm-2.2.1#

如果在安装mmm
的时候,提示没有make
命令,则需要先安装make
命令,安装的时候如果是Debian或Ubuntu系统,使用如下apt-get命令安装:


apt-get install make cmake -y

如果是CentOS或Redhat系统,则使用如下的yum命令来安装:


yum install make cmake -y

以上编译安装MMM需要在每一个节点都执行,包括两个master节点和两个slave节点,还有monitor监控节点也要安装。

安装完MMM之后,我们需要注意一下几个目录,这是我们使用MMM服务的基础。


# MMM各种配置文件所在目录
/etc/mysql-mmm

# MMM服务日志文件所在目录
/var/log/mysql-mmm/mmm_mond.log # MMM的monitor服务的日志文件
/var/log/mysql-mmm/mmm_agentd.log # MMM的agent服务的日志文件

# 各种perl脚本所在目录
/usr/lib/mysql-mmm/agent # agent客户端各种脚本所在目录
/usr/lib/mysql-mmm/monitor # monitor监控端各种脚本所在目录
/usr/lib/mysql-mmm/tools # 工具包脚本所在目录

# 启动和关闭MMM服务的脚本文件
/etc/init.d/mysql-mmm-agent
/etc/init.d/mysql-mmm-monitor


创建MMM使用的MySQL用户

监控用和客户端用户,在所有的节点上都要创建这两个用户。如果已经配置组从同步,在master1上创建就OK,其他节点会自动同步这两个创建好的用户到其他节点。


create user 'mmm_monitor'@'172.20.0.%' identified by 'mmm_monitor';
grant replication client on *.* to 'mmm_monitor'@'172.20.0.%';

create user 'mmm_agent'@'172.20.0.%' identified by 'mmm_agent';
grant super, replication client, process on *.* to 'mmm_agent'@'172.20.0.%';

需要注意的是这两个用户的权限不同,结合前面我们配置组从同步的哪一个用户,我们来对比一下:

  • monitor:MMM监控使用的用户,拥有replication client权限就可以。

  • agent:MMM客户单使用的用,拥有super、replication client、process权限。

  • replication:组从同步使用的用户,拥有replication slave权限即可。

最后的用户在四个节点上面的结果如下图所示:

修改MMM的配置文件

MMM所有的配置文件都在如下目录中:


root@master1:/etc/mysql-mmm# ls -lstr etc/mysql-mmm/*
4 -rw-r----- 1 root root 321 Feb 22 21:46 etc/mysql-mmm/mmm_mon.conf
4 -rw-r----- 1 root root 1293 Feb 22 21:46 etc/mysql-mmm/mmm_tools.conf
4 -rw-r----- 1 root root 37 Feb 22 22:21 etc/mysql-mmm/mmm_agent.conf
4 -rw-r----- 1 root root 789 Feb 22 23:20 etc/mysql-mmm/mmm_common.conf
root@master1:/etc/mysql-mmm#

mmm_comm.conf配置文件

所有5个节点中的/etc/mysql-mmm/mmm_common.conf
配置文件都修改为如下所示的内容。


root@master1:/etc/mysql-mmm# cat mmm_common.conf

active_master_role writer


<host default>
# 网卡的名称,各个主机上面网络设备的名称
cluster_interface eth0

pid_path /var/run/mmm_agentd.pid
bin_path /usr/lib/mysql-mmm/

# 主从复制用户名和密码
replication_user repl_user
replication_password repl_user

# MMM服务使用的anget用户名和密码
agent_user mmm_agent
agent_password mmm_agent

</host>

# master1的配置信息
<host master1>
ip 172.20.0.11
mode master
peer master2
</host>

# master2的配置信息
<host master2>
ip 172.20.0.21
mode master
peer master1
</host>

# slave1的配置信息
<host slave1>
ip 172.20.0.12
mode slave
</host>

# slave2的配置信息
<host slave2>
ip 172.20.0.22
mode slave
</host>

# 写虚拟IP的配置信息,指定可写的主机名称
<role writer>
hosts master1, master2
ips 172.20.0.100
mode exclusive
</role>

# 读虚拟IP的配置信息,指定可以提供读服务的主机名称。下面的VIP和主键名称不一定是一一对应的,VIP是随机分布到各个可读节点的。
# 如果提供多个VIP,有可能一个节点被分配多个VIP,这样也是支持的。
<role reader>
hosts master1, master2, slave1, slave2
ips 172.20.0.111, 172.20.0.211, 172.20.0.122, 172.20.0.222
mode balanced
</role>

root@master1:/etc/mysql-mmm#

上面的role reader
中配置的可读节点,可以根据自己的需求来配置,这里我把master1, master2, slave1, slave2
都作为可读的节点,当然可以把主节点master1
去掉,只配置master2, slave1, slave2
三个节点。这里的ips
也是我们指定的VIP的值,我们可以配置多个VIP,最好是VIP的个数和上面的host的数目一致,表示每一个提供读的节点分配一个VIP。

mmm_agent.conf配置文件

每一个节点上面的/etc/mysql-mmm/mmm_agent.conf
配置文件中,都在第2行中,修改一下主机名称。下面给出master1节点的配置如下:


root@master1:/etc/mysql-mmm# cat mmm_agent.conf
include mmm_common.conf
this master1
root@master1:/etc/mysql-mmm#

其他master2、slave1、slave2各个节点也需要作出对应的修改。只要把master1改为对应的主机名称即可。

mmm_mon.conf配置文件

在monitor节点上,修改/etc/mysql-mmm/mmm_mon.conf
配置文件,修改内容如下所示,其他四个节点不需要对这个文件做修改。


root@monitor:/etc/mysql-mmm# cat mmm_mon.conf
include mmm_common.conf

<monitor>
ip 127.0.0.1
pid_path /var/run/mmm_mond.pid
bin_path /usr/lib/mysql-mmm/
status_path /var/lib/misc/mmm_mond.status
ping_ips 172.20.0.1, 172.20.0.11, 172.20.0.21, 172.20.0.12, 172.20.0.22 # 网关IP地址,和各个节点的物理IP地址,用于监控各个节点的状态是否可用
</monitor>

# MMM服务使用MySQL中的monitor用户名称和密码
<host default>
monitor_user mmm_monitor
monitor_password mmm_monitor
</host>

# debug值为0非debug模式,为1的时候表示debug模式,debug模式下,会在/var/log/mysql-mmm/mmm_mond.log日志文件中生成更多日志信息。
debug 0
root@monitor:/etc/mysql-mmm#


启动MMM服务

客户端agent服务相关命令如下,客户端agent启动后日志存放在/var/log/mysql-mmm/mmm_agentd.log
文件中。


/etc/init.d/mysql-mmm-agent start
/etc/init.d/mysql-mmm-agent status
/etc/init.d/mysql-mmm-agent stop
/etc/init.d/mysql-mmm-agent restart

监控端monitor服务相关命令如下,监控端monitor启动后日志存放在/var/log/mysql-mmm/mmm_mond.log
文件中。


/etc/init.d/mysql-mmm-monitor start
/etc/init.d/mysql-mmm-monitor status
/etc/init.d/mysql-mmm-monitor stop
/etc/init.d/mysql-mmm-monitor restart

MMM监控状态有一个管理命令mmm_control
,它的使用帮助如下所示:


root@monitor:/# mmm_control --help
Invalid command '--help'

Valid commands are:
help - show this message
ping - ping monitor
show - show status
checks [<host>|all [<check>|all]] - show checks status
set_online <host> - set host <host> online
set_offline <host> - set host <host> offline
mode - print current mode.
set_active - switch into active mode.
set_manual - switch into manual mode.
set_passive - switch into passive mode.
move_role [--force] <role> <host> - move exclusive role <role> to host <host>
(Only use --force if you know what you are doing!)
set_ip <ip> <host> - set role with ip <ip> to host <host>

root@monitor:/#

常用的维护节点状态的命令如下:


mmm_control show
mmm_control checks all
mmm_control set_online master1
mmm_control set_online master2
mmm_control set_online slave1
mmm_control set_online slave2

下面分别在四个MySQL节点上执行如下命令启动并查看MMM的客户端服务

  • master1主节点上,启动和查看MMM的客户端服务如下:


root@master1:/etc/mysql-mmm# 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@master1:/etc/mysql-mmm# etc/init.d/mysql-mmm-agent status
Daemon bin: '/usr/sbin/mmm_agentd'
Daemon pid: '/var/run/mmm_agentd.pid'
Checking MMM Agent process: running.
root@master1:/etc/mysql-mmm#
  • master2主节点上,启动和查看MMM的客户端服务如下:


root@master2:/etc/mysql-mmm# 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@master2:/etc/mysql-mmm# etc/init.d/mysql-mmm-agent status
Daemon bin: '/usr/sbin/mmm_agentd'
Daemon pid: '/var/run/mmm_agentd.pid'
Checking MMM Agent process: running.
root@master2:/etc/mysql-mmm#
  • slave1主节点上,启动和查看MMM的客户端服务如下:


root@slave1:/etc/mysql-mmm# 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@slave1:/etc/mysql-mmm# etc/init.d/mysql-mmm-agent status
Daemon bin: '/usr/sbin/mmm_agentd'
Daemon pid: '/var/run/mmm_agentd.pid'
Checking MMM Agent process: running.
root@slave1:/etc/mysql-mmm#
  • slave2主节点上,启动MMM的客户端服务如下:


root@slave2:/etc/mysql-mmm# 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@slave2:/etc/mysql-mmm# etc/init.d/mysql-mmm-agent status
Daemon bin: '/usr/sbin/mmm_agentd'
Daemon pid: '/var/run/mmm_agentd.pid'
Checking MMM Agent process: running.
root@slave2:/etc/mysql-mmm#

下面在监控节点上执行如下命令启动并查看MMM的监控服务

  • monitor节点上,启动和查看MMM的监控端服务如下:


root@monitor:/etc/mysql-mmm# etc/init.d/mysql-mmm-monitor start
Daemon bin: '/usr/sbin/mmm_mond'
Daemon pid: '/var/run/mmm_mond.pid'
Starting MMM Monitor daemon: Ok

root@monitor:/etc/mysql-mmm# etc/init.d/mysql-mmm-monitor status
Daemon bin: '/usr/sbin/mmm_mond'
Daemon pid: '/var/run/mmm_mond.pid'
Checking MMM Monitor process: running.
root@monitor:/etc/mysql-mmm#
  • 在monitor节点,查看监控的状态:


root@monitor:/etc/mysql-mmm# mmm_control show
master1(172.20.0.11) master/AWAITING_RECOVERY. Roles:
master2(172.20.0.21) master/AWAITING_RECOVERY. Roles:
slave1(172.20.0.12) slave/AWAITING_RECOVERY. Roles:
slave2(172.20.0.22) slave/AWAITING_RECOVERY. Roles:

root@monitor:/etc/mysql-mmm# mmm_control set_online master1;
OK: State of 'master1' changed to ONLINE. Now you can wait some time and check its new roles!
root@monitor:/etc/mysql-mmm# mmm_control set_online master2
OK: State of 'master2' changed to ONLINE. Now you can wait some time and check its new roles!
root@monitor:/etc/mysql-mmm# mmm_control set_online slave1
OK: State of 'slave1' changed to ONLINE. Now you can wait some time and check its new roles!
root@monitor:/etc/mysql-mmm# mmm_control set_online slave2
OK: State of 'slave2' changed to ONLINE. Now you can wait some time and check its new roles!
root@monitor:/etc/mysql-mmm# mmm_control show
master1(172.20.0.11) master/ONLINE. Roles: reader(172.20.0.111), writer(172.20.0.100)
master2(172.20.0.21) master/ONLINE. Roles: reader(172.20.0.211)
slave1(172.20.0.12) slave/ONLINE. Roles: reader(172.20.0.122)
slave2(172.20.0.22) slave/ONLINE. Roles: reader(172.20.0.222)

root@monitor:/etc/mysql-mmm#

问题排查1:monitor服务不能正常启动?

当在monitor节点启动监控服务后,监控服务一会就异常退出了。原因是在使用docker启动集群节点的时候没有使用--cap-add NET_ADMIN
参数,没有这个参数就没有办法在容器只用使用虚拟VIP的功能。在删除容器后,增加参数重新运行后,才运行起来。

后来,又发现monitor节点启监控服务器仍然失败,查看日志/var/log/mysql-mmm/mmm_mond.log
,如下所示:


root@monitor:/etc/mysql-mmm# tail -f var/log/mysql-mmm/mmm_mond.log
2021/02/22 23:26:27 INFO Waiting for network connection...
2021/02/22 23:26:27 INFO Spawning checker 'ping_ip'...
2021/02/22 23:26:27 INFO Shutting down checker 'ping_ip'...
2021/02/22 23:26:27 INFO Network connection is available.
2021/02/22 23:26:27 FATAL Child exited with exitcode 255, restarting after 10 second sleep

修改/etc/mysql-mmm/mmm_mon.conf
配置文件中的debug
的值为1
,表示以debug
的模式运行monitor服务,此时我们再重新启动monitor服务,查看输出的详细错误日志如下:


root@monitor:/etc/mysql-mmm# etc/init.d/mysql-mmm-monitor start
Daemon bin: '/usr/sbin/mmm_mond'
Daemon pid: '/var/run/mmm_mond.pid'
Starting MMM Monitor daemon: 2021/02/22 23:30:17 INFO STARTING...
2021/02/22 23:30:17 DEBUG Created pid file '/var/run/mmm_mond.pid' with pid 5330
2021/02/22 23:30:17 INFO Waiting for network connection...
2021/02/22 23:30:17 INFO Spawning checker 'ping_ip'...
2021/02/22 23:30:17 DEBUG IP '172.20.0.1' is reachable: OK
2021/02/22 23:30:17 INFO Shutting down checker 'ping_ip'...
2021/02/22 23:30:17 INFO Network connection is available.
Use of uninitialized value $old_state in string ne at usr/share/perl5/MMM/Monitor/Agent.pm line 42.
2021/02/22 23:30:17 FATAL Child exited with exitcode 255, restarting after 10 second sleep

于是去修改了/usr/share/perl5/MMM/Monitor/Agent.pm
文件,在第41行增加如下内容,保存退出,重新启动monitor服务。


if (! defined($old_state)) { $old_state = 'certinally not new_state'; }

然后再次重启monitor服务,启动成功。然后把/etc/mysql-mmm/mmm_mon.conf
配置文件中的debug
的值再次修改为0
,关闭debug
模式再次重启monitor服务。此时查看monitor服务的日志内容如下:


root@monitor:/# tail -f var/log/mysql-mmm/mmm_mond.log
2021/02/22 23:42:43 INFO Check 'rep_backlog' on 'slave1' is ok!
2021/02/22 23:42:43 INFO Check 'rep_backlog' on 'master2' is ok!
2021/02/22 23:42:43 INFO Check 'rep_threads' on 'master1' is ok!
2021/02/22 23:42:43 INFO Check 'rep_threads' on 'slave2' is ok!
2021/02/22 23:42:43 INFO Check 'rep_threads' on 'slave1' is ok!
2021/02/22 23:42:43 INFO Check 'rep_threads' on 'master2' is ok!
2021/02/22 23:42:43 INFO Check 'ping' on 'master1' is ok!
2021/02/22 23:42:43 INFO Check 'ping' on 'slave2' is ok!
2021/02/22 23:42:43 INFO Check 'ping' on 'slave1' is ok!
2021/02/22 23:42:43 INFO Check 'ping' on 'master2' is ok!

问题排查2:虚拟IP不能再各个节点生成?

启动MMM后,发现不能通过VIP访问MySQL数据库,去各个节点使用ifconfig -a
或者ip addr
命令查看发现没有对应的VIP生成。查看了各个节点MMM agent服务的日志文件/var/log/mysql-mmm/mmm_agent.log
,发现如下错误信息:


root@master1:/# tail -f var/log/mysql-mmm/mmm_agentd.log
2021/02/23 17:16:19 FATAL Couldn't configure IP '172.20.0.111' on interface 'eth0': undef
2021/02/23 17:16:19 FATAL Couldn'
t allow writes: undef
2021/02/23 17:16:22 FATAL Couldn't configure IP '172.20.0.111' on interface 'eth0': undef
2021/02/23 17:16:22 FATAL Couldn'
t allow writes: undef

经过排查发现是在设置VIP的时候失败,设置客户端VIP的脚本如下:


/usr/lib/mysql-mmm/agent/configure_ip

执行上面的脚本发现如下错误:


提示我们,需要在perl中安装arp.pm包。安装的时候,为了提高速度,我们修改一下perl安装模块的时候使用的镜像源。

修改perl安装包的时候使用的镜像源,参考如下方式修改:


root@master1:/# perl -MCPAN -e shell
cpan[5]> o conf urllist
urllist
0 [http://www.cpan.org/]
Type 'o conf' to view all configuration items


cpan[6]> o conf urllist push http://mirrors.aliyun.com/CPAN/
Please use 'o conf commit' to make the config permanent!


cpan[7]> o conf commit
commit: wrote '/root/.cpan/CPAN/MyConfig.pm'

cpan[8]> o conf urllist
urllist
0 [http://www.cpan.org/]
1 [http://mirrors.aliyun.com/CPAN/]
Type 'o conf' to view all configuration items


cpan[9]> install Net::ARP

cpan[10]>

其中各个命令的含义如下:

  • o conf urllist
    :查看的当前的镜像源

  • o conf urllist push http://mirrors.aliyun.com/CPAN/
    :添加阿里的perl镜像源

  • o conf commit
    :提交对镜像源的修改

  • install Net::ARP
    :安装arp.pm包。

经过上面的安装方式,发现安装失败。于是下载源码自己编译安装这个包。参考如下命令顺序来编译安装。


# 下载源码文件
wget https://cpan.metacpan.org/authors/id/C/CR/CRAZYDJ/Net-ARP-1.0.11.tgz

# 解压下载后的文件
tar -zxvf Net-ARP-1.0.11.tgz

# 进入下载目录
cd Net-ARP-1.0.11

# 执行编译
perl Makefile.PL

# 执行安装
make install

上面安装Net-ARP包的操作,需要在除了monitor节点的四个节点上都执行安装一下。

最后所有节点的IP地址和VIP地址如下所示:

验证VIP访问数据库

当我们的MMM客户段服务在四个MySQL数据库实例中启动,并且MMM监控服务在monitor节点启动之后。我们在monitor节点上面尝试使用各个VIP看能否正常连接到MySQL数据库。验证的结果如下:


root@monitor:/etc/mysql-mmm#
root@monitor:/etc/mysql-mmm# mmm_control show
master1(172.20.0.11) master/ONLINE. Roles: reader(172.20.0.111), writer(172.20.0.100)
master2(172.20.0.21) master/ONLINE. Roles: reader(172.20.0.122)
slave1(172.20.0.12) slave/ONLINE. Roles: reader(172.20.0.211)
slave2(172.20.0.22) slave/ONLINE. Roles: reader(172.20.0.222)

root@monitor:/etc/mysql-mmm# mysql -uroot -proot -h172.20.0.100 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+---------------+
| @@hostname |
+---------------+
| master1.mysql |
+---------------+
root@monitor:/etc/mysql-mmm# mysql -uroot -proot -h172.20.0.111 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+---------------+
| @@hostname |
+---------------+
| master1.mysql |
+---------------+
root@monitor:/etc/mysql-mmm# mysql -uroot -proot -h172.20.0.122 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+---------------+
| @@hostname |
+---------------+
| master2.mysql |
+---------------+
root@monitor:/etc/mysql-mmm# mysql -uroot -proot -h172.20.0.211 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------+
| @@hostname |
+--------------+
| slave1.mysql |
+--------------+
root@monitor:/etc/mysql-mmm# mysql -uroot -proot -h172.20.0.222 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------+
| @@hostname |
+--------------+
| slave2.mysql |
+--------------+
root@monitor:/etc/mysql-mmm#


验证MMM的高可用

我们把master1节点上面的MySQL服务停止掉,来验证一下是否会把主从同步的源头从master1切换为master2上面,并且我们在monitor节点上,仍然可以通过writer vip 去连接到MySQL上。

停止master1节点上面的MySQL服务,在master1节点上,执行如下命令:


root@master1:~/Net-ARP-1.0.11# etc/init.d/mysql stop
............
[info] MySQL Community Server 5.7.31 is stopped.
root@master1:~/Net-ARP-1.0.11# %
➜ ~

接着,我们在monitor节点上,查看MMM监控各个节点服务的状态,发现master1节点以及下线了,并且我们的writer ip,已经从原先的master1节点迁移到master2节点上了。如下所示:


root@monitor:/etc/mysql-mmm# mmm_control show
# Warning: agent on host master1 is not reachable
master1(172.20.0.11) master/HARD_OFFLINE. Roles:
master2(172.20.0.21) master/ONLINE. Roles: reader(172.20.0.122), writer(172.20.0.100)
slave1(172.20.0.12) slave/ONLINE. Roles: reader(172.20.0.111), reader(172.20.0.211)
slave2(172.20.0.22) slave/ONLINE. Roles: reader(172.20.0.222)

root@monitor:/etc/mysql-mmm# mmm_control checks all
slave2 ping [last change: 2021/02/23 16:19:44] OK
slave2 mysql [last change: 2021/02/23 16:19:44] OK
slave2 rep_threads [last change: 2021/02/23 16:19:44] OK
slave2 rep_backlog [last change: 2021/02/23 16:19:44] OK: Backlog is null
master1 ping [last change: 2021/02/23 18:44:57] ERROR: Could not ping 172.20.0.11
master1 mysql [last change: 2021/02/23 18:44:40] ERROR: Connect error (host = 172.20.0.11:3306, user = mmm_monitor)! Can't connect to MySQL server on '172.20.0.11' (115)
master1 rep_threads [last change: 2021/02/23 16:19:44] OK
master1 rep_backlog [last change: 2021/02/23 16:19:44] OK: Backlog is null
slave1 ping [last change: 2021/02/23 16:19:44] OK
slave1 mysql [last change: 2021/02/23 16:19:44] OK
slave1 rep_threads [last change: 2021/02/23 16:19:44] OK
slave1 rep_backlog [last change: 2021/02/23 16:19:44] OK: Backlog is null
master2 ping [last change: 2021/02/23 16:19:44] OK
master2 mysql [last change: 2021/02/23 16:19:44] OK
master2 rep_threads [last change: 2021/02/23 16:19:44] OK
master2 rep_backlog [last change: 2021/02/23 16:19:44] OK: Backlog is null

root@monitor:/etc/mysql-mmm#

此时我们看到master2上面的IP地址信息如下,writer vip 172.20.0.100
已经迁移到了master2主机上了。


root@master2:~/Net-ARP-1.0.11# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1000
link/tunnel6 :: brd ::
12: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:14:00:15 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.20.0.21/24 brd 172.20.0.255 scope global eth0
valid_lft forever preferred_lft forever
inet 172.20.0.122/32 scope global eth0
valid_lft forever preferred_lft forever
inet 172.20.0.100/32 scope global eth0
valid_lft forever preferred_lft forever
root@master2:~/Net-ARP-1.0.11#

在monitor节点上,查看MMM的监控服务器的日志信息如下:


root@monitor:/etc/mysql-mmm# tail -20 /var/log/mysql-mmm/mmm_mond.log
2021/02/23 16:19:49 INFO Check 'mysql' on 'slave2' is ok!
2021/02/23 16:19:49 INFO Check 'mysql' on 'master1' is ok!
2021/02/23 16:19:49 INFO Check 'mysql' on 'slave1' is ok!
2021/02/23 16:19:49 INFO Check 'mysql' on 'master2' is ok!
2021/02/23 18:44:30 WARN Check 'rep_threads' on 'master1' is in unknown state! Message: UNKNOWN: Connect error (host = 172.20.0.11:3306, user = mmm_monitor)! Can't connect to MySQL server on '172.20.0.11' (115)
2021/02/23 18:44:30 WARN Check '
rep_backlog' on 'master1' is in unknown state! Message: UNKNOWN: Connect error (host = 172.20.0.11:3306, user = mmm_monitor)! Can't connect to MySQL server on '172.20.0.11' (115)
2021/02/23 18:44:40 ERROR Check 'mysql' on 'master1' has failed for 10 seconds! Message: ERROR: Connect error (host = 172.20.0.11:3306, user = mmm_monitor)! Can't connect to MySQL server on '172.20.0.11' (115)
2021/02/23 18:44:41 FATAL State of host '
master1' changed from ONLINE to HARD_OFFLINE (ping: OK, mysql: not OK)
2021/02/23 18:44:41 INFO Removing all roles from host '
master1':
2021/02/23 18:44:41 INFO Removed role '
reader(172.20.0.111)' from host 'master1'
2021/02/23 18:44:41 INFO Removed role '
writer(172.20.0.100)' from host 'master1'
2021/02/23 18:44:41 FATAL Can'
t reach agent on host 'master1'
2021/02/23 18:44:41 ERROR Can't send offline status notification to 'master1' - killing it!
2021/02/23 18:44:41 FATAL Could not kill host '
master1' - there may be some duplicate ips now! (There's no binary configured for killing hosts.)
2021/02/23 18:44:41 INFO Orphaned role 'writer(172.20.0.100)' has been assigned to 'master2'
2021/02/23 18:44:41 INFO Orphaned role 'reader(172.20.0.111)' has been assigned to 'slave1'
2021/02/23 18:44:57 ERROR Check 'ping' on 'master1' has failed for 11 seconds! Message: ERROR: Could not ping 172.20.0.11
root@monitor:/etc/mysql-mmm#

我们在monitor节点上,再次尝试连接到writer vip 172.20.0.100
上面,发现已经连接到master2上面了,如下所示:


root@monitor:/etc/mysql-mmm# mysql -uroot -proot -h172.20.0.100 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+---------------+
| @@hostname |
+---------------+
| master2.mysql |
+---------------+
root@monitor:/etc/mysql-mmm#

下面我们看一下slave1和slave2节点主从同步的配置是否,自动切换到master2节点上。分别登录到slave1和slave2节点上执行如下SQL命令:


select * from mysql.slave_master_info\G

查看结果如下:

通过下面的截图,可以看出在新的主节点上面执行的插入数据,是可以正常的同步到两个slave从节点上。

下面我们把master1节点重新启动,让MySQL数据库服务恢复。


# 启动master1容器
docker start mysql-ha-mmm-master1

# 进入master1容器
docker exec -it mysql-ha-mmm-master1 /bin/bash

# 启动master1上面的MMM的agent服务
/etc/init.d/mysql-mmm-agent start

进入monitor节点上,查看各个节点的状态:


# 在master1启动后,在monitor节点查看各个节点状态的时候,发现已经不再有"Warning: agent on host master1 is not reachable"的警告了。
root@monitor:/etc/mysql-mmm# mmm_control show
master1(172.20.0.11) master/AWAITING_RECOVERY. Roles:
master2(172.20.0.21) master/ONLINE. Roles: reader(172.20.0.122), writer(172.20.0.100)
slave1(172.20.0.12) slave/ONLINE. Roles: reader(172.20.0.111), reader(172.20.0.211)
slave2(172.20.0.22) slave/ONLINE. Roles: reader(172.20.0.222)

# 设置master1节点上线
root@monitor:/etc/mysql-mmm# mmm_control set_online master1
OK: State of 'master1' changed to ONLINE. Now you can wait some time and check its new roles!

# 再次查看各个节点的状态,发现master1已经上线了。但是它此时成立备用的主节点了,并且给他分配了一个reader VIP地址。
root@monitor:/etc/mysql-mmm# mmm_control show
master1(172.20.0.11) master/ONLINE. Roles: reader(172.20.0.211)
master2(172.20.0.21) master/ONLINE. Roles: reader(172.20.0.122), writer(172.20.0.100)
slave1(172.20.0.12) slave/ONLINE. Roles: reader(172.20.0.111)
slave2(172.20.0.22) slave/ONLINE. Roles: reader(172.20.0.222)

root@monitor:/etc/mysql-mmm#

MMM高可用验证结果小结:

  • master1节点宕机之后,master2节点会接管master1的所有任务。

  • writer VIP会自动从master1上面转移到master2上面。

  • 两个从节点slave1和slave2会自动的把主从同步的链路从master1切换到master2上面。

  • 如果在master1上除了提供写的服务,还提供可读的服务,也就是为其分配了reader VIP,那么当master1宕机后,这个reader VIP不会丢失,会被迁移到其他任意一个节点上。

  • 在master1重启后,在monitor节点通过命令mmm_control set_online master1
    设置master1节点上线后,master1节点不会接管现有master2的角色,而是作为一个备用主节点集群中提供服务。此时,只有master2节点宕机后,master1节点才会重新成为主节点的角色。

  • 随着master1和master2节点的宕机和恢复,提供写的VIP会在两个节点上来回切换。

对于这个5个服务器组成的高可用集群,如果我们担心MMM的monitor节点是单节点,不是高可用的monitor服务,我们可以在选择一台服务器,在上面部署另外一个monitor服务,使用keepalive组件,保证两个monitor服务至少有一个可用。这样就更加完美了。

总结

上面就是关于MySQL高可用架构-MMM架构的搭建过程。期间涉及到了MySQL主从同步集群的搭建,我们搭建了一个双主双从的集群,然后基于这个集群,又在每一个节点上面编译安装了MMM插件,在每一个节点上启动了MMM的agent服务。还选择了一台服务器,安装MMM监控服务。

希望对你有所帮助,后续会分享其他高可用架构搭建的方式。


微信搜索“coder-home”或扫一扫下面的二维码,关注公众号,

第一时间了解更多干货分享,还有各类视频教程资源。扫描它,带走我


文章转载自程序猿集锦,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论