docker部署mysql主主备份(keepalived)跨主机自动切换

docker部署mysql主主备份(keepalived)跨主机自动切换

docker部署mysql主主备份

docker部署mysql主主备份(keepalived)跨主机自动切换

docker部署mysql主主备份 haproxy代理(swarm)

1.环境准备

  • centos7系统
  • docker环境
  • docker-compose环境

2.主主同步原理

​ 主主复制即在两台MySQL主机内都可以变更数据,而且另外一台主机也会做出相应的变更。聪明的你也许已经想到该怎么实现了。对,就是将两个主从复制有机合并起来就好了。只不过在配置的时候我们需要注意一些问题,例如,主键重复,server-id不能重复等等。

​ 两台MySQL之间互为彼此的从库,同时又是主库。这种方案,既做到了访问量的压力分流,同时也解决了"单点故障"问题。任何一台故障,都还有另外一套可供使用的服务。

主主复制----->互为主从

3.预期目标

搭建一个两主的Mysql环境

实现一个数据库挂掉自动切换数据库

从属关系 容器名称 服务器 端口 vip
mysql-master1 192.168.56.100 3306 192.168.56.120
mysql-master2 192.168.56.101 3306
  • 环境采用docker部署
  • 使用docker部署mysql 及keepalived

4.搭建配置

4.1. 两主机互通开放防火墙

sh 复制代码
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.56.101" accept"
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.56.100" accept"

firewall-cmd --reload
firewall-cmd --list-all

4.2.主1服务器(56.100)

4.2.1 docker-compose.yml
yml 复制代码
mkdir -p /home/scsdm/services/mysql && cd /home/scsdm/services/mysql
cat > docker-compose.yml << EOF
version: '3'
services:
  node1:
    image: mysql:5.7.23
    hostname: mysql-master1
    container_name: mysql-master1
    restart: always
    ports:
      - "3306:3306"
    network_mode: host
    environment:
      - MYSQL_ROOT_PASSWORD=hancloud1234!
      - TZ=Asia/Shanghai
    volumes:
      - $PWD/mysql_master1/slowSql:/data/mysql
      - $PWD/mysql_master1/data:/var/lib/mysql
      - $PWD/mysql_master1/logs:/var/log/mysql
      - $PWD/mysql_master1/conf/my.cnf:/etc/mysql/my.cnf
    privileged: true
    command: ['mysqld','--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci','--default-time-zone=+08:00']
    entrypoint: bash -c "chown -R mysql:mysql /var/log/mysql && exec /entrypoint.sh mysqld"
