MySQL高可用集群方案

MySQL高可用集群方案

HiperMatrix平台目前对MySQL没有太大的并发量的读写,目前使用一个双主的集群既可以满足高可用的需求

Docker部署MySQL双主高可用集群

准备两个服务器节点,节点信息如下:

节点1: 192.168.1.101(MySQL master节点)
节点2: 192.168.1.102(MySQL slave节点)

节点1上部署MySQL服务1

在节点1上面创建MySQL master配置文件, 命名为master.cnf, 内容如下:

[mysqld]
# MySQL实例id值,数值,保证集群里面的MySQL id不要重复
server-id       = 1
# 要生成二进制日志文件 master服务器一定要开启
log-bin         = mysql-bin
# auto_imcrement步进值,一般情况下集群里面有几个MySQL实例就填上该数值
auto_increment_increment = 2 
# 表示自增长字段起始值, 一般按照master master服务器的顺序进行设置
auto_increment_offset=1  
# 允许的最大连接数量
max_connections = 2000

节点1上运行:

docker run -d --name mysql-1 --net iot \
    -p 3306:3306 \
    -v ./master.cnf:/etc/mysql/conf.d/master.cnf \
    -v /opt/db/master/mysql:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=123456 \
    mysql:8.0.26

mysql-1启动完成后,在节点1依次执行以下启动mysql console

docker exec -t mysql-1 bash
mysql -uroot -p123456

然后在mysql console中执行一下的几条msql指令

create user 'slave'@'%' identified with mysql_native_password by 'replPassWd';
grant replication slave,replication client on *.* to 'slave'@'%';
flush privileges;

show master status;

也可以执行一下命令查看用户权限授予情况:

show grants for 'slave'@'%';

完整的执行过程如下:

$ docker exec -it mysql-1 bash
root@cabf6d592173:/# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 16
Server version: 8.0.26 MySQL Community Server - GPL

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

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.

mysql> create user 'slave'@'%' identified with mysql_native_password by 'replPassWd';
Query OK, 0 rows affected (0.02 sec)

mysql> grant replication slave,replication client on *.* to 'slave'@'%';
Query OK, 0 rows affected (0.00 sec)

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

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 |      848 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)


节点2上部署MySQL服务2

在节点2上面创建MySQL master配置文件, 命名为master.cnf, 内容如下:

[mysqld]
# MySQL实例id值,数值,保证集群里面的MySQL id不要重复
server-id       = 2
# 要生成二进制日志文件 master服务器一定要开启
log-bin         = mysql-bin
# auto_imcrement步进值,一般情况下集群里面有几个MySQL实例就填上该数值
auto_increment_increment = 2 
# 表示自增长字段起始值, 一般按照master master服务器的顺序进行设置
auto_increment_offset=2
# 允许的最大连接数量
max_connections = 2000

节点2上运行:

docker run -d --name mysql-2 --net iot \
    -p 3306:3306 \
    -v ./master.cnf:/etc/mysql/conf.d/master.cnf \
    -v /opt/db/master/mysql:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=123456 \
    mysql:8.0.26

mysql-2启动完成后,在节点2依次执行以下命令启动mysql console

docker exec -t mysql-1 bash
mysql -uroot -p123456

然后在mysql console中执行一下的几条msql指令

change master to master_host='192.168.1.101',
master_port=3306,
master_user='slave',
master_password='replPassWd',
master_log_file='mysql-bin.000003',
master_log_pos=848;

start slave;

其中 master_log_file 配置的文件为节点1上show master status命令看到的文件名,master_log_pos为Position的值

完整的执行过程如下:

$ docker exec -it mysql-1 bash
root@cabf6d592173:/# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 16
Server version: 8.0.26 MySQL Community Server - GPL

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

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.

mysql> change master to master_host='192.168.1.101',
    -> master_port=3306,
    -> master_user='slave',
    -> master_password='replPassWd',
    -> master_log_file='mysql-bin.000003',
    -> master_log_pos=848;
Query OK, 0 rows affected, 9 warnings (0.02 sec)

mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)

以上命令是将节点2配置为节点1 MySQL的从节点,节点2的实例会不停的从mysql-1实例上面同步数据过来

可以用一下命令看看slave同步数据的状态:

show slave status\G

节点1配置MySQL为节点2的从节点

在节点2上创建slave用户用于同步数据,方式和节点1上的步骤是一样的

create user 'slave'@'%' identified with mysql_native_password by 'replPassWd';
grant replication slave,replication client on *.* to 'slave'@'%';
flush privileges;

执行完成后,使用show master status查看信息如下:

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

然后再在节点1上执行:

change master to master_host='192.168.1.102',
master_port=3306,
master_user='slave',
master_password='replPassWd',
master_log_file='mysql-bin.000001',
master_log_pos=3118397;

start slave;

其中 master_log_file 配置的文件为前面节点2上执行show master status命令看到的文件名,master_log_pos为Position的值

start slave命令执行之后节点1上MySQL实例也即为mysql-2的从节点,这样mysql-1和mysql-2就组成了一个双主的集群

配置KeepAlived实现VIP访问

安装KeepAlived

以ubuntu为例安装KeepAlived, 执行一下命令就可以完成keepalived的安装,其他Linux系统采用其对应的包管理命令安装KeepAlived

sudo apt install keepalived

节点1配置master KeepAlived

在节点1上创建/etc/keepalived/keepalived_check_mysql.sh,内容如下:

