使用 MMM 实现 MySQL 双主复制高可用

本文介绍了一种名为MMM(Master-Master Replication Manager for MySQL)的脚本程序,该程序支持MySQL双主故障切换和日常管理。MMM可以监控MySQL Master-Master复制状态,并在服务器故障时实现自动切换。此外,文章还提供了详细的安装配置步骤和功能测试方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、MMM 简介

1. 概述

2. 优缺点

3. 工作原理

4. 典型用例

(1)双节点设置

(2)双主 + 一个/多个从

5. 系统需求

二、实验设计

1. 基本环境

2. 架构设计

三、MMM 安装配置

1. 配置双主复制

2. 安装 MMM

3. 建立数据库用户

4. 配置 MMM

(1)通用配置

(2)agent 配置

(3)monitor 配置

四、功能测试

1. 启动 MMM

(1)启动 agent

(2)启动监控

(3)检查 MMM 启动后的状态

2. 测试切换

参考:


一、MMM 简介

1. 概述

        MMM(Master-Master replication manager for MySQL)是一套支持双主故障切换和双主日常管理的脚本程序。MMM 使用 Perl 语言开发,主要用来监控和管理 MySQL Master-Master(双主)复制,可以说是 mysql 主主复制管理器。虽然叫做双主复制,但是业务上同一时刻只允许对一个主进行写入,另一台备选主上提供部分读服务,以加速在主主切换时刻备选主的预热,可以说 MMM 这套脚本程序一方面实现了故障切换的功能,另一方面其内部附加的工具脚本也可以实现多个 slave 的 read 负载均衡。MMM 是关于 MySQL 主主复制配置的监控、故障转移和管理的一套可伸缩的脚本套件(在任何时候只有一个节点可以被写入)。这个套件也能对居于标准的主从配置的任意数量的从服务器进行读负载均衡,所以可以用它在一组居于复制的服务器启动虚拟 IP,除此之外,它还有实现数据备份、节点之间重新同步功能的脚本。

        MMM 提供了自动和手动两种方式移除一组服务器中复制延迟较高的服务器的虚拟 IP,同时它还可以备份数据,实现两节点之间的数据同步等。由于 MMM 无法完全的保证数据一致性,所以 MMM 适用于对数据的一致性要求不是很高,但是又想最大程度的保证业务可用性的场景。MySQL本身没有提供 replication failover 的解决方案,通过 MMM 方案能实现服务器的故障转移,从而实现 MySQL 的高可用。对于那些对数据的一致性要求很高的业务,不建议采用 MMM 这种高可用架构。

2. 优缺点

  • 优点:高可用性,扩展性好,出现故障自动切换,对于主主同步,在同一时间只提供一台数据库写操作,保证的数据的一致性。
  • 缺点:Monitor 节点是单点,可以结合 Keepalived 实现高可用。

3. 工作原理

        MMM 是一套灵活的脚本程序,基于 perl 实现,用来对 mysql replication 进行监控和故障迁移,并能管理 mysql Master-Master 复制的配置(同一时间只有一个节点是可写的)。MMM 的主要功能通过以下三个脚本提供:

  • mmm_mond:监视守护进程,它执行所有监视工作并做出有关角色切换的所有决定等等。此脚本需要在监管机上运行。
  • mmm_agentd:运行在每个 mysql 服务器上(Master 和 Slave)的代理进程,完成监控的探针工作和执行简单的远端服务设置。此脚本需要在被监管机上运行。
  • mmm_control:一个简单的脚本,提供管理 mmm_mond 进程的命令。

        mysql-mmm 的监管端会提供多个虚拟 IP(VIP),包括一个可写 VIP,多个可读 VIP。通过监管的管理,这些 IP 会绑定在可用 MySQL 之上,当某一台 MySQL 宕机时,监管会将 VIP 迁移至其它 MySQL。在整个监管过程中,需要在 MySQL 中添加相关授权用户,以便让 MySQL 可以支持监理机的维护。授权的用户包括一个 mmm_monitor 用户和一个 mmm_agent 用户,如果想使用 mmm 的备份工具则还要添加一个 mmm_tools 用户。

