MySQL高可用搭建方案之(MMM)(一)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: MySQL高可用搭建方案之(MMM)

有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top

注意:这篇转载文章,非原创

首发博客地址

原文地址


前言

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只是:「M」ulti-「M」aster Replication 「M」anager 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

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



相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
3月前
|
存储 关系型数据库 MySQL
Mysql高可用|索引|事务 | 调优
Mysql高可用|索引|事务 | 调优
|
4月前
|
SQL 容灾 关系型数据库
rds容灾与高可用
rds容灾与高可用
30 4
|
4月前
|
关系型数据库 MySQL
电子好书发您分享《MySQL MGR 8.0高可用实战》
电子好书发您分享《MySQL MGR 8.0高可用实战》 电子好书发您分享《MySQL MGR 8.0高可用实战》
92 1
|
3月前
|
SQL 存储 关系型数据库
MySQL索引(二)索引优化方案有哪些
MySQL索引(二)索引优化方案有哪些
52 0
|
21天前
|
存储 SQL 分布式计算
搭建Mysql Cluster集群实现高可用
搭建Mysql Cluster集群实现高可用
18 0
|
21天前
|
关系型数据库 MySQL Linux
centos7下 Mysql+Keepalived 双主热备高可用图文配置详解
centos7下 Mysql+Keepalived 双主热备高可用图文配置详解
21 0
|
2月前
|
canal 消息中间件 关系型数据库
【分布式技术专题】「分布式技术架构」MySQL数据同步到Elasticsearch之N种方案解析,实现高效数据同步
【分布式技术专题】「分布式技术架构」MySQL数据同步到Elasticsearch之N种方案解析,实现高效数据同步
90 0
|
2月前
|
SQL 关系型数据库 MySQL
【MySQL技术之旅】(7)总结和盘点优化方案系列之常用SQL的优化
【MySQL技术之旅】(7)总结和盘点优化方案系列之常用SQL的优化
71 1
|
2月前
|
缓存 关系型数据库 MySQL
史上最全MySQL 大表优化方案(长文)
史上最全MySQL 大表优化方案(长文)
538 0
|
3月前
|
监控 容灾 关系型数据库
rds容灾与高可用
rds容灾与高可用
56 6