MySQL 高可用之MMM
MMM即Multi-Master Replication Manager for MySQL:mysql多主复制管理器,基于perl实现,关于mysql主主复制 配置的监控、故障转移和管理的一套可伸缩的脚本套件(在任何时候只有一个节点可以被写入),MMM也能 对从服务器进行读负载均衡,所以可以用它来在一组用于复制的服务器启动虚拟ip,除此之外,它还有实现数 据备份、节点之间重新同步功能的脚本。MySQL本身没有提供replication failover的解决方案,通过MMM方案 能实现服务器的故障转移,从而实现mysql的高可用。MMM不仅能提供浮动IP的功能,如果当前的主服务器挂 掉后,会将你后端的从服务器自动转向新的主服务器进行同步复制,不用手工更改同步配置。
优点:高可用性,扩展性好,出现故障自动切换,对于主主同步,在同一时间只提供一台数据库写操作,保证 的数据的一致性。当主服务器挂掉以后,另一个主立即接管,其他的从服务器能自动切换,不用人工干预。
缺点:monitor节点是单点,不过这个你也可以结合keepalived或者haertbeat做成高可用;至少三个节点,对主机 的数量有要求,需要实现读写分离,还需要在前端编写读写分离程序。在读写非常繁忙的业务系统下表现不是很 稳定,可能会出现复制延时、切换失效等问题。MMM方案并不太适应于对数据安全性要求很高,并且读、写 繁忙的环境中。
适用场景: MMM的适用场景为数据库访问量大,并且能实现读写分离的场景。
Mmm主要功能 由下面三个脚本提供: mmm_mond 负责所有的监控工作的监控守护进程,决定节点的移除(mmm_mond进程定 时心跳检测,失败则将write ip浮动到另外一台master)等等 mmm_agentd 运行在mysql服务器上的代理守护进 程,通过简单远程服务集提供给监控节点 mmm_control 通过命令行管理mmm_mond进程 在整个监管过程中, 需要在mysql中添加相关授权用户,授权的用户包括一个mmm_monitor用户和一个mmm_agent用户,如果想 使用mmm的备份工具则还要添加一个mmm_tools用户。
二、开始部署
环境如下:
1、在5台主机上都进行如下操作
#添加主机解析 [ ~]# vim /etc/hosts 192.168.171.135 master1 192.168.171.131 master2 192.168.171.146 slave1 192.168.171.136 slave2 192.168.171.134 monitor #安装perl依赖 [ ~]# yum -y install perl-* libart_lgpl.x86_64 rrdtool.x86_64 rrdtool-perl.x86_64 #安装perl的相关库,默认为国外的源,可以直接使用如下命令进行安装 [ ~]# cpan -i Algorithm::Diff Class::Singleton DBI DBD::mysql Log::Dispatch Log::Log4perl Mail::Send Net::Ping Proc::Daemon Time::HiRes Params::Validate Net::ARP #这里我使用的是阿里云的cpan,所以需要更改镜像源 [ ~]# cpan # 初始化 cpan[1]> o conf urllist # 查看当前有的URL urllist 0 [http://mirror.navercorp.com/CPAN/] 1 [http://cpan.mirror.cdnetworks.com/] 2 [http://cpan.rinet.ru/] Type ‘o conf‘ to view all configuration items #删除当前有的url cpan[6]> o conf urllist pop http://cpan.mirror.cdnetworks.com/ cpan[10]> o conf urllist pop http://mirror.navercorp.com/CPAN/ cpan[13]> o conf urllist pop http://cpan.rinet.ru/ #添加阿里云的镜像源 cpan[16]> o conf urllist push https://mirrors.aliyun.com/CPAN/ cpan[17]> o conf commit # 提交 #安装perl的相关库 [ ~]# cpan -i Algorithm::Diff Class::Singleton DBI DBD::mysql Log::Dispatch Log::Log4perl Mail::Send Net::Ping Proc::Daemon Time::HiRes Params::Validate Net::ARP
哦。。。报错了,排查发现DBD-mysql、Net-ping、Net::ARP这是哪个没有安装成功,所以下载软件包手动安装试试
~]# wget https://cpan.metacpan.org/authors/id/C/CR/CRAZYDJ/Net-ARP-1.0.11.tgz [ ~]# wget https://cpan.metacpan.org/authors/id/R/RU/RURBAN/Net-Ping-2.73.tar.gz [ ~]# wget https://cpan.metacpan.org/authors/id/D/DV/DVEEDEN/DBD-mysql-4.050.tar.gz [ ~]# tar zxf DBD-mysql-4.050.tar.gz [aster1 ~]# cd DBD-mysql-4.050/ [ DBD-mysql-4.050]# perl Makefile.PL [ DBD-mysql-4.050]# make install [ ~]# tar zxf Net-Ping-2.73.tar.gz [ ~]# cd Net-Ping-2.73/ [ Net-Ping-2.73]# perl Makefile.PL [ Net-Ping-2.73]# make install [ ~]# tar zxf Net-ARP-1.0.11.tgz [ ~]# cd Net-ARP-1.0.11/ [ Net-ARP-1.0.11]# perl Makefile.PL [ Net-ARP-1.0.11]# make install
perl的相关库安装成功如下所示
在master1、master2、slave1、slave2主机上安装mysql5.7和配置复制 master1和master2互为主从, slave1、slave2为master1的从
#master1 [ ~]# vim /etc/my.cnf # 添加如下 log-bin=mysql-bin binlog_format=mixed server-id=1 relay-log=relay-bin relay-log-index=slave-relay-bin.index log-slave-updates = 1 auto-increment-increment = 2 auto-increment-offset = 1 #master2 [ ~]# vim /etc/my.cnf log-bin = mysql-bin binlog_format = mixed server-id = 2 relay-log = relay-bin relay-log-index = slave-relay-bin.index log-slave-updates = 1 auto-increment-increment = 2 auto-increment-offset = 2 #slave1 [ ~]# vim /etc/my.cnf server-id = 3 relay-log = relay-bin relay-log-index = slave-relay-bin.index read_only = 1 #slave2 [ ~]# vim /etc/my.cnf server-id = 4 relay-log = relay-bin relay-log-index = slave-relay-bin.index read_only = 1 #所有都进行重启 [ ~]# systemctl restart mysqld
主从配置(master1和master2配置为主主,slave1和slave2配置成master1的从)
#master1上授权 mysql> grant replication slave on *.* to ‘192.168.171.%‘ identified by ‘123‘; mysql> show master status; # 获取binlog文件和 Position点 +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000001 | 453 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec) #master2上授权 mysql> grant replication slave on *.* to ‘192.168.171.%‘ identified by ‘123‘; mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000001 | 453 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec) #在master2、slave1和slave2执行 mysql> change master to master_host=‘192.168.171.135‘,master_port=3306,master_user=‘rep‘,master_password=‘123‘,master_log_file=‘mysql-bin.000001‘,master_log_pos=453; mysql> start slave;
验证主从复制,master2主机
slave1主机
slave2主机
确保Slave_IO_Running和Slave_SQL_Running都为yes
将master1配置为master2的从,实现master1和master2互为主从
#master2上 mysql> show master status; # 获取binlog文件和Position点 +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000001 | 453 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec) #master1上 mysql> change master to master_host=‘192.168.171.131‘,master_port=3306,master_user=‘rep‘,master_password=‘123‘,master_log_file=‘mysql-bin.000001‘,master_log_pos=453; mysql> start slave;
验证主从复制
mysql-mmm配置
在4台 mysql节点上创建用户
#创建代理账号 mysql> grant super,replication client,process on *.* to ‘mmm_agent‘@‘192.168.171.%‘ identified by ‘123‘; #创建监控账号 mysql> grant replication client on *.* to ‘mmm_monitor‘@‘192.168.171.%‘ identified by ‘123‘;
注:由于之前我们已经完成了主从复制,所以在一台上创建用户会直接同步到其他从服务器上
#检查是否同步成功 mysql> select user,host from mysql.user where user like ‘mmm_%‘; +-------------+---------------+ | user | host | +-------------+---------------+ | mmm_agent | 192.168.171.% | | mmm_monitor | 192.168.171.% | +-------------+---------------+ 2 rows in set (0.00 sec) #检查用户所拥有的权限是否完善 mysql> show grants for ‘mmm_agent‘@‘192.168.171.%‘; +--------------------------------------------------------------------------------+ | Grants for % | +--------------------------------------------------------------------------------+ | GRANT PROCESS, SUPER, REPLICATION CLIENT ON *.* TO ‘mmm_agent‘@‘192.168.171.%‘ | +--------------------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> show grants for ‘mmm_monitor‘@‘192.168.171.%‘; +------------------------------------------------------------------+ | Grants for % | +------------------------------------------------------------------+ | GRANT REPLICATION CLIENT ON *.* TO ‘mmm_monitor‘@‘192.168.171.%‘ | +------------------------------------------------------------------+ 1 row in set (0.00 sec)
注:mmm_monitor用户:mmm监控用于对mysql服务器进程健康检查
mmm_agent用户:mmm代理用来更 改只读模式,复制的主服务器等
安装MySQL-mmm
#在数据库服务器(master1、master2、slave1、slave2)上do都进行安装 [ ~]# wget http://pkgs.fedoraproject.org/repo/pkgs/mysql-mmm/mysql-mmm2.2.1.tar.gz/f5f8b48bdf89251d3183328f0249461e/mysql-mmm-2.2.1.tar.gz [ ~]# tar zxf mysql-mmm-2.2.1.tar.gz [ ~]# cd mysql-mmm-2.2.1/ [ mysql-mmm-2.2.1]# make install
配置mmm 编写配置文件,五台主机必须一致
完成安装后,所有的配置文件都放到了/etc/mysql-mmm/下面。管理服务器和数据库服务器上都要包含一个共同的文件mmm_common.conf
#编写配置文件 [ mysql-mmm]# vim mmm_common.conf active_master_role writer # master角色的标示,所有的db服务器要开启read_only参数,对 于writer服务器监控代理会自动将read_only属性关闭 <host default> cluster_interface ens33 # 群集的网络接口 pid_path /var/run/mmm_agentd.pid # pid路径 bin_path /usr/lib/mysql-mmm/ # 可执行文件路径 replication_user rep # 复制用户 replication_password 123 # 复制用户的密码 agent_user mmm_agent # 代理用户 agent_password 123 # 代理用户的密码 </host> <host master1> # master1的host名 ip 192.168.171.135 # master1的ip mode master # 角色属性,master代表是主 peer master2 # 与master1对等的服务器的host名,也就是从master2的服务器host名 </host> <host master2> ip 192.168.171.131 mode master peer master1 </host> <host slave1> # 从库的host名,如果存在多个从库可以重复一样的配置 ip 192.168.171.146 # 从的IP mode slave # slave的角色属性代表当前host是从 </host> <host slave2> ip 192.168.171.136 mode slave </host> <role writer> # writer角色配置 hosts master1,master2 #能进行写操作的服务器的host名,如果不想切换写操作这 里可以只配置master,这样也可以避免因为网络延时而进行write的切换,但是一旦master出现故障那 么当前的MMM就没有writer了只有对外的read操作 ips 192.168.171.250 # 对外提供的写操作的虚拟IP,也就是VIP mode exclusive # exclusive代表只允许存在一个主,也就是只能提供一个写的IP </role> <role reader> #read角色配置 hosts master2,slave1,slave2 # 对外提供读操作的服务器的host名,当然这里也可以把 master加进来 ips 192.168.171.251, 192.168.171.252, 192.168.171.253 # 对外提供读操作的虚拟ip,这三个ip和 host不是一一对应的,并且ips也hosts的数目也可以不相同,如果这样配置的话其中一个hosts会分配 两个ip mode balanced # balanced代表负载均衡 </role>
同时将这个文件拷贝到其它的服务器,配置不变
[ ~]# scp /etc/mysql-mmm/mmm_common.conf :/etc/mysql-mmm/ [ ~]# scp /etc/mysql-mmm/mmm_common.conf :/etc/mysql-mmm/ [ ~]# scp /etc/mysql-mmm/mmm_common.conf :/etc/mysql-mmm/ [ ~]# scp /etc/mysql-mmm/mmm_common.conf :/etc/mysql-mmm/ #也有一个更简便的方法,我这里没有配置好主机名,所以一个个复制的 [] for host in master1 master2 slave1 slave2 ; do scp /etc/mysql-mmm/mmm_common.conf $host:/etc/mysql-mmm/ ; done
代理文件配置 编辑 4台mysql节点机上的/etc/mysql-mmm/mmm_agent.conf
#master1 [ ~]# vim /etc/mysql-mmm/mmm_agent.conf include mmm_common.conf this master1 #master2 include mmm_common.conf this master2 #slave1 include mmm_common.conf this slave1 #slave2 include mmm_common.conf this slave2 #注意:这个配置只配置db服务器,监控服务器不需要配置 #启动代理进程 在 /etc/init.d/mysql-mmm-agent的脚本文件的#!/bin/sh下面,加入如下内容(所有db服务器上) [ ~]# vim /etc/init.d/mysql-mmm-agent #!/bin/sh source /root/.bash_profile #添加成系统服务并设置为自启动 [ ~]# chkconfig --add mysql-mmm-agent [ ~]# chkconfig mysql-mmm-agent on [ ~]# /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
编辑 monitor主机上的/etc/mysql-mmm/mmm_mon.conf
[ ~]# vim /etc/mysql-mmm/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 192.168.171.135, 192.168.171.131, 192.168.171.146, 192. 168.171.136 # 用于测试网络可用 性 IP地址列表,只要其中有一个地址 ping 通,就代表网络正常,这里不要写入本机地址 auto_set_online 0 #设置自动online的时间,默认是超过60s就将它设置为online,默认是60s, 这里将其设为0就是立即online </monitor> <check default> check_period 5 # 检查周期默认为5s trap_period 10 # 一个节点被检测不成功的时间持续trap_period秒,就慎重的认为这个节点失败了 timeout 2 # 检查超时的时间 restart_after 10000 # 在完成restart_after次检查后,重启checker进程 max_backlog 86400 # 记录检查rep_backlog日志的最大次数 </check> <host default> monitor_user mmm_monitor monitor_password 123 </host> debug 0 # 0正常模式,1为debug模式 #启动监控进程,加入如下内容 [ ~]# vim /etc/init.d/mysql-mmm-monitor #!/bin/sh source /root/.bash_profile #添加成系统服务并设置为自启动 [ ~]# chkconfig --add mysql-mmm-monitor [ ~]# chkconfig mysql-mmm-monitor on [ ~]# /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
注:无论是在db端还是在监控端如果有对配置文件进行修改操作都需要重启代理进程和监控进程。
注:MMM启动顺序:先启动monitor,再启动 agent 检查集群状态。
#查看集群状态 [ ~]# mmm_control show master1(192.168.171.135) master/AWAITING_RECOVERY. Roles: master2(192.168.171.131) master/AWAITING_RECOVERY. Roles: slave1(192.168.171.146) slave/AWAITING_RECOVERY. Roles: slave2(192.168.171.136) slave/AWAITING_RECOVERY. Roles: #可以看到都处于离线状态,这是我们需要输入如下命令,手动使他上线 [ ~]# mmm_control set_online master1 [ ~]# mmm_control set_online master2 [ ~]# mmm_control set_online slave1 [ ~]# mmm_control set_online slave2 #再次查看,发现已经OK了 [ ~]# mmm_control show master1(192.168.171.135) master/ONLINE. Roles: writer(192.168.171.250) master2(192.168.171.131) master/ONLINE. Roles: reader(192.168.171.252) slave1(192.168.171.146) slave/ONLINE. Roles: reader(192.168.171.253) slave2(192.168.171.136) slave/ONLINE. Roles: reader(192.168.171.251)
模拟master1宕机,手动停止mysql服务,观察monitor日志,master1的日志如下
查看群集的最新状态
[ ~]# mmm_control show master1(192.168.171.135) master/HARD_OFFLINE. Roles: master2(192.168.171.131) master/ONLINE. Roles: reader(192.168.171.252), writer(192.168.171.250) slave1(192.168.171.146) slave/ONLINE. Roles: reader(192.168.171.253) slave2(192.168.171.136) slave/ONLINE. Roles: reader(192.168.171.251) #从显示结果可以看出master1的状态有ONLINE转换为HARD_OFFLINE,写VIP转移到了master2主机上。 检查所 有的db服务器群集状态 [ ~]# mmm_control checks all master1 ping [last change: 2020/06/29 00:39:00] OK master1 mysql [last change: 2020/06/29 00:53:54] ERROR: Connect error (host = 192.168.171.135:3306, user = mmm_monitor)! Can‘t connect to MySQL server on ‘192.168.171.135‘ (111) master1 rep_threads [last change: 2020/06/29 00:39:00] OK master1 rep_backlog [last change: 2020/06/29 00:39:00] OK: Backlog is null slave1 ping [last change: 2020/06/29 00:39:00] OK slave1 mysql [last change: 2020/06/29 00:39:00] OK slave1 rep_threads [last change: 2020/06/29 00:39:00] OK slave1 rep_backlog [last change: 2020/06/29 00:39:00] OK: Backlog is null master2 ping [last change: 2020/06/29 00:39:00] OK master2 mysql [last change: 2020/06/29 00:39:00] OK master2 rep_threads [last change: 2020/06/29 00:39:00] OK master2 rep_backlog [last change: 2020/06/29 00:39:00] OK: Backlog is null slave2 ping [last change: 2020/06/29 00:39:00] OK slave2 mysql [last change: 2020/06/29 00:39:00] OK slave2 rep_threads [last change: 2020/06/29 00:39:00] OK slave2 rep_backlog [last change: 2020/06/29 00:39:00] OK: Backlog is null #从上面可以看到master1能ping通,说明只是服务死掉了
启动master1主机的mysql服务,观察monitor日志,master1的日志如下
从上面可以看到master1的状态由hard_offline改变为awaiting_recovery状态
用如下命令将服务器上线
[ ~]# mmm_control set_online master1 #查看群集最新状态 [ ~]# mmm_control show master1(192.168.171.135) master/ONLINE. Roles: master2(192.168.171.131) master/ONLINE. Roles: reader(192.168.171.252), writer(192.168.171.250) slave1(192.168.171.146) slave/ONLINE. Roles: reader(192.168.171.253) slave2(192.168.171.136) slave/ONLINE. Roles: reader(192.168.171.251) #可以看到主库启动不会接管主,只到现有的主再次宕机,才会再次切换。
**总结** (1)master2备选主节点宕机不影响集群的状态, 就是移除了master2备选节点的读状态。 (2)master1主节点宕机,由master2备选主节点接管写角色, slave1,slave2指向新master2主库进行复制,slave1,slave2会自动change master到master2. (3)如果master1主库 宕机,master2复制应用又落后于master1时就变成了主可写状态,这时的数据主无法保证一致性。 如果 master2,slave1,slave2延迟于master1主,这个时master1宕机,slave1,slave2将会等待数据追上db1后,再重新 指向新的主node2进行复制操作,这时的数据也无法保证同步的一致性。 (4)如果采用MMM高可用架构,主, 主备选节点机器配置一样,而且开启半同步进一步提高安全性或采用MariaDB/mysql5.7进行多线程从复制,提 高复制的性能
附:
1.日志文件: 日志文件往往是分析错误的关键,所以要善于利用日志文件进行问题分析。 db 端:/var/log/mysql-mmm/mmm_agentd.log 监控端:/var/log/mysql-mmm/mmm_mond.log 2.命令文件: mmm_agentd:db代理进程的启动文件 mmm_mond:监控进程的启动文件 mmm_backup:备份文件 mmm_restore:还原文件 mmm_control:监控操作命令文件 db服务器端只有mmm_agentd程序,其它的都是在monitor服务器端。 3.mmm_control用法 mmm_control程序可以用于监控群集状态、切换writer、设置online\offline操作等。 Valid commands are: help - show this message #帮助信息 ping - ping monitor #ping当前的群集是否正 常 show - show status #群集在线状态检查 checks [|all [|all]] - show checks status#执行监控检查操作 set_online - set host online #将host设置为online set_offline - set host offline #将host设置为offline mode - print current mode. #打印输出当前的mode set_active - switch into active mode.
#检查所有的db服务器群集状态:
[ ~]# mmm_control checks all #检查项包括:ping、mysql是否正常运行、复制线程是否正常等检查群集环境在线状况: [ ~]# mmm_control show #对指定的host执行offline操作: [ ~]# mmm_controlset_offline slave2 #对指定的host执行onine操作: [ ~]# mmm_controlset_online slave2 #执行write切换(手动切换): 查看当前的slave对应的master [ ~]# mysql -uroot -p123456 -e ‘show slave status\G;‘ mysql: [Warning] Using a password on the command line interface can be insecure. 1. row Slave_IO_State: Waiting for master to send event Master_Host: 192.168.171.134 #writer切换,要确保mmm_common.conf文件中的writer属性有配置对应的host,否则无法切换 [ ~]# mmm_controlmove_role writer master1 OK: Role ‘writer‘ has been moved from ‘master2‘ to ‘master1‘. Now you can wait some time and check new roles info!
4.其它处理问题 如果不想让writer从master切换到backup(包括主从的延时也会导致写VIP的切换),那么 可以在配置/etc/mysql-mmm/mmm_common.conf时,去掉中的backup #writer角色配置 hosts master1 #这里只配置一个Hosts ips 192.168.31.2#对外提供的写操作的虚拟IP mode exclusive #exclusive代表只允 许存在一个主,也就是只能提供一个写的IP 这样的话当master1出现故障了writer写操作不会切换到 master2服务器,并且slave也不会指向新的master,此时当前的MMM之前对外提供写服务。 5.总结 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参数的影 响。