MySQL-mmm是Multi-Master Replication Manager For MySQL的缩写,该软件是为MySQL数据库实现主主复制功能而实现的一系列脚本。

MySQL-mmm的功用:

可以实现MySQL数据库的高可用效果,当主数据库出现故障后,会自动切换其他主服务器,保证业务不会中断,也能对主从数据库服务器实现读负载均衡,在具体的实现细节中,它可以实现一组基于复制的虚拟IP,还能有对数据备份、节点之间重新同步的功能。

MySQL-mmm的使用场景:

用户的读写请求已经完成了读写分离,无论是前端的应用程序层面解决还是使用了MySQL语句路由,到达数据库时,读写分离的工作已经完成,MySQL-MMM主要完成的是数据库节点间工作状态的监控及资源的流转操作。

MySQL-mmm运行的进程:

mysql-mmm是一组脚本套件,其安装套件中有mysql-mmm-monitor、mysql-mmm-tools、mysql-mmm-agent、mysql-mmm四部分。

monitor程序包安装后启动的服务用于监控在common配置文件中定义的数据库工作状况,通常我们使用的数据库主服务器中有一个节点是允许写入数据,其他的节点只能读取数据,如果主服务器故障,监控程序会通知另外的服务器端启动主服务器端原有的资源,并代替之前的主服务器的工作,更多的是接替了主服务器的写入的任务。

mysql-agent程序包是安装在各个数据库节点上的代理程序,其主要功用在于当其他节点尤其是主节点出现故障后,其可以收到mysql-monitor进程的信息,并根据自身的配置自动修改其工作特性,比如提升自己为主服务器,接收写请求,或者是修改主服务器指向等。


实例:使用MySQL-mmm实现双主模型的数据库的高可用

使用三台虚拟机:node1为主服务器,接收用户的写操作,IP:172.16.103.2

                node2为备用主服务器,接收用户的读请求,IP:172.16.103.3

                monitor主机为监控用服务器,其IP:172.16.103.1

                两个主服务器使用的VIP地址为:172.16.103.200(接收写请求的IP)、172.16.103.201、172.16.103.202(后两个IP接收读请求)


实验用简易拓扑:

基于MySQL-mmm实现MySQL的高可用_第1张图片                              

一、准备工作:

配置好/etc/hosts文件,注意配置好hosts文件很关键,因为连接数据库服务器默认使用的是第一个与IP地址匹配的主机名,这个名称要和授权的IP地址反解出来的主机名保持一致,否则就会出现无法连接或者无法写入的错误,示例:

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.16.103.1 monitor monitor.cluster.com
172.16.103.2 node1 node1.cluster.com
172.16.103.3 node2 node2.cluster.com
172.16.0.1 server.magelinux.com server

注意:简短的主机名放在了完整主机名的前面比如172.16.103.1 monitor monitor.cluster.com而不是习惯性的172.16.103.1 monitor.cluster.com monitor,因为在后续的配置mmm的过程中都是使用的简短的主机名,而我们在连接数据库建立授权账号的时候又往往使用的是IP地址,这些解析的对应关系一定要弄清楚,数据库只解析第一个匹配到的主机名,注意在这里是只解析前面的简短的主机名,我的意思是在解析172.16.103.1时数据库会只解析node1而不会去解析node1.cluster.com,如果完整的主机名放在了前面,那么后续在解析时是会出问题的,也即无法连接数据库去执行写操作。如果觉得这样的配置很繁琐,就在数据库的配置文件中mysqld字段添加skip-name-resolve一行就可以避免这些问题了。

二、在两台虚拟机上安装数据库,安装过程未给出,请参考前面博客内容,直接给出数据库的配置文件:

1、node1:(也只列出了需要添加或者需要留意的条目)

datadir = /mydata/data
auto-increment-increment = 2
auto-increment-offset = 2
relay-log=mysql-relay
relay-log-index=mysql-relay.index
log-bin=mysql-bin
binlog_format=mixed
server-id  = 1

由于两个数据库服务器是主主模型,都要从对方复制数据,所以都要开启中继日志和二进制日志,而且为了避免数据出现讹误,记录数据时使用不同的ID,偏移位置是不同的,而且要注意服务器的ID号一定是不同的。

2、node2:

datadir = /mydata/data
auto-increment-increment = 2
auto-increment-offset = 1
relay-log=mysql-relay
relay-log-index=mysql-relay.index
log-bin=mysql-bin
server-id = 2

3、连接node1数据库,创建授权账号,由于两个数据库节点之间是复制数据的,所以可以在一个数据库上执行授权操作,另一个数据库只需要在指向主服务器时,指向的记录位置在创建账号之前就可以了。

MariaDB [(none)]> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |      245 |              |                  |
+------------------+----------+--------------+------------------+
MariaDB [(none)]> GRANT REPLICATION CLIENT,REPLICATION SLAVE ON *.* TO repl@'172.16.%.%' IDENTIFIED BY 'repl';
MariaDB [(none)]> GRANT REPLICATION CLIENT,REPLICATION SLAVE ON *.* TO 'mmm_monitor'@'172.16.%.%' IDENTIFIED BY 'mmm_monitor';
MariaDB [(none)]> GRANT PROCESS,SUPER,REPLICATION CLIENT,REPLICATION SLAVE ON *.* TO 'mmm_agent'@'172.16.%.%' IDENTIFIED BY 'mmm_agent'

4、连接node2数据库:执行CHANGE MASTER TO操作,要注意指向的数据库文件及pos!

MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='172.16.103.2',MASTER_USER='repl',MASTER_PASSWORD='repl',MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=245;
MariaDB [(none)]> START SLAVE;
MariaDB [(none)]> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.16.103.2
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 960
               Relay_Log_File: mysql-relay.000002
                Relay_Log_Pos: 529
        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: 960
              Relay_Log_Space: 819
              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: 1
1 row in set (0.00 sec)

之后,查看一下node2的Pos及二进制日志文件,以便在node1上指向到node2:

MariaDB [(none)]> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |      880 |              |                  |
+------------------+---------

在node1上执行操作:

MariaDB [(none)]>  CHANGE MASTER TO MASTER_HOST='172.16.103.3',MASTER_USER='repl',MASTER_PASSWORD='repl',MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=880;
MariaDB [(none)]> START SLAVE;
MariaDB [(none)]> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.16.103.3
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 880
               Relay_Log_File: mysql-relay.000002
                Relay_Log_Pos: 529
        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: 880
              Relay_Log_Space: 819
              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: 2

双主的数据库配置完成。

三、在三台主机上安装mysql-mmm的程序包:

# yum install -y mysql-mmm*

1、在node1上配置:

[root@node1 ~]# cd /etc/mysql-mmm/
[root@node1 mysql-mmm]# vim mmm_agent.conf

在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 node1

 编辑node1上的mmm_common.conf文件,配置内容为:

active_master_role      writer

    cluster_interface       eth0
    pid_path                /var/run/mysql-mmm/mmm_agentd.pid
    bin_path                /usr/libexec/mysql-mmm/
    replication_user        repl
    replication_password    repl
    agent_user              mmm_agent
    agent_password          mmm_agent


    ip      172.16.103.2
    mode    master
    peer    node2


    ip      172.16.103.3
    mode    master
    peer    node1


    ip      172.16.103.1
    mode    slave


    hosts   node1, node2
    ips     172.16.103.200
    mode    exclusive


    hosts   node1, node2
    ips     172.16.103.201, 172.16.103.202
    mode    balanced

 mmm_common.conf文件在各个节点上内容相同,复制到其他的节点上去即可:

# scp mmm_common.conf monitor:/etc/mysql-mmm/
# scp mmm_common.conf node2:/etc/mysql-mmm/

2、在node2上编辑配置文件,内容如下:

[root@node2 mysql-mmm]# vim /etc/mysql-mmm/mmm_agent.conf      
include mmm_common.conf
this node2

3、在监控节点上配置

mmm_agent.conf内容为:

[root@monitor mysql-mmm]# vim mmm_agent.conf
include mmm_common.conf
this monitor
include mmm_common.conf

    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            172.16.103.2,172.16.103.3   #这里配置的是监控用的IP地址,但不要设置本机的IP地址,其用途是是探测本机与外部通信的
    auto_set_online     10    #这个参数的默认值是60,用于恢复数据库正常工作的时间间隔,默认时间过长,可以缩短一些
    # The kill_host_bin does not exist by default, though the monitor will
    # throw a warning about it missing.  See the section 5.10 "Kill Host
    # Functionality" in the PDF documentation.
    #
    # kill_host_bin     /usr/libexec/mysql-mmm/monitor/kill_host
    #


    monitor_user        mmm_monitor   #设置之前授权的账号和密码信息
    monitor_password    mmm_monitor

debug 0

至此两台数据库服务器主机以及在三台节点上配置mmm的过程完毕,现在可以启动数据库及mmm服务了。

# service mysqld start

node1和node2上:

# service mysql-mmm-agent start

monitor上:

# service mysql-mmm-monitor start

在全部启动完毕后,监控端可以查看到各数据库的工作状态,使用mmm_control命令查看:

[root@monitor mysql-mmm]# mmm_control show
# Warning: agent on host monitor is not reachable
  monitor(172.16.103.1) slave/HARD_OFFLINE. Roles: 
  node1(172.16.103.2) master/ONLINE. Roles: reader(172.16.103.201), writer(172.16.103.200)
  node2(172.16.103.3) master/ONLINE. Roles: reader(172.16.103.202)

在node1上查看IP地址的配置情况:

[root@node1 mysql-mmm]# ip addr show
1: lo:  mtu 16436 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:e1:37:51 brd ff:ff:ff:ff:ff:ff
    inet 172.16.103.2/16 brd 172.16.255.255 scope global eth0
    inet 172.16.103.201/32 scope global eth0
    inet 172.16.103.200/32 scope global eth0
    inet6 fe80::20c:29ff:fee1:3751/64 scope link 
       valid_lft forever preferred_lft forever

在node2上启动的IP为:

[root@node2 mysql-mmm]# ip addr show
1: lo:  mtu 16436 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:cf:64:8f brd ff:ff:ff:ff:ff:ff
    inet 172.16.103.3/16 brd 172.16.255.255 scope global eth0
    inet 172.16.103.202/32 scope global eth0
    inet6 fe80::20c:29ff:fecf:648f/64 scope link 
       valid_lft forever preferred_lft forever

如果服务器故障了,所有配置在主服务器上的VIP都会流转到另一个主服务器上:

[root@node2 mysql-mmm]# ip addr show
1: lo:  mtu 16436 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:cf:64:8f brd ff:ff:ff:ff:ff:ff
    inet 172.16.103.3/16 brd 172.16.255.255 scope global eth0
    inet 172.16.103.202/32 scope global eth0
    inet 172.16.103.201/32 scope global eth0
    inet 172.16.103.200/32 scope global eth0
    inet6 fe80::20c:29ff:fecf:648f/64 scope link 
       valid_lft forever preferred_lft forever

可以看到VIP 200,201,202都配置在了node2上。