4. 典型用例

(1)双节点设置

        双节点架构如图1 所示。

图1

        在双节点主-主设置中,MMM 使用五个 IP:每个节点的单个永久 IP,两个读取 VIP(只读)和 1 个写入 VIP(更新)。最后三个 IP 在节点之间迁移,具体取决于节点可用性。通常在没有复制延迟时,活动主库有 2 个 VIP(读写),备用主库有 1 个读VIP(只读)。如果发生故障,读写操作都会迁移到工作节点。

(2)双主 + 一个/多个从

        这种架构如图2 所示。

图2

5. 系统需求

        对于使用 n 个 MySQL 服务器的 MMM 设置,有以下需求:

  • n + 1 个主机:每个 MySQL 服务器一个主机; MMM 监视器的一个主机。
  • 2 * n + 1 个 IP 地址:每个主机一个固定 IP + 读角色一个 VIP,一个写入 VIP。
  • monitor user:具有用于 MMM 监视器的 REPLICATION CLIENT 特权的 MySQL 用户。
  • agent user:具有 SUPER,REPLICATION CLIENT,MMM 代理进程权限的 MySQL 用户。
  • replication user:具有 REPLICATION SLAVE 权限的 MySQL 用户,用于复制。
  • tools user:具有 SUPER,REPLICATION CLIENT,RELOAD for MMM 工具权限的 MySQL 用户。

        监控主机需要安装以下支持包:

  1. perl
  2. fping(如果想以非 root 用户身份运行 mmm_mond)
  3. Perl 模块:
  • Algorithm::Diff
  • Class:Singleton
  • DBI and DBD::mysql
  • File::Basename
  • File::stat
  • File::Temp
  • Log::Dispatch
  • Log::Log4perl
  • Mail::Send
  • Net::Ping
  • Proc::Daemon
  • Thread::Queue
  • Time::HiRes

        对于节点主机,初始应该在所有 MySQL 服务器的配置中设置 read_only=1,MMM 将使用 active_master_role 在活动主机上将其更改为 read_only=0。主机需要安装以下支持包:

  1. perl
  2. iproute
  3. send_arp (solaris)
  4. Perl模块:
  • Algorithm::Diff
  • DBI and DBD::mysql
  • File::Basename
  • File::stat
  • Log::Dispatch
  • Log::Log4perl
  • Mail::Send
  • Net::ARP (linux)
  • Proc::Daemon
  • Time::HiRes

        如果要使用 MMM 工具(mmm_backup,mmm_restore,mmm_clone),则必须将 LVM 用于 MySQL 数据库和日志所在的分区。注意,需要对回滚段空间进行自由物理扩展,参见“Estimating Undo Space needed for LVM Snapshot”。MMM 工具还需要以下 perl 模块:

  • Path::Class
  • Data::Dumper

二、实验设计

1. 基本环境

  • 操作系统版本:CentOS Linux release 7.2.1511 (Core)
  • MySQL版本:5.6.14
  • 主机信息:见表1

角色

IP

主机名

网卡

server_id

DB1

172.16.1.125

hdp2

ens32

125

DB2

172.16.1.126

hdp3

ens32

126

Monitor

172.16.1.127

hdp4

-

-

表1

  • VIP信息:见表2

VIP

角色

描述

172.16.1.100

write

应用程序连接该VIP对主库进行写请求

172.16.1.210

read

应用程序连接该VIP进行读请求

172.16.1.211

read

应用程序连接该VIP进行读请求

表2

2. 架构设计

        实验架构如图3 所示。

图3


三、MMM 安装配置

1. 配置双主复制

        双主复制的详细配置步骤可以参考这篇文章:“MySQL主从复制与主主复制 - 那一叶随风 - 博客园”,这里从略。

2. 安装 MMM

        在三台主机执行下面的 yum 命令安装 MMM 软件包。

