MySQL MMM架构
简介
MMM 是一套支持双主故障切换以及双主日常管理的第三方软件。MMM 由 Perl 开发,用来管理和监控双主复制,虽然是双主架构,但是业务上同一时间只允许一个节点进行写入操作。
MMM 包含两类角色:writer和reader,分别对应读写节点和只读节点。使用 MMM 管理双主节点的情况下,当writer节点出现宕机(假设是 master1),程序会自动移除该节点上的读写VIP,切换到Master2上,并自动设置Master2为read_only = 0,同时,所有Slave节点会指向Master2。
除了管理双主节点,MMM也会管理Slave节点,在出现宕机、复制延迟或复制错误的情况下,MMM会移除该节点的VIP,直到节点恢复正常。
组件
MMM由两类程序组成:
- monitor进程,监控集群内数据库的状态,在出现异常时发布切换命令,一般和数据库分开部署。
- agent进程,它是运行在每个 MySQL 服务器上的代理进程,monitor命令的执行者,完成监控的探针工作和具体服务设置。例如:设置VIP、切换VIP、指向新同步节点。
MMM架构如图所示。
?
切换流程
以上述MMM架构为例,描述一下故障转移的流程,现在假设 Master1 宕机:
- Monitor检测到Master1连接失败。
- Monitor发送set_offline指令到Master1的Agent。
- Master1 Agent如果存活,则下线写VIP,尝试把Master1设置为read_only=1。
- Moniotr发送set_online指令到Master2。
- Master2 Agent接收到指令,执行select master_pos_wait() 等待同步完毕。
- Master2 Agent上线写VIP,把Master2 节点设为read_only=0。
- Monitor发送更改同步对象的指令到各个Slave节点的Agent。
- 各个Slave节点向新Master同步数据。
从整个流程可以看到,如果主节点出现故障,MMM会自动实现切换,不需要人工干预,同时我们也能看出一些问题,就是数据库挂掉后,只是做了切换,不会主动补齐丢失的数据,所以MMM会有数据不一致性的风险。
?
MMM安装部署
MMM主要功能由下面三个脚本提供:
mmm_mond,负责所有的监控工作的监控守护进程,决定节点的移除(mmm_mond进程定时心跳检测,如果检测到write节点失败,则将write VIP浮动到另外一台 master。)等等。
mmm_agentd,运行在MySQL服务器上的代理守护进程,通过简单远程服务集提供给监控节点。
mmm_control,通过命令行管理mmm_mond进程,在整个监管过程中,需要在MySQL中添加相关授权用户,授权的用户包括一个mmm_monitor用户和一个mmm_agent用户,如果想使用MMM的备份工具,则还要添加一个mmm_tools用户。
环境说明
?
?
双主一从环境准备
操作前已经准备好了一套双主一从架构的数据库,各节点的my.cnf配置文件如下所示。
MASTER1:
[ backup]# more /etc/my.cnf [mysqld] port = 3306 socket = /data/mysql/mysql.sock basedir = /usr/local/mysql datadir = /data/mysql user = mysql symbolic_links = 0 character_set_server = latin1 autocommit = off transaction_isolation = READ-COMMITTED ? server-id = 1 ? ## Master setting log_bin = /data/mysql/logs/binlog log_bin_index = /data/mysql/logs/binlog.index ? auto_increment_offset = 1 auto_increment_increment = 2 ? ## Slave setting relay_log = /data/mysql/logs/relay-log relay_log_index = /data/mysql/logs/relay-log.index master_info_repository=TABLE relay_log_info_repository=TABLE log_slave_updates = on relay_log_recovery = on ? [mysqld_safe] log_error = /var/log/mysqld.log ? [client] socket = /data/mysql/mysql.sock default_character_set = latin1 prompt="\\\\h [\\d]>" [ backup]#? |
?
Master2:
[ backup]# more /etc/my.cnf [mysqld] port = 3306 socket = /data/mysql/mysql.sock basedir = /usr/local/mysql datadir = /data/mysql user = mysql symbolic_links = 0 character_set_server = latin1 autocommit = off transaction_isolation = READ-COMMITTED ? server-id = 2 ? ## Master setting log_bin = /data/mysql/logs/binlog log_bin_index = /data/mysql/logs/binlog.index ? auto_increment_offset = 2 auto_increment_increment = 2 ? ## Slave setting relay_log = /data/mysql/logs/relay-log relay_log_index = /data/mysql/logs/relay-log.index master_info_repository=TABLE relay_log_info_repository=TABLE log_slave_updates = on relay_log_recovery = on ? [mysqld_safe] log_error = /var/log/mysqld.log ? [client] socket = /data/mysql/mysql.sock default_character_set = latin1 prompt="\\\\h [\\d]>" [ backup]#? |
?
Slave:
[ mysql]# more /etc/my.cnf [mysqld] port = 3306 socket = /data/mysql/mysql.sock basedir = /usr/local/mysql datadir = /data/mysql user = mysql symbolic_links = 0 character_set_server = latin1 autocommit = off transaction_isolation = READ-COMMITTED ? server-id = 3 ? ## Master setting log_bin = /data/mysql/logs/binlog log_bin_index = /data/mysql/logs/binlog.index ? ? ## Slave setting relay_log = /data/mysql/logs/relay-log relay_log_index = /data/mysql/logs/relay-log.index master_info_repository=TABLE relay_log_info_repository=TABLE log_slave_updates = on relay_log_recovery = on ? ? [mysqld_safe] log_error = /var/log/mysqld.log ? [client] socket = /data/mysql/mysql.sock default_character_set = latin1 prompt="\\\\h [\\d]>" [ mysql]# |
?
yum 安装
如果服务器能连网或者有合适YUM源,可以直接执行以下命令安装MMM软件包。
(1)、增加YUM源(如果默认有YUM源,则这一步可以忽略)。
?
(2)、在agent节点上安装mysql-mmm-agent。
# yum install -y mysql-mmm-agent |
?
(3)、在monitor节点上安装mysql-mmm-monitor。
# yum install -y mysql-mmm-monitor |
?
mysql-mmm-agent安装后的主要拓扑结构如下所示。
文件或目录 | 说明 |
/etc/init.d/mysql-mmm-agent | 启动服务程序,控制agent随操作系统自动启动,chkconfig ….. on |
/etc/mysql-mmm | Agent的配置文件目录,内有mmm_agent.conf和mmm_common.conf |
/usr/libexec/mysql-mmm/agent | Agent调用的脚本目录 |
/usr/sbin/mmm_agentd | Agent主程序目录 |
/var/log/mysql-mmm | Agent的日志目录 |
?
mysql-mmm-monitor安装后的主要拓扑结构如下所示。
文件或目录 | 说明 |
/etc/init.d/mysql-mmm-monitor | 启动服务程序,控制monitor随操作系统自动启动,chkconfig ….. on |
/etc/mysql-mmm | Monitor的配置文件目录,内有mmm_mon.conf和mmm_common.conf、mmm_mon_log.conf |
/usr/libexec/mysql-mmm/monitor | Monitor调用的脚本目录 |
/usr/sbin/mmm_control | Monitor的控制程序 |
/usr/sbin/mmm_mond | monitor主程序目录 |
/var/log/mysql-mmm | Monitor的日志目录 |
?
新建用户
在主节点中执行下列建立 MMM 用户的命令:
create user ‘mmm_monitor‘@‘192.168.56.%‘ identified by ‘mmm_monitor‘; create user ‘mmm_agent‘@‘192.168.56.%‘ identified by ‘mmm_agent‘; grant replication client on *.* to ‘mmm_monitor‘@‘192.168.56.%‘; grant super, replication client, process on *.* to ‘mmm_agent‘@‘192.168.56.%‘; flush privileges;? |
?
配置 MMM
配置mmm_common.conf文件
MMM 有3个配置文件,分别是:mmm_agent.conf、mmm_common.conf、mmm_mon.conf,在/etc/mysql-mmm目录下。
如果区分集群,也就是说一台服务器跑多个MMM,那么配置文件可以这样命名 mmm_agent_cluster.conf、mmm_common_cluster.conf、mmm_mon_cluster.conf。其中 cluster 表示集群名称:
mmm_common.conf,通用配置文件,在所有MMM节点都需要。
mmm_agent.conf,agent配置文件,在MMM Agent节点需要。
mmm_mon.conf,monitor配置文件,在MMM Monitor节点需要。
?
(1)、修改/etc/mysql-mmm/mmm_common.conf文件,内容如下所示。
[ mysql-mmm]# cat mmm_common.conf active_master_role writer ? <host default> cluster_interface eth0 pid_path /var/run/mysql-mmm/mmm_agentd.pid bin_path /usr/libexec/mysql-mmm/ replication_user repuser replication_password welcome1 agent_user mmm_agent agent_password mmm_agent </host> ? <host mysqldb01> ip 192.168.56.131 mode master peer mysqldb02 </host> ? <host mysqldb02> ip 192.168.56.132 mode master peer mysqldb01 </host> ? <host mysqldb03> ip 192.168.56.133 mode slave </host> ? <role writer> hosts mysqldb01, mysqldb02 ips 192.168.56.191 mode exclusive </role> ? <role reader> hosts mysqldb01, mysqldb02 ips 192.168.56.192, 192.168.56.193 mode balanced </role> [ mysql-mmm]# |
其中replication_user用于检查复制的用户,agent_user为agent的用户,mode标明是否为主或者备选主,或者从库。mode exclusive主为独占模式,同一时刻只能有一个主,<role write>中hosts表示目前的主库和备选主的真实主机ip或者主机名,ips为对外提供的虚拟机ip地址,<role readr>中hosts代表从库真实的ip和主机名,ips代表从库的虚拟ip地址。
?
将节点1的/etc/mysql-mmm/mmm_common.conf文件复制到其他的所有节点,包括monitor节点,因为这里面的内容是完全相同的。
[ mysql-mmm]# scp mmm_common.conf mysqldb02:/etc/mysql-mmm/ [ mysql-mmm]# scp mmm_common.conf mysqldb03:/etc/mysql-mmm/ [ mysql-mmm]# scp mmm_common.conf mysqldb05:/etc/mysql-mmm/? |
?
配置agent节点的mmm_agent文件
分别在mysqldb01、mysqldb02、mysqldb03这三台主机的/etc/mysql-mmm目录中配置mmm_agent.conf文件,分别用不同的字符标识,注意这三台机器的this 变量这块,比如本环境中,mysqldb01主机要配置this mysqldb01,mysqldb02主机要配置为this mysqldb02,而mysqldb03主机要配置为this mysqldb03。
[ mysql-mmm]# more 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 mysqldb01 [ mysql-mmm]#? |
?
配置monitor节点的mmm_mon文件
monitor主机的/etc/mysql-mmm目录中配置mmm_mon.conf文件,内容如下:
[ mysql-mmm]# cat mmm_mon.conf |grep -v "\#" include mmm_common.conf ? <monitor> ip 127.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_ips 192.168.56.131, 192.168.56.132, 192.168.56.133 auto_set_online 60 ? </monitor> ? <host default> monitor_user mmm_monitor monitor_password mmm_monitor </host> ? debug 0 |
ping_ips are some ips that are pinged to determine whether the network connection of the monitor is ok.
?
启动 MMM
启动 MMM 的顺序是:
- 启动 MMM Monitor
- 启动 MMM Agent
关闭 MMM 的顺序则反过来执行。
启动 Monitor
在?monitor?节点上执行启动命令,编辑/etc/default/mysql-mmm-monitor文件,enable the monitor:
ENABLED=1 |
设置随操作系统自动启动:
chkconfig mysql-mmm-monitor on |
启动monitor:
service mysql-mmm-monitor start |
如果启动有报错查看 mmm 日志,mmm 日志放在?/var/log/mysql-mmm/?目录下。
启动 Agent
在?agent?节点上执行启动命令,编辑/etc/default/mysql-mmm-agent文件,enable the agent:
ENABLED=1 |
设置随操作系统自动启动:
chkconfig mysql-mmm-agent on |
启动monitor:
service mysql-mmm-agent start |
如果启动有报错查看 mmm 日志,mmm 日志放在?/var/log/mysql-mmm/?目录下。
?
观察 mmm 状态
在?monitor?节点执行?mmm_control show?命令查看各节点状态:
[ ~]# mmm_control show mysqldb01(192.168.56.131) master/ONLINE. Roles: writer(192.168.56.191) mysqldb02(192.168.56.132) master/ONLINE. Roles: reader(192.168.56.192) mysqldb03(192.168.56.133) slave/ONLINE. Roles: reader(192.168.56.193) [ ~]# |
在?monitor?节点执行?mmm_control @cluster checks all?命令检测所有节点:
[ ~]# mmm_control checks all mysqldb02 ping [last change: 2020/04/17 18:53:11] OK mysqldb02 mysql [last change: 2020/04/17 18:53:11] OK mysqldb02 rep_threads [last change: 2020/04/17 18:53:11] OK mysqldb02 rep_backlog [last change: 2020/04/17 18:53:11] OK: Backlog is null mysqldb03 ping [last change: 2020/04/17 18:53:11] OK mysqldb03 mysql [last change: 2020/04/17 18:53:11] OK mysqldb03 rep_threads [last change: 2020/04/17 18:53:11] OK mysqldb03 rep_backlog [last change: 2020/04/17 18:53:11] OK: Backlog is null mysqldb01 ping [last change: 2020/04/17 18:53:11] OK mysqldb01 mysql [last change: 2020/04/17 18:53:11] OK mysqldb01 rep_threads [last change: 2020/04/17 18:53:11] OK mysqldb01 rep_backlog [last change: 2020/04/17 18:53:11] OK: Backlog is null [ ~]# |
?
MMM 切换
MMM 切换有两种方式:
- 手动切换。
- 自动切换。
直接切换 role
相关命令:
mmm_control [@cluster] move_role [writer/reader] host 给某个节点增加角色
[ mysql-mmm]# mmm_control show mysqldb01(192.168.56.131) master/ONLINE. Roles: writer(192.168.56.191) mysqldb02(192.168.56.132) master/ONLINE. Roles: reader(192.168.56.192) mysqldb03(192.168.56.133) slave/ONLINE. Roles: reader(192.168.56.193) ? [ mysql-mmm]# mmm_control move_role writer mysqldb02 OK: Role ‘writer‘ has been moved from ‘mysqldb01‘ to ‘mysqldb02‘. Now you can wait some time and check new roles info! [ mysql-mmm]# mmm_control show mysqldb01(192.168.56.131) master/ONLINE. Roles: mysqldb02(192.168.56.132) master/ONLINE. Roles: reader(192.168.56.192), writer(192.168.56.191) mysqldb03(192.168.56.133) slave/ONLINE. Roles: reader(192.168.56.193) ? [ mysql-mmm]# |
?
使用"上线""下线"功能切换
切换操作也可以用以下两个命令完成。
下线某个节点:
# mmm_control [@cluster] set_offline host |
上线某个节点:
# mmm_control [@cluster] set_online host |
?
宕机自动切换
模拟将主写的MASTER1节点关机,观察切换过程。
[ ~]# mmm_control show # Warning: agent on host mysqldb01 is not reachable mysqldb01(192.168.56.131) master/HARD_OFFLINE. Roles: mysqldb02(192.168.56.132) master/ONLINE. Roles: reader(192.168.56.192), writer(192.168.56.191) mysqldb03(192.168.56.133) slave/ONLINE. Roles: reader(192.168.56.193) ? [ ~]#? |
可以看出,MASTER1节点已经关机,MASTER2节点变成了主写节点,同时主写的VIP也转移到MASTER2主机上。同时,SLAVE的主会自动切换到MASTER2数据库。
[ ~]# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1726 Server version: 5.7.26-log MySQL Community Server (GPL) ? Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. ? Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. ? Type ‘help;‘ or ‘\h‘ for help. Type ‘\c‘ to clear the current input statement. ? [(none)]>select * from mysql.slave_master_info \G *************************** 1. row *************************** Number_of_lines: 25 Master_log_name: binlog.000004 Master_log_pos: 154 Host: 192.168.56.132 User_name: repuser User_password: welcome1 Port: 3306 Connect_retry: 60 Enabled_ssl: 0 Ssl_ca: Ssl_capath: Ssl_cert: Ssl_cipher: Ssl_key: Ssl_verify_server_cert: 0 Heartbeat: 30 Bind: Ignored_server_ids: 0 Uuid: Retry_count: 86400 Ssl_crl: Ssl_crlpath: Enabled_auto_position: 0 Channel_name: Tls_version: 1 row in set (0.00 sec) ? [(none)]>select * from mysql.slave_relay_log_info \G *************************** 1. row *************************** Number_of_lines: 7 Relay_log_name: /data/mysql/logs/relay-log.000001 Relay_log_pos: 4 Master_log_name: binlog.000004 Master_log_pos: 154 Sql_delay: 0 Number_of_workers: 0 Id: 1 Channel_name: 1 row in set (0.00 sec) ? [(none)]>? |
?
节点1主机恢复后,一切正常,但主写不会自动回切。
[ ~]# mmm_control show mysqldb01(192.168.56.131) master/ONLINE. Roles: mysqldb02(192.168.56.132) master/ONLINE. Roles: reader(192.168.56.192), writer(192.168.56.191) mysqldb03(192.168.56.133) slave/ONLINE. Roles: reader(192.168.56.193) ? [ ~]#? |
?