Mysql 主主与 keepalived 实现高可用

1.MySQL双主(主主)架构方案思路是:

2.主主环境(这里只介绍2台主的配置方案):

3.创建过程

3.3 创建数据库相关账户并开户主从同步

3.4 测试主从同步

4.配置keepalived 高可用

5.模拟测试mysqld高可用


1.MySQL双主(主主)架构方案思路是:

1.两台mysql都可读写,互为主备,默认只使用一台(masterA)负责数据的写入,另一台(masterB)备用;

2.masterA是masterB的主库,masterB又是masterA的主库,它们互为主从;

3.两台主库之间做高可用,可以采用keepalived等方案(使用VIP对外提供服务);

4.所有提供服务的从服务器与masterB进行主从同步(双主多从);

5.建议采用高可用策略的时候,masterA或masterB均不因宕机恢复后而抢占VIP(非抢占模式);

这样做可以在一定程度上保证主库的高可用,在一台主库down掉之后,可以在极短的时间内切换到另一台主库上(尽可能减少主库宕机对业务造成的影响),减少了主从同步给线上主库带来的压力;

但是也有几个不足的地方:

1.masterB可能会一直处于空闲状态(可以用它当从库,负责部分查询);

2.主库后面提供服务的从库要等masterB先同步完了数据后才能去masterB上去同步数据,这样可能会造成一定程度的同步延时;

2.主主环境(这里只介绍2台主的配置方案):

1.CentOS  64位 2台:masterA(192.168.139.130),masterB(192.168.139.131)

2.官方Mysql5.6版本

3.创建过程

3.1 首先我们两台虚拟机上都要安装好mysql,并启动(具体安装过程可以参考我的第十七课预习任务的方法)

//在masterA上
[root@knightlai01 ~]# ps aux |grep mysql
root        988  0.0  0.1 115432  1704 ?        S    Oct20   0:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --datadir=/data/mysql --pid-file=
mysql      1188  0.0 46.3 1302820 462644 ?      Sl   Oct20   0:57 /usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql --datadir=/data/myscal/mysql/lib/plugin --user=mysql --log-error=/data/mysql/error.log --pid-file=/data/mysql/mysql.pid --socket=/tmp/mysql.sock
root       4047  0.0  0.0 112708   960 pts/0    S+   20:27   0:00 grep --color=auto mysql

//在masterB上
[root@knightlai02 shell]# ps aux |grep mysql
root        974  0.0  0.1 115432  1700 ?        S    Oct20   0:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --datadir=/data/mysql --pid-file=/data/mysql/mysql.pid
mysql      1193  0.0 46.3 1333488 462280 ?      Sl   Oct20   1:03 /usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql --datadir=/data/mysql --plugin-dir=/usr/local/mysql/lib/plugin --user=mysql --log-error=/data/mysql/error.log --pid-file=/data/mysql/mysql.pid --socket=/tmpmysql.sock
root       6134  0.0  0.0 112704   956 pts/0    R+   21:20   0:00 grep --color=auto mysql

3.2 在MasterA上配置  /etc/my.cnf

[root@knightlai01 shell]# vim /etc/my.cnf
basedir = /usr/local/mysql 
datadir = /data/mysql
socket = /tmp/mysql.sock
log-error = /data/mysql/error.log
pid-file = /data/mysql/mysql.pid 
server_id=130
log_bin=knightlai                  #打开二进制功能,MASTER主服务器必须打开此项
binlog_format = mixed
relay-log =relay-bin
relay-log-index =slave-relay-bin.index
auto-increment-increment =1
auto-increment-offset =2


#masterA自增长ID
auto_increment_offset = 1
auto_increment_increment = 2          #奇数ID

在MasterB上配置

basedir = /usr/local/mysql 
datadir = /data/mysql
socket = /tmp/mysql.sock
log-error = /data/mysql/error.log
pid-file = /data/mysql/mysql.pid
server_id=131
log_bin=slave 
binlog_format= mixed
relay-log=relay-bin
relay-log-index= slave-relay-bin.index
auto-increment-increment= 2
auto-increment-offset=2

注意:mysql1和mysql只有server-id不同和auto-increment-offset不同,其他必须相同。

binlog_format= mixed:指定mysql的binlog日志的格式,mixed是混合模式。

relay-log:开启中继日志功能

relay-log-index:中继日志清单

auto-increment-increment= 2:表示自增长字段每次递增的量,其默认值是1。它的值应设为整个结构中服务器的总数,本案例用到两台服务器,所以值设为2。

auto-increment-offset= 2:用来设定数据库中自动增长的起点(即初始值),因为这两能服务器都设定了一次自动增长值2,所以它们的起点必须得不同,这样才能避免两台服务器数据同步时出现主键冲突。