yum -y install mysql-mmm-*

3. 建立数据库用户

        在 DB1、DB2 中建立 mmm_agent 和 mmm_monitor 用户。

grant super,replication client,process on *.* to 'mmm_agent'@'%' identified by '123456';
grant replication client on *.* to 'mmm_monitor'@'%' identified by '123456';

4. 配置 MMM

(1)通用配置

        编辑 DB1 上的 /etc/mysql-mmm/mmm_common.conf 文件,内容如下:

active_master_role      writer

<host default>
    cluster_interface       ens32
    pid_path                /var/run/mmm_agentd.pid
    bin_path                /usr/libexec/mysql-mmm/
    replication_user        repl
    replication_password    123456
    agent_user              mmm_agent
    agent_password          123456
</host>

<host db1>
    ip      172.16.1.125
    mode    master
    peer    db2
</host>

<host db2>
    ip      172.16.1.126
    mode    master
    peer    db1
</host>

<role writer>
    hosts   db1, db2
    ips     172.16.1.100
    mode    exclusive
</role>

<role reader>
    hosts   db1, db2
    ips     172.16.1.210, 172.16.1.211
    mode    balanced
</role>

        主要配置项说明:

  • active_master_role:活动主机角色名称,agent 与 monitor 使用。
  • replication_user:用于复制的用户。
  • agent_user:mmm-agent 用户。
  • host段中的mode:标明是否为主或者备选主,或者从库。
  • role段中的mode:exclusive 为独占模式,同一时刻只能有一个主。balanced 可能有多个 ips,ips 将在主机之间平衡。
  • <role write> 中的 hosts:表示目前的主库和备选主的真实主机 IP 或者主机名,ips 为对外提供的虚拟机 ip 地址。
  • <role readr> 中的 hosts:代表从库真实的 ip 和主机名,ips 代表从库的虚拟 ip 地址。

        将该文件复制到其它所有节点(DB2、Monitor)。

scp /etc/mysql-mmm/mmm_common.conf 172.16.1.126:/etc/mysql-mmm/
scp /etc/mysql-mmm/mmm_common.conf 172.16.1.127:/etc/mysql-mmm/

(2)agent 配置

        DB1 的 /etc/mysql-mmm/mmm_agent.conf 文件内容为:

include mmm_common.conf
this db1

        DB2 的 /etc/mysql-mmm/mmm_agent.conf 文件内容为:

include mmm_common.conf
this db2

(3)monitor 配置

        Monitor 上的 /etc/mysql-mmm/mmm_mon.conf 文件内容为:

include mmm_common.conf

<monitor>
    ip                  172.16.1.127
    pid_path            /var/run/mmm_mond.pid
    bin_path            /usr/libexec/mysql-mmm
    status_path         /var/lib/mysql-mmm/mmm_mond.status
    ping_ips            172.16.1.125,172.16.1.126
    auto_set_online     60
</monitor>

<host default>
    monitor_user        mmm_monitor
    monitor_password    123456
</host>

debug 0

        auto_set_online 表示将节点状态从 AWAITING_RECOVERY 切换到 ONLINE 之前等待的秒数,0 表示已禁用。

四、功能测试

1. 启动 MMM

(1)启动 agent

        在 DB1、DB2 上执行:

/etc/init.d/mysql-mmm-agent start
/etc/init.d/mysql-mmm-agent start

        /etc/init.d/mysql-mmm-agent 文件内容分如下:

#!/bin/sh
#
# mysql-mmm-agent    This shell script takes care of starting and stopping
#                    the mmm agent daemon.
#
# chkconfig: - 64 36
# description:  MMM Agent.
# processname: mmm_agentd
# config: /etc/mmm_agent.conf
# pidfile: /var/run/mmm_agentd.pid

# Cluster name (it can be empty for default cases)
CLUSTER=''


#-----------------------------------------------------------------------
# Paths
if [ "$CLUSTER" != "" ]; then
    MMM_AGENTD_BIN="/usr/sbin/mmm_agentd @$CLUSTER"
    MMM_AGENTD_PIDFILE="/var/run/mmm_agentd-$CLUSTER.pid"
