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工具实现自动故障转移,确保群集高可用。

相关推荐
苹果醋31 分钟前
vue + iview + vue-i18n中英翻译
java·运维·spring boot·mysql·nginx
Angletank24 分钟前
SpringBoot中JPA组件深入查询业务实现
数据库·spring boot·后端·mysql
星光一影26 分钟前
社交交友软件系统源码 即时通讯 聊天 微信小程序 App H5三端通用
mysql·微信小程序·小程序·php·uniapp·交友
梦里不知身是客1127 分钟前
mysql的B+Tree介绍
数据库·mysql
youxiao_9028 分钟前
Docker 容器(二)
运维·docker·容器
爱宇阳29 分钟前
使用 Docker 容器备份 GitLab 实例教程
docker·容器·gitlab
爱宇阳30 分钟前
使用 Docker 容器备份与 Docker Compose 升级 GitLab 实例教程
docker·eureka·gitlab
木童66239 分钟前
Docker 容器化 Web 服务全流程实践(含网络深度场景)
前端·网络·docker
不如打代码KK42 分钟前
MySQL死锁排查指南
数据库·mysql
打不了嗝 ᥬ᭄2 小时前
【MySQL】数据类型以及库和表的操作
数据库·mysql