//如果是克隆的虚拟机需要修改这个uuid
[root@knightlai01 shell]# cat /data/mysql/auto.cnf
[auto]
server-uuid=b14b02c7-b46b-11e8-b604-000c29ecfccf

3.3 创建数据库相关账户并开户主从同步

在MasterA 上配置

//添加主从同步账户
mysql> grant replication slave on *.* to 'repl'@'192.168.139.131' identified by '123456';
Query OK, 0 rows affected (0.19 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.07 sec)

//查看主库状态 记住这个值 “file” “position”
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| knightlai.000007 |      411 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.02 sec)

//配置同步信息
mysql> change master to master_host='192.168.139.131',master_port=3306,master_user='repl',master_password='123456',master_log_file='slave.000001',master_log_pos=120;
Query OK, 0 rows affected, 2 warnings (1.31 sec)

mysql> start slave;
Query OK, 0 rows affected (0.88 sec)

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.139.131
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: slave.000001
          Read_Master_Log_Pos: 120
               Relay_Log_File: mysql-relay-bin.000002
                Relay_Log_Pos: 279
        Relay_Master_Log_File: slave.000001
             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: 120
              Relay_Log_Space: 452
              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: 131
                  Master_UUID: b14b02c7-b46b-44e8-b604-000c29ecfccf
             Master_Info_File: /data/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 0
1 row in set (0.02 sec)

在Master B上配置

注意:由于这里是测试环境,可以保证没数据写入,否则需要的步骤是:先masterA锁表-->masterA备份数据-->masterA解锁表 -->masterB导入数据-->masterB设置主从-->查看主从

mysql> grant replication slave on *.* to 'repl'@'192.168.139.130' identified by '123456';
Query OK, 0 rows affected (0.56 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.05 sec)

mysql> show master status;
+--------------+----------+--------------+------------------+-------------------+
| File         | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+--------------+----------+--------------+------------------+-------------------+
| slave.000001 |      120 |              |                  |                   |
+--------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)



mysql> change master to master_host='192.168.139.130',master_port=3306,master_user='repl',master_password='123456',master_log_file='knightlai.000007',master_log_pos=411;
Query OK, 0 rows affected, 2 warnings (0.08 sec)

mysql> start slave;
Query OK, 0 rows affected (0.02 sec)

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.139.130
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: knightlai.000007
          Read_Master_Log_Pos: 411
               Relay_Log_File: relay-bin.000002
                Relay_Log_Pos: 283
        Relay_Master_Log_File: knightlai.000007
             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: 411
              Relay_Log_Space: 450
              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: 168
                  Master_UUID: b14b02c7-b46b-11e8-b604-000c29ecfccf
             Master_Info_File: /data/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 0
1 row in set (0.15 sec)

3.4 测试主从同步

在MasterA上创建一个数据库

mysql> create  database test1;
Query OK, 1 row affected (0.03 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| db1                |
| mysql              |
| performance_schema |
| test               |
| test1              |
| test1012           |
| zrlog              |
+--------------------+
8 rows in set (0.18 sec)

在Master B上查看

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| db1                |
| mysql              |
| performance_schema |
| test               |
| test1              |
| test1012           |
| zrlog              |
+--------------------+
8 rows in set (0.15 sec)

4.配置keepalived 高可用

4.1 安装keepalived

//在Master A上安装keepalived
[root@knightlai02 ~]# ps aux |grep keep
zabbix     1561  0.0  0.2 254844  2448 ?        S    22:44   0:00 /usr/sbin/zabbix_server: housekeeper [startup idle for 30 minutes]
root       2132  0.0  0.1 118676  1348 ?        Ss   22:47   0:00 /usr/sbin/keepalived -D
root       2133  0.0  0.3 129608  3308 ?        S    22:47   0:00 /usr/sbin/keepalived -D
root       2134  0.0  0.2 129548  2812 ?        S    22:47   0:00 /usr/sbin/keepalived -D
root       2170  0.0  0.0 112708   960 pts/0    S+   22:47   0:00 grep --color=auto keep

//在Master B上安装keepalived
[root@knightlai02 ~]# ps aux |grep keep
zabbix     1561  0.0  0.2 254844  2448 ?        S    22:44   0:00 /usr/sbin/zabbix_server: housekeeper [startup idle for 30 minutes]
root       2132  0.0  0.1 118676  1348 ?        Ss   22:47   0:00 /usr/sbin/keepalived -D
root       2133  0.0  0.3 129608  3308 ?        S    22:47   0:00 /usr/sbin/keepalived -D
root       2134  0.0  0.2 129548  2812 ?        S    22:47   0:00 /usr/sbin/keepalived -D
root       2170  0.0  0.0 112708   960 pts/0    S+   22:47   0:00 grep --color=auto keep

4.2 编辑Master  A上的配置文件

[root@knightlai02 init.d]# cat /etc/keepalived/keepalived.conf 
global_defs {
   notification_email {
     [email protected]
   }
   notification_email_from [email protected]
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL
}
 
vrrp_script chk_mysql {
    script "/usr/local/sbin/check_ng.sh"
    interval 3
}
 
vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 51
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass aminglinux>com
    }
    virtual_ipaddress {
        192.168.139.100
    }
 
    track_script {
        chk_mysql
    }
 
}