else 
    MMM_AGENTD_BIN="/usr/sbin/mmm_agentd"
    MMM_AGENTD_PIDFILE="/var/run/mmm_agentd.pid"
fi

echo "Daemon bin: '$MMM_AGENTD_BIN'"
echo "Daemon pid: '$MMM_AGENTD_PIDFILE'"

#-----------------------------------------------------------------------
# See how we were called.
case "$1" in
  start)
        # Start daemon.
        echo -n "Starting MMM Agent daemon... "
        if [ -s $MMM_AGENTD_PIDFILE ] && kill -0 `cat $MMM_AGENTD_PIDFILE` 2> /dev/null; then
            echo " already running."
            exit 0
        fi
        $MMM_AGENTD_BIN
        if [ "$?" -ne 0 ]; then
            echo "failed"
            exit 1
        fi
        echo "Ok"
        exit 0
        ;;

  stop)
        # Stop daemon.
        echo -n "Shutting down MMM Agent daemon"
        if [ -s $MMM_AGENTD_PIDFILE ]; then
            pid="$(cat $MMM_AGENTD_PIDFILE)"
            cnt=0
            kill "$pid"
            while kill -0 "$pid" 2>/dev/null; do
                cnt=`expr "$cnt" + 1`
                if [ "$cnt" -gt 15 ]; then
                    kill -9 "$pid"
                    break
                fi
                sleep 2
                echo -n "."
            done
            echo " Ok"
            exit 0
        fi
        echo " not running."
        exit 0
        ;;

  status)
        echo -n "Checking MMM Agent process:"
        if [ ! -s $MMM_AGENTD_PIDFILE ]; then
            echo " not running."
            exit 3
        fi
        pid="$(cat $MMM_AGENTD_PIDFILE)"
        if ! kill -0 "$pid" 2> /dev/null; then
            echo " not running."
            exit 1
        fi
        echo " running."
        exit 0
        ;;

  restart|reload)
        $0 stop
        $0 start
        exit $?
        ;;

  *)
        echo "Usage: $0 {start|stop|restart|status}"
        ;;
esac

exit 1

(2)启动监控

        在 Monitor 上执行:

/etc/init.d/mysql-mmm-monitor start

        /etc/init.d/mysql-mmm-monitor 文件内容分如下:

#!/bin/sh
#
# mysql-mmm-monitor  This shell script takes care of starting and stopping
#                    the mmm monitoring daemon.
#
# chkconfig: - 64 36
# description:  MMM Monitor.
# processname: mmm_mond
# config: /etc/mmm_mon.conf
# pidfile: /var/run/mmm_mond.pid

# Cluster name (it can be empty for default cases)
CLUSTER=''


#-----------------------------------------------------------------------
# Paths
if [ "$CLUSTER" != "" ]; then
    MMM_MOND_BIN="/usr/sbin/mmm_mond @$CLUSTER"
    MMM_MOND_PIDFILE="/var/run/mmm_mond-$CLUSTER.pid"
else 
    MMM_MOND_BIN="/usr/sbin/mmm_mond"
    MMM_MOND_PIDFILE="/var/run/mmm_mond.pid"
fi

echo "Daemon bin: '$MMM_MOND_BIN'"
echo "Daemon pid: '$MMM_MOND_PIDFILE'"