EOF
4.2.2 配置
sql 复制代码
mkdir -p /home/scsdm/services/mysql/mysql_master1/conf
cd /home/scsdm/services/mysql/mysql_master1/conf
cat > my.cnf << EOF
!includedir /etc/mysql/conf.d/ 
!includedir /etc/mysql/mysql.conf.d/
[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
default-time-zone=+08:00
max_connections=1000

# 开启binlog
log-bin=mysql-bin
log-bin-index=mysql-bin.index
# 服务器唯一id,默认值1
server-id=1
max_binlog_size=1G
max_binlog_cache_size=1G
# 设置日志格式,默认值ROW
binlog_format=mixed
expire_logs_days=7
# 开启慢查询
slow_query_log=1
long_query_time=2
slow_query_log_file=/data/mysql/slow.log
# 错误日志
log_error=/var/log/mysql/error.log
# 设置需要复制的数据库,默认复制全部数据库
#binlog-do-db=mcp_manager
# 设置不需要复制的数据库
binlog-ignore-db=mysql
binlog-ignore-db=infomation_schema
EOF
4.2.3 启动主1服务器
cd /home/scsdm/services/mysql
# my.cnf 权限不能是777,会被忽略
chmod 644 /home/scsdm/services/mysql/mysql_master1/conf/my.cnf
docker-compose up -d
4.2.4 进入容器
sh 复制代码
#进入容器:env LANG=C.UTF-8 避免容器中显示中文乱码
docker exec -it mysql-master1 env LANG=C.UTF-8 /bin/bash
#进入容器内的mysql命令行
mysql -uroot -p
4.2.5 创建用户用于备份
sql 复制代码
-- 创建slave用户
CREATE USER 'slave'@'%';
-- 设置密码
ALTER USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY 'hancloud@1234';
-- 授予复制权限
GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%';
-- 刷新权限
FLUSH PRIVILEGES;

查看创建的用户信息

sql 复制代码
select host,user from mysql.user;
4.2.6 主机中查询master1状态

执行完此步骤后不要再操作主服务器MYSQL,防止主服务器状态值变化

sql 复制代码
SHOW MASTER STATUS;

记下FilePosition的值。

执行完此步骤后不要再操作主服务器MYSQL,防止主服务器状态值变化。

4.3.主2服务器(56.101)

4.3.1 docker-compose.yml
yml 复制代码
mkdir -p /home/scsdm/services/mysql && cd /home/scsdm/services/mysql
cat > docker-compose.yml << EOF
version: '3'
services:
  node1:
    image: mysql:5.7.23
    hostname: mysql-master2
    container_name: mysql-master2
    restart: always
    ports:
      - "3306:3306"
    network_mode: host
    environment:
      - MYSQL_ROOT_PASSWORD=hancloud1234!
      - TZ=Asia/Shanghai
    volumes:
      - $PWD/mysql_master2/slowSql:/data/mysql
      - $PWD/mysql_master2/data:/var/lib/mysql
      - $PWD/mysql_master2/logs:/var/log/mysql
      - $PWD/mysql_master2/conf/my.cnf:/etc/mysql/my.cnf
    privileged: true
    command: ['mysqld','--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci','--default-time-zone=+08:00']
    entrypoint: bash -c "chown -R mysql:mysql /var/log/mysql && exec /entrypoint.sh mysqld"
EOF
4.3.2 配置
sql 复制代码
mkdir -p /home/scsdm/services/mysql/mysql_master2/conf
cd /home/scsdm/services/mysql/mysql_master2/conf
cat > my.cnf << EOF
!includedir /etc/mysql/conf.d/ 
!includedir /etc/mysql/mysql.conf.d/
[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
default-time-zone=+08:00
max_connections=1000

# 开启binlog
log-bin=mysql-bin
log-bin-index=mysql-bin.index
# 服务器唯一id,默认值1
server-id=2
max_binlog_size=1G
max_binlog_cache_size=1G
# 设置日志格式,默认值ROW
binlog_format=mixed
expire_logs_days=7
# 开启慢查询
slow_query_log=1
long_query_time=2
slow_query_log_file=/data/mysql/slow.log
# 错误日志
log_error=/var/log/mysql/error.log
# 设置需要复制的数据库,默认复制全部数据库
#binlog-do-db=mcp_manager
# 设置不需要复制的数据库
binlog-ignore-db=mysql
binlog-ignore-db=infomation_schema
EOF
4.3.3 启动主2服务器
sh 复制代码
cd /home/scsdm/services/mysql
# my.cnf 权限不能是777,会被忽略
chmod 644 /home/scsdm/services/mysql/mysql_master2/conf/my.cnf
docker-compose up -d
4.3.4 进入容器
sql 复制代码
#进入容器:env LANG=C.UTF-8 避免容器中显示中文乱码
docker exec -it mysql-master2 env LANG=C.UTF-8 /bin/bash
#进入容器内的mysql命令行
mysql -uroot -p
4.3.5 创建用户用于备份
sql 复制代码
-- 创建slave用户
CREATE USER 'slave'@'%';
-- 设置密码
ALTER USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY 'hancloud@1234';
-- 授予复制权限
GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%';
-- 刷新权限
FLUSH PRIVILEGES;
4.3.6 主机中查询master2状态

执行完此步骤后不要再操作主服务器MYSQL,防止主服务器状态值变化

sql 复制代码
SHOW MASTER STATUS;

记下FilePosition的值。

4.3.7 配置主2 主
sh 复制代码
# 配置主Mysql地址
CHANGE MASTER TO MASTER_HOST='192.168.56.100', 
# 配置主Mssql创建的用于备份的用户名和密码和端口
MASTER_USER='slave',MASTER_PASSWORD='hancloud@1234', MASTER_PORT=3306,
# 配置主Mssql的binlog日志名称和当前所在位置(上面记录的位置)
MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=959; 
4.3.8 启动主2复制功能
sql 复制代码
START SLAVE;

-- 查看状态(不需要分号)
SHOW SLAVE STATUS\G
4.3.9 配置主1 主
sh 复制代码
# 配置主Mysql地址
CHANGE MASTER TO MASTER_HOST='192.168.56.101', 
# 配置主Mssql创建的用于备份的用户名和密码和端口
MASTER_USER='slave',MASTER_PASSWORD='hancloud@1234', MASTER_PORT=3306,
# 配置主Mssql的binlog日志名称和当前所在位置(上面记录的位置)
MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=959; 
4.3.10 启动主1复制功能
sql 复制代码
START SLAVE;

-- 查看状态(不需要分号)
SHOW SLAVE STATUS\G
4.3.11 关闭主主复制
sql 复制代码
-- 在从机上执行。功能说明:停止I/O 线程和SQL线程的操作。
stop slave; 

-- 在从机上执行。功能说明:用于删除SLAVE数据库的relaylog日志文件,并重新启用新的relaylog文件。
reset slave;

-- 在主机上执行。功能说明:删除所有的binglog日志文件,并将日志索引文件清空,重新开始所有新的日志文件。
-- 用于第一次进行搭建主从库时,进行主库binlog初始化工作;
reset master;

4.4 部署keepalived

4.4.1 下面内容分别到两台机器上执行
sh 复制代码
mkdir -p /home/scsdm/services/keepalived/checksh && cd /home/scsdm/services/keepalived

cat > /home/scsdm/services/keepalived/checksh/check-mysql.sh << EOF
#!/bin/bash
count=`netstat -apn | grep 3306 | wc -l`
if [ $count -gt 0 ]; then
    exit 0
else
   sleep 2 
   count=`netstat -apn | grep 3306 | wc -l`
   if [ $count -gt 0 ]; then
   pkill keepalived
   fi 
   exit 1
fi
EOF

# 虚拟ip
IP="192.168.56.120"
# 需要的网卡
ETH="enp0s3"
cat > /home/scsdm/services/keepalived/keepalived.conf << EOF
global_defs {
   router_id LVS_2
   script_user root                    # 脚本执行用户
   enable_script_security              # 开启脚本安全权限
}

vrrp_script checkMsql
{
    script "/checksh/check-mysql.sh"  # 这个地址写的事容器内脚本路径
    interval 2
    weight -30
}


vrrp_instance VI_1 {
    state BACKUP
    # 注意网卡
    interface ETH
    virtual_router_id 51
    priority 100
    advert_int 1
    nopreempt
    
    virtual_ipaddress {
      # 需要修改成对应的虚拟ip
        IP
    }

    authentication {
        auth_type PASS
        auth_pass password
    }

    track_script {
        checkMsql
    }
}
EOF

cat > /home/scsdm/services/keepalived/docker-compose.yml << EOF
version: '3'

services:
  keepalived:
    image: osixia/keepalived:stable
    hostname: keepalived
    volumes:
      - "${PWD}/checksh:/checksh"
      - "${PWD}/keepalived.conf:/container/service/keepalived/assets/keepalived.conf"
      - "/etc/localtime:/etc/localtime:ro"
    restart: always
    privileged: true
    network_mode: host
    command: --loglevel debug --copy-service
EOF
docker-compose up -d

即可使用该虚拟ip访问

5.测试同步

5.1.主1Mysql中创建数据

sql 复制代码
CREATE DATABASE mcp_manager;
USE mcp_manager;
CREATE TABLE t_user (
 id BIGINT AUTO_INCREMENT,
 uname VARCHAR(30),
 PRIMARY KEY (id)
);
INSERT INTO t_user(uname) VALUES('xiaohong');
INSERT INTO t_user(uname) VALUES('xiaoming');

5.2.查看数据库


5.3.主2Mysql中新增数据

sql 复制代码
INSERT INTO t_user(uname) VALUES('xiaohong2');
INSERT INTO t_user(uname) VALUES('xiaoming2');

5.4.查看数据库


6.mysql双主架构优缺点

6.1 双主架构实现原理

当从库IO线程接受到主库传递来的二进制日志(Binlog)并将之保存为从库的中继日志(relay log),然后从库SQL线程将中继日志(relay log)的事件重做到从库上,实现主从数据同步。

如果SQL线程发现该事件的server_id与当前从库的server_id相同,则会丢弃该事件,因此如果两台MySQL如何互为主从,不会导致相同的事件被重复执行。

6.2 双主架构设计目标

在一套MySQL复制群集中,通过双主或多主架构,解决一主多从架构的单点故障,减少主从切换的故障处理时间,增加MySQL群集的高可用性。

6.3 双主架构实现方案

1、主备模式,两台MySQL互为主从,其中一台作为主节点对外提供服务,另外一台作为备机节点(standby),当提供服务的主节点发生故障后,将服务请求快速切换到备用节点,原主节点故障恢复后转换为备用节点(standby)。

2、主主模式,两台MySQL互为主从,且两台MySQL均作为主节点对外提供服务,当其中一台MySQL发生故障后,将指向该故障节点的请求快速切换到另外一台MySQL,原来指向非故障节点的请求不受影响。

在主主模式下,两个主库都提供读写服务,如果应用通过两个主库操作相同数据,则会发生冲突导致数据覆盖(使用语句模式复制)或复制异常(使用行模式复制) ,因此需要对读写服务进行控制:

1、基于自主主键控制,通过设置自增属性auto_increment_offset和auto_increment_increment来控制每个主节点生产不同的自增值,并根据不同自增值访问不同主节点。

2、基于库级别或表级别控制,如应用APP1访问节点node1上的DB1库,而应用APP2访问节点node2上的DB2库,两个主节点间不会操作相同表的数据,因此不会存在事务冲突。

为保证应用程序使用相同数据库连接配置而不受故障切换影响,常用方案有:

1、VIP,通过vrrpd或keepalived将VIP动态绑定到新主节点

2、域名,通过切换域名将域名指向新主节点

3、代理,通过更新代理中存放的路由信息来指向新主节点。

6.4 双主架构优点

1、主主模式能将读写请求分摊到两个主节点,有效提升服务器使用率。

2、主节点发生故障后,能快速进行主从切换。

3、当故障节点恢复后,故障节点能通过复制进行数据恢复(应用其他节点数据)和数据同步(将未同步数据发生给其他节点)。

6.5 双主架构缺点

1、当主节点上MySQL实例发生故障后,可能会存在部分数据(Binlog)未同步到另外的主节点,导致数据丢失(直到故障节点恢复)。

2、主主模式下,很容易因数据访问控制不当导致数据冲突。

3、为提高系统高可用性,双主架构会被扩展成双主多从结构,同样存在主节点发生故障后多个从库选主和恢复复制的问题。

6.6 MMM架构

在双主架构下,MySQL本身并没有自动故障切换能力,Google开源项目MySQL-MMM(Master-Master Replication Manager for MySQL)能够用来监控MySQL主主复制并实现自动故障转移。

在使用after_sync的半同步复制的双主架构下,能有效确保两个主库的BINLOG同步,再配合MMM工具实现自动故障转移,确保群集高可用。

相关推荐
C吴新科3 小时前
MySQL入门操作详解
mysql
Ai 编码助手6 小时前
MySQL中distinct与group by之间的性能进行比较
数据库·mysql
南猿北者6 小时前
docker容器
docker·容器
白云如幻6 小时前
MySQL排序查询
数据库·mysql
苹果醋36 小时前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx
二十雨辰6 小时前
[linux]docker基础
linux·运维·docker
风和先行7 小时前
adb 命令查看设备存储占用情况
android·adb
time never ceases7 小时前
使用docker方式进行Oracle数据库的物理迁移(helowin/oracle_11g)
数据库·docker·oracle
stars_User7 小时前
MySQL数据库面试题(下)
数据库·mysql
Yaml47 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理