4.3  编辑Master B上的配置文件

[root@knightlai01 ~]# cat /etc/keepalived/keepalived.conf 
global_defs {
   notification_email {
     [email protected]
   }
   notification_email_from [email protected]
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL
}
 
vrrp_script chk_mysql {
    script "/usr/local/sbin/check_ng.sh"
    interval 3
}
 
vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 51
    priority 90
    nopreempt 
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass aminglinux>com
    }
    virtual_ipaddress {
        192.168.139.100
    }
 
    track_script {
        chk_mysql
    }
 
}

4.4 两个配置脚本内容一致,路径一致

//Master A与B上面的脚本一样
[root@knightlai02 init.d]# cat /usr/local/sbin/check_mysql.sh
#时间变量,用于记录日志
d=`date --date today +%Y%m%d_%H:%M:%S`
#计算mysqld进程数量
n=`ps -C mysqld --no-heading|wc -l`
#如果进程为0,则启动mysqld,并且再次检测mysqld进程数量,
#如果还为0,说明mysqld无法启动,此时需要关闭keepalived
if [ $n -eq "0" ]; then
        # systemctl start mysqld
        sleep 3
        n2=`ps -C mysqld  --no-heading|wc -l`
        if [ $n2 -eq "0"  ]; then
                echo "$d mysqld down,keepalived will stop" >> /var/log/mysql.log
                systemctl stop keepalived
        fi
fi

5.模拟测试mysqld高可用

5.1 模拟master A上面mysql keepalived故障

用测试机192.168.139.134去测试mysql

//在Master A上面关闭mysqld服务
[root@knightlai02 init.d]# systemctl stop mysqld
[root@knightlai02 init.d]# ps aux |grep mysqld
root      13947  0.0  0.0 112704   956 pts/0    S+   04:33   0:00 grep --color=auto mysqld

//在134测试机上面访问mysql 192.168.139.100
MySQL [(none)]> show global variables like 'server%';
+----------------+--------------------------------------+
| Variable_name  | Value                                |
+----------------+--------------------------------------+
| server_id      | 131                                  |
| server_id_bits | 32                                   |
| server_uuid    | b14b02c7-b46b-44e8-b604-000c29ecfccf |
+----------------+--------------------------------------+
3 rows in set (0.00 sec)


//这里的server_id 131,说明我们访问的是第一台Master B
[root@knightlai02 init.d]# cat /etc/my.cnf
[mysqld]
 server_id=131
 basedir = /usr/local/mysql 
 datadir = /data/mysql
 socket = /tmp/mysql.sock
 log-error = /data/mysql/error.log
 pid-file = /data/mysql/mysql.pid

5.2 模拟master B上面mysql keepalived故障

//在Master B上面关闭mysqld服务
[root@knightlai02 init.d]# systemctl stop mysqld
[root@knightlai02 init.d]# ps aux |grep mysqld
root      13947  0.0  0.0 112704   956 pts/0    S+   04:33   0:00 grep --color=auto mysqld

//在134测试机上面访问mysql 192.168.139.100
MySQL [(none)]> show global variables like 'server%';
+----------------+--------------------------------------+
| Variable_name  | Value                                |
+----------------+--------------------------------------+
| server_id      | 130                                  |
| server_id_bits | 32                                   |
| server_uuid    | b14b02c7-b46b-44e8-b604-000c29ecfccf |
+----------------+--------------------------------------+
3 rows in set (0.00 sec)


//这里的server_id 130,说明我们访问的是第一台Master A
[root@knightlai02 init.d]# cat /etc/my.cnf
[mysqld]
 server_id=130
 basedir = /usr/local/mysql 
 datadir = /data/mysql
 socket = /tmp/mysql.sock
 log-error = /data/mysql/error.log
 pid-file = /data/mysql/mysql.pid

猜你喜欢

转载自blog.csdn.net/a1779078902/article/details/83268577