#-----------------------------------------------------------------------
# See how we were called.
case "$1" in
  start)
        # Start daemon.
        echo -n "Starting MMM Monitor daemon: "
        if [ -s $MMM_MOND_PIDFILE ] && kill -0 `cat $MMM_MOND_PIDFILE` 2> /dev/null; then
            echo " already running."
            exit 0
        fi
        $MMM_MOND_BIN
        if [ "$?" -ne 0 ]; then
            echo "failed"
            exit 1
        fi
        echo "Ok"
        exit 0
        ;;

  stop)
        # Stop daemon.
        echo -n "Shutting down MMM Monitor daemon: "
        if [ -s $MMM_MOND_PIDFILE ]; then
            pid="$(cat $MMM_MOND_PIDFILE)"
            cnt=0
            kill "$pid"
            while kill -0 "$pid" 2>/dev/null; do
                cnt=`expr "$cnt" + 1`
                if [ "$cnt" -gt 15 ]; then
                    kill -9 "$pid"
                    break
                fi
                sleep 2
                echo -n "."
            done
            echo " Ok"
            exit 0
        fi
        echo " not running."
        exit 0
        ;;

  status)
        echo -n "Checking MMM Monitor process:"
        if [ ! -s $MMM_MOND_PIDFILE ]; then
            echo " not running."
            exit 3
        fi
        pid="$(cat $MMM_MOND_PIDFILE)"
        if ! kill -0 "$pid" 2> /dev/null; then
            echo " not running."
            exit 1
        fi
        echo " running."
        exit 0
        ;;

  restart|reload)
        $0 stop
        $0 start
        exit $?
        ;;

  *)
        echo "Usage: $0 {start|stop|restart|status}"
        ;;
esac

exit 1

(3)检查 MMM 启动后的状态

        mmm 启动成功后,在 Monitor 上执行 mmm_control show 和 mmm_control checks 命令结果如下:

[root@hdp4~]#mmm_control show
  db1(172.16.1.125) master/ONLINE. Roles: reader(172.16.1.210)
  db2(172.16.1.126) master/ONLINE. Roles: reader(172.16.1.211), writer(172.16.1.100)

[root@hdp4~]#
[root@hdp4~]#mmm_control checks
db2  ping         [last change: 2018/08/02 08:57:38]  OK
db2  mysql        [last change: 2018/08/02 08:57:38]  OK
db2  rep_threads  [last change: 2018/08/02 08:57:38]  OK
db2  rep_backlog  [last change: 2018/08/02 08:57:38]  OK: Backlog is null
db1  ping         [last change: 2018/08/02 08:57:38]  OK
db1  mysql        [last change: 2018/08/02 08:57:38]  OK
db1  rep_threads  [last change: 2018/08/02 08:57:38]  OK
db1  rep_backlog  [last change: 2018/08/02 08:57:38]  OK: Backlog is null

2. 测试切换

(1)停止 DB1 上的 MySQL 服务

service mysql stop

        查看状态,DB1 上的 VIP reader(172.16.1.210)自动迁移到 DB2 上。

[root@hdp4~]#mmm_control show
  db1(172.16.1.125) master/HARD_OFFLINE. Roles: 
  db2(172.16.1.126) master/ONLINE. Roles: reader(172.16.1.210), reader(172.16.1.211), writer(172.16.1.100)

[root@hdp4~]#

(2)启动 DB1 上的 MySQL 服务

service mysql start

        一分钟之后,状态恢复:

[root@hdp4~]#mmm_control show
  db1(172.16.1.125) master/ONLINE. Roles: reader(172.16.1.210)
  db2(172.16.1.126) master/ONLINE. Roles: reader(172.16.1.211), writer(172.16.1.100)

[root@hdp4~]#

(3)停止 DB2 上的 MySQL 服务

service mysql stop

        DB2 上负责读的 VIP(172.16.1.211)以及负责写的 VIP(172.16.1.100)会自动迁移到 DB1 上。

[root@hdp4~]#mmm_control show
  db1(172.16.1.125) master/ONLINE. Roles: reader(172.16.1.210), reader(172.16.1.211), writer(172.16.1.100)
  db2(172.16.1.126) master/HARD_OFFLINE. Roles: 

[root@hdp4~]#

(4)启动 DB2 上的 MySQL 服务

service mysql start

        一分钟之后,DB1 上负责读的 VIP(172.16.1.210)自动迁移到 DB2 上,但是负责写的 VIP(172.16.1.100),仍在 DB1 上。