#!/bin/bash

INSTANCE=mysql-1
USER=root
PWD=123456
CMD="mysql -u$USER -p$PWD  -e 'show status;'"
LOG_FILE=/etc/keepalived/action.log


function log() {
    msg=$1

    echo $(date +'%Y-%m-%d %H:%M:%S') $msg >> $LOG_FILE
}

container=`docker ps | grep $INSTANCE`
if [ -z "$container" ]; then
    echo $(date +'%Y-%m-%d %H:%M:%S') "$INSTANCE is not running" >> $LOG_FILE
    exit 1
fi

docker exec -t $INSTANCE bash -c "$CMD" >/dev/null 2>&1

if [ $? == 0 ]; then
    log "mysql login successfully"
    exit 0
else
    let "n=0"
    while [ $n -lt 5 ]
    do
        docker exec -t $INSTANCE bash -c "$CMD" >/dev/null 2>&1
        if [ $? == 0 ]; then
            log "mysql re-login successfully"
            exit 0
        else
            let "n=n+1"
        fi
        sleep 3
    done
    
    log  "mysql connection faild!"

    exit 1
fi

然后将keepalived_check_mysql文件权限更改为可执行:

chmod +x /etc/keepalived/keepalived_check_mysql.sh

在节点1上创建/etc/keepalived/keepalived.conf文件,内容如下:

! Configuration File for keepalived

global_defs {
   notification_email {
     support@h-visions.com
   }
   notification_email_from kp-master@h-visions.com
   smtp_server localhost
   smtp_connect_timeout 30
}

vrrp_script check_mysql_status {
	script "/etc/keepalived/keepalived_check_mysql.sh"
	interval 10
}

vrrp_instance VI_1 {
    state BACKUP
    interface enp1s0
    virtual_router_id 101
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.1.103
    }
    track_script {
	    check_mysql_status
    }
}

notification_email: 根据实际情况进行更改
notification_email_from: 根据情况进行调整
VI_1: 实例名称,相同的备节点的命令保证和该名称相同
interface: 网卡名称,使用ifconfig查看需要配置VIP地址的网卡
virtual_router_id: 路由id,主节点和备节点必须一致
priority: 优先级,一般备节点要低于主节点
advert_int: 通信检查间隔,这里配置的为1秒
virtual_ipaddress: 虚拟ip地址,根据实际网络环境进行调整,后面访问mysql的集群通过该vip进行访问

配置文件完成后,重启keepalived服务:

sudo service keepalived restart

然后可以查看vip是否已经生效

$ ip addr show enp1s0
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether e4:3a:6e:3b:fb:04 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.101/24 brd 192.168.10.255 scope global enp1s0
       valid_lft forever preferred_lft forever
    inet 192.168.1.103/32 scope global enp1s0
       valid_lft forever preferred_lft forever
    inet6 fe80::e63a:6eff:fe3b:fb04/64 scope link 
       valid_lft forever preferred_lft forever

看到这一行(inet 192.168.1.103/32 scope global enp1s0)出现,表示vip(192.168.1.103)已经生效

节点2配置backup KeepAlived

在节点2上创建/etc/keepalived/keepalived_check_mysql.sh,内容如下:

#!/bin/bash

INSTANCE=mysql-2
USER=root
PWD=123456
CMD="mysql -u$USER -p$PWD  -e 'show status;'"
LOG_FILE=/etc/keepalived/action.log


function log() {
    msg=$1

    echo $(date +'%Y-%m-%d %H:%M:%S') $msg >> $LOG_FILE
}

container=`docker ps | grep $INSTANCE`
if [ -z "$container" ]; then
    echo $(date +'%Y-%m-%d %H:%M:%S') "$INSTANCE is not running" >> $LOG_FILE
    exit 1
fi

docker exec -t $INSTANCE bash -c "$CMD" >/dev/null 2>&1

if [ $? == 0 ]; then
    log "mysql login successfully"
    exit 0
else
    let "n=0"
    while [ $n -lt 5 ]
    do
        docker exec -t $INSTANCE bash -c "$CMD" >/dev/null 2>&1
        if [ $? == 0 ]; then
            log "mysql re-login successfully"
            exit 0
        else
            let "n=n+1"
        fi
        sleep 3
    done
    
    log  "mysql connection faild!"

    exit 1
fi

然后将keepalived_check_mysql文件权限更改为可执行:

sudo chmod +x /etc/keepalived/keepalived_check_mysql.sh

在节点2上创建/etc/keepalived/keepalived.conf文件,内容如下:

! Configuration File for keepalived

global_defs {
   notification_email {
     support@h-visions.com
   }
   notification_email_from kp-master@h-visions.com
   smtp_server localhost
   smtp_connect_timeout 30

   script_user root
   enable_script_security
}

vrrp_script check_mysql_status {
    script "/etc/keepalived/keepalived_check_mysql.sh"
    interval 10
}

vrrp_instance VI_1 {
    state BACKUP
    interface enp1s0
    virtual_router_id 101
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.1.103
    }
    track_script {
        check_mysql_status
    }
}

同样当配置完成后,重启keepalived服务:

sudo service keepalived restart

待两个节点的keepalived服务都跑起来之后,之后mysql通过vip(192.168.1.103)的地址进行访问即可,如jdbc:mysql://192.168.1.103:3306/iot_data,当其中的一个数据库实例停止之后,keepalived自动切换到另外一个正常的mysql实例上

2022-08-11
0