[root@hdp4~]#mmm_control show
  db1(172.16.1.125) master/ONLINE. Roles: reader(172.16.1.211), writer(172.16.1.100)
  db2(172.16.1.126) master/ONLINE. Roles: reader(172.16.1.210)

[root@hdp4~]#

(5)只读节点上 stop slave
        在 DB2 上停止复制:

mysql> stop slave;

        查看状态,DB2 上的 VIP(172.16.1.210)会自动迁移到 DB1 上。

[root@hdp4~]#mmm_control show
  db1(172.16.1.125) master/ONLINE. Roles: reader(172.16.1.210), reader(172.16.1.211), writer(172.16.1.100)
  db2(172.16.1.126) master/REPLICATION_FAIL. Roles: 

[root@hdp4~]#

(6)只读节点上 start slave
        在 DB2 上启动复制:

mysql> start slave;

        状态恢复:

[root@hdp4~]#mmm_control show
  db1(172.16.1.125) master/ONLINE. Roles: reader(172.16.1.211), writer(172.16.1.100)
  db2(172.16.1.126) master/ONLINE. Roles: reader(172.16.1.210)

[root@hdp4~]#

(7)读写节点上 stop slave
        在 DB1 上停止复制:

mysql> stop slave;

        查看状态无任何变化。理论上也应该是对现有的环境无任何影响。

[root@hdp4~]#mmm_control show
  db1(172.16.1.125) master/ONLINE. Roles: reader(172.16.1.211), writer(172.16.1.100)
  db2(172.16.1.126) master/ONLINE. Roles: reader(172.16.1.210)

[root@hdp4~]#

(8)停止 MMM 监控主机上的 monitor 服务

/etc/init.d/mysql-mmm-monitor stop

        VIP 都还在之前的节点上:

[root@hdp2~]#ip a | grep ens32
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 172.16.1.125/24 brd 172.16.1.255 scope global ens32
    inet 172.16.1.100/32 scope global ens32
    inet 172.16.1.211/32 scope global ens32

[mysql@hdp3~]$ip a | grep ens32
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 172.16.1.126/24 brd 172.16.1.255 scope global ens32
    inet 172.16.1.210/32 scope global ens32

(9)启动 MMM 监控服务

/etc/init.d/mysql-mmm-monitor start

        对 DB1 和 DB2 上的相关服务无影响。

[root@hdp4~]#mmm_control show
  db1(172.16.1.125) master/ONLINE. Roles: reader(172.16.1.211), writer(172.16.1.100)
  db2(172.16.1.126) master/ONLINE. Roles: reader(172.16.1.210)

[root@hdp4~]#

(10)查看监控日志

        以上的角色切换的过程都在监控日志中记录:

[root@hdp4~]#tail -f /var/log/mysql-mmm/mmm_mond.log
...

2018/08/02 09:07:46 FATAL State of host 'db1' changed from ONLINE to HARD_OFFLINE (ping: OK, mysql: not OK)
2018/08/02 09:10:53 FATAL State of host 'db1' changed from HARD_OFFLINE to AWAITING_RECOVERY
2018/08/02 09:11:54 FATAL State of host 'db1' changed from AWAITING_RECOVERY to ONLINE because of auto_set_online(60 seconds). It was in state AWAITING_RECOVERY for 61 seconds
2018/08/02 09:14:06 FATAL State of host 'db2' changed from ONLINE to HARD_OFFLINE (ping: OK, mysql: not OK)
2018/08/02 09:16:22 FATAL State of host 'db2' changed from HARD_OFFLINE to AWAITING_RECOVERY
2018/08/02 09:17:24 FATAL State of host 'db2' changed from AWAITING_RECOVERY to ONLINE because of auto_set_online(60 seconds). It was in state AWAITING_RECOVERY for 62 seconds
2018/08/02 09:20:02 FATAL State of host 'db2' changed from ONLINE to REPLICATION_FAIL
2018/08/02 09:22:14 FATAL State of host 'db2' changed from REPLICATION_FAIL to ONLINE

参考:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值