MySQL双主同步

MySQL 双主同步

1、什么是MySQL双主同步

MySQL双主同步,也称为双主互备(Master-Master Replication),是一种高可用性的数据库架构。在这种架构下,两台MySQL服务器互为主从,即Server A是Server B的主库,同时Server B也是Server A的主库。

简单来说,就是两个数据库节点之间建立了双向的数据复制通道,任何一方数据的变更都会同步到另一方。
🔄 核心工作原理

双向复制:

通常的主从复制是单向的(A → B)。

双主同步则是闭环的(A ⇋ B)。A产生的二进制日志(binlog)会被B拉取并执行,同时B产生的binlog也会被A拉取并执行。

读写能力:

理论上,两个节点都可以接受读写请求。但在实际生产环境中,为了防止数据冲突和保证一致性,通常会配置为"一主写,一主备"(即平时只往A写,B作为热备),或者通过中间件严格控制写入路由。
🛡️ 为什么需要双主同步?

高可用性:如果主库A宕机,系统可以迅速切换到主库B继续提供服务,避免单点故障导致业务中断。

数据冗余:数据在两个节点都有完整备份,提高了数据安全性。

负载均衡:在某些场景下,可以将读请求分摊到两个节点上,减轻单一数据库的压力。

2、使用环境

只需要一台虚拟机,改虚拟机必须安装好docker,使用docker创建4个容器进行mysql隔离来实现MySQL双主同步

角色 容器名 端口 版本 系统
master mysql-master1 3306 MySQL 8.4.8 redhat 9.x
master mysql-master2 3308 MySQL 8.4.8 redhat 9.x
slave mysql-slave1 3307 MySQL 8.4.8 redhat 9.x
slave mysql-slave2 3309 MySQL 8.4.8 redhat 9.x

3、安装docker

登录阿里云镜像网站:https://developer.aliyun.com/mirror/?spm=a2c6h.13651102.0.0.554d1b11m9sIOz\&serviceType=mirror\&tag=容器

找到docker-ce

点击docker-ce后找到对应系统的docker安装方式

bash 复制代码
# step 1: 安装必要的一些系统工具
sudo yum install -y yum-utils

# Step 2: 添加软件源信息
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 注意这里网址的centos改为自己对应系统的名字,这里我所使用的是rhel,网站就应该是https://mirrors.aliyun.com/docker-ce/linux/rhel/docker-ce.repo

# Step 3: 安装Docker
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y

# Step 4: 配置国内镜像加速器
# 创建目录
sudo mkdir -p /etc/docker
# 写入配置文件
sudo tee /etc/docker/daemon.json <<-'EOF'
{
    "registry-mirrors": [
    	"https://docker-0.unsee.tech",
        "https://docker-cf.registry.cyou",
        "https://docker.1panel.live"
    ]
}
EOF
# 重启docker服务
sudo systemctl daemon-reload && sudo systemctl restart docker

# 注意:
# 官方软件源默认启用了最新的软件,您可以通过编辑软件源的方式获取各个版本的软件包。例如官方并没有将测试版本的软件源置为可用,您可以通过以下方式开启。同理可以开启各种测试版本等。
# vim /etc/yum.repos.d/docker-ce.repo
#   将[docker-ce-test]下方的enabled=0修改为enabled=1
#
# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# yum list docker-ce.x86_64 --showduplicates | sort -r
#   Loading mirror speeds from cached hostfile
#   Loaded plugins: branch, fastestmirror, langpacks
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            docker-ce-stable
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            @docker-ce-stable
#   docker-ce.x86_64            17.03.0.ce-1.el7.centos            docker-ce-stable
#   Available Packages
# Step2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.0.ce.1-1.el7.centos)
# sudo yum -y install docker-ce-[VERSION]

使用docker拉取一个mysql:8.4.8的镜像

bash 复制代码
docker pull mysql:8.4.8

1、创建网络

bash 复制代码
[root@localhost ~]# docker network create mysql_net
bash 复制代码
# 创建对应的目录文件
mkdir -p /data/{master1,master2,slave1,slave2}/{log,data,conf}

2、修改两台master的配置文件

sh 复制代码
[root@localhost ~]# cd /data/master1/conf/
[root@localhost conf]# vim my.cnf

# mysql-master1
[mysqld]
server_id=11
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
log-bin=mysql-bin
auto-increment-increment=2
auto-increment-offset=1

[root@localhost ~]# cd /data/master2/conf/
[root@localhost conf]# vim my.cnf
# mysql-master2
[mysqld]
server_id=33
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
log-bin=mysql-bin
auto-increment-increment=2
auto-increment-offset=2

3、创建两个master容器

sh 复制代码
# mysql-master1
docker run --name mysql-master1 \
--restart=always \
-p 3306:3306 \
-v /data/master1/log:/var/log/mysql \
-v /data/master1/data:/var/lib/mysql \
-v /data/master1/conf/my.cnf:/etc/my.cnf \
-e MYSQL_ROOT_PASSWORD=123456 \
--network mysql_net \
-d mysql:8.4.8


# mysql-master2
docker run --name mysql-master2 \
--restart=always \
-p 3308:3306 \
-v /data/master2/log:/var/log/mysql \
-v /data/master2/data:/var/lib/mysql \
-v /data/master2/conf/my.cnf:/etc/my.cnf \
-e MYSQL_ROOT_PASSWORD=123456 \
--network mysql_net \
-d mysql:8.4.8

4、配置两台slave

sh 复制代码
[root@localhost conf]# cd /data/slave1/conf/
[root@localhost conf]# vim my.cnf
# mysql-slave1
[mysqld]
server_id=22
log-bin=mysql-slave-bin
relay_log=mysql-relay
read_only=1

[root@localhost conf]# cd /data/slave2/conf/
[root@localhost conf]# vim my.cnf
# mysql-slave2
[mysqld]
server_id=44
log-bin=mysql-slave-bin
relay_log=mysql-relay
read_only=1

5、创建两台slave

sh 复制代码
# mysql-slave1
docker run --name mysql-slave1 \
--restart=always \
-p 3307:3306 \
-v /data/slave1/log:/var/log/mysql \
-v /data/slave1/data:/var/lib/mysql \
-v /data/slave1/conf/my.cnf:/etc/my.cnf \
-e MYSQL_ROOT_PASSWORD=123456 \
--network mysql_net \
-d mysql:8.4.8

# mysql-slave2
docker run --name mysql-slave2 \
--restart=always \
-p 3309:3306 \
-v /data/slave2/log:/var/log/mysql \
-v /data/slave2/data:/var/lib/mysql \
-v /data/slave2/conf/my.cnf:/etc/my.cnf \
-e MYSQL_ROOT_PASSWORD=123456 \
--network mysql_net \
-d mysql:8.4.8
bash 复制代码
[root@localhost conf]# tree /data/
/data/
├── master1
│   ├── conf
│   │   └── my.cnf
│   ├── data
│   └── log
├── master2
│   ├── conf
│   │   └── my.cnf
│   ├── data
│   └── log
├── slave1
│   ├── conf
│   │   └── my.cnf
│   ├── data
│   └── log
└── slave2
    ├── conf
    │   └── my.cnf
    ├── data
    └── log

6、在master1上创建用户

sql 复制代码
# mysql-master1
[root@localhost ~]# docker exec -it mysql-master1 /bin/bash
bash-5.1# mysql -uroot -p'123456'

mysql> create user 'repl_user'@'%' identified by '123456';
Query OK, 0 rows affected (0.01 sec)

mysql> create user 'slave_sync_user'@'%' identified by '123456';
Query OK, 0 rows affected (0.00 sec)

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

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

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

mysql> show binary log status;
+------------------+----------+--------------+--------------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB         | Executed_Gtid_Set |
+------------------+----------+--------------+--------------------------+-------------------+
| mysql-bin.000003 |     1448 |              | mysql,information_schema |                   |
+------------------+----------+--------------+--------------------------+-------------------+
1 row in set (0.00 sec)

7、配置master1和slave1同步

sql 复制代码
[root@localhost ~]# docker exec -it mysql-slave1 /bin/bash
bash-5.1# mysql -uroot -p'123456'
# mysql-slave1
mysql> change replication source to \
    -> source_host='mysql-master1',
    -> source_user='slave_sync_user',
    -> source_password='123456',
    -> source_log_file='mysql-bin.000003',
    -> source_log_pos=1448,  # 注意这里的位置一定是在master1中执行show binary log status;之后显示的那个位置id和file的,一定和自己显示的一样
    -> get_source_public_key=1;
Query OK, 0 rows affected, 2 warnings (0.01 sec)

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

mysql> show replica status\G
*************************** 1. row ***************************
             Replica_IO_State: Waiting for source to send event
                  Source_Host: mysql-master1
                  Source_User: slave_sync_user
                  Source_Port: 3306
                Connect_Retry: 60
              Source_Log_File: mysql-bin.000003
          Read_Source_Log_Pos: 1448
               Relay_Log_File: mysql-relay.000002
                Relay_Log_Pos: 328
        Relay_Source_Log_File: mysql-bin.000003
           Replica_IO_Running: Yes
          Replica_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
......

8、配置master2和slave2同步

sql 复制代码
# mysql-master2
[root@localhost ~]# docker exec -it mysql-master2 /bin/bash
bash-5.1# mysql -uroot -p123456
mysql> 

mysql> create user 'repl_user'@'%' identified by '123456';
Query OK, 0 rows affected (0.01 sec)

mysql> create user 'slave_sync_user'@'%' identified by '123456';
Query OK, 0 rows affected (0.00 sec)

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

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

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

mysql> show binary log status;
+------------------+----------+--------------+--------------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB         | Executed_Gtid_Set |
+------------------+----------+--------------+--------------------------+-------------------+
| mysql-bin.000003 |     1447 |              | mysql,information_schema |                   |
+------------------+----------+--------------+--------------------------+-------------------+
1 row in set (0.00 sec)


# mysql-slave2
[root@localhost ~]# docker exec -it mysql-slave2 /bin/bash
bash-5.1# mysql -uroot -p123456
mysql> 

mysql> change replication source to \
    -> source_host='mysql-master2',
    -> source_user='slave_sync_user',
    -> source_password='123456',
    -> source_log_file='mysql-bin.000003',
    -> source_log_pos=1447,
    -> get_source_public_key=1;
Query OK, 0 rows affected, 2 warnings (0.01 sec)

mysql> start replica;
Query OK, 0 rows affected (0.03 sec)

mysql> show replica status\G
*************************** 1. row ***************************
             Replica_IO_State: Waiting for source to send event
                  Source_Host: mysql-master2
                  Source_User: slave_sync_user
                  Source_Port: 3306
                Connect_Retry: 60
              Source_Log_File: mysql-bin.000003
          Read_Source_Log_Pos: 1447
               Relay_Log_File: mysql-relay.000002
                Relay_Log_Pos: 328
        Relay_Source_Log_File: mysql-bin.000003
           Replica_IO_Running: Yes
          Replica_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
......

9、配置master1和master2同步

sql 复制代码
# mysql-master2
mysql> change replication source to \
    -> source_host='mysql-master1',
    -> source_user='repl_user',
    -> source_password='123456',
    -> source_log_file='mysql-bin.000003',
    -> source_log_pos=1448,
    -> get_source_public_key=1;
Query OK, 0 rows affected, 2 warnings (0.01 sec)

mysql> start replica;
Query OK, 0 rows affected (0.04 sec)

mysql> show replica status\G
*************************** 1. row ***************************
             Replica_IO_State: Waiting for source to send event
                  Source_Host: mysql-master1
                  Source_User: repl_user
                  Source_Port: 3306
                Connect_Retry: 60
              Source_Log_File: mysql-bin.000003
          Read_Source_Log_Pos: 1448
               Relay_Log_File: d5f566847452-relay-bin.000002
                Relay_Log_Pos: 328
        Relay_Source_Log_File: mysql-bin.000003
           Replica_IO_Running: Yes
          Replica_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
......

10、配置master2和master1同步

sql 复制代码
# mysql-master2 上执行
mysql> show binary log status;
+------------------+----------+--------------+--------------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB         | Executed_Gtid_Set |
+------------------+----------+--------------+--------------------------+-------------------+
| mysql-bin.000003 |     1447 |              | mysql,information_schema |                   |
+------------------+----------+--------------+--------------------------+-------------------+
1 row in set (0.00 sec)

# mysql-master1 上执行
mysql> change replication source to \
    -> source_host='mysql-master2',
    -> source_user='repl_user',
    -> source_password='123456',
    -> source_log_file='mysql-bin.000003',
    -> source_log_pos=1447,
    -> get_source_public_key=1;
Query OK, 0 rows affected, 2 warnings (0.01 sec)

mysql> start replica;
Query OK, 0 rows affected (0.03 sec)

mysql> show replica status\G
*************************** 1. row ***************************
             Replica_IO_State: Waiting for source to send event
                  Source_Host: mysql-master2
                  Source_User: repl_user
                  Source_Port: 3306
                Connect_Retry: 60
              Source_Log_File: mysql-bin.000003
          Read_Source_Log_Pos: 1447
               Relay_Log_File: bdd9cc4ffbb8-relay-bin.000002
                Relay_Log_Pos: 328
        Relay_Source_Log_File: mysql-bin.000003
           Replica_IO_Running: Yes
          Replica_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
......

11、数据同步测试

1. 在 mysql-master1 上创建库

sql 复制代码
-- 在 mysql-master1 上创建库
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)

mysql> create database mydb;
Query OK, 1 row affected (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mydb               |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)


-- mysql-master2 上查看
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mydb               |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

-- 在 mysql-slave1 上查看
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mydb               |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

-- 在mysql-slave2 上查看
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mydb               |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.01 sec)

2. 在mysql-master2上创建表

sql 复制代码
mysql> use mydb;
Database changed
mysql> create table t1(id int);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t1 values(1),(2),(3);
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from t1;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)


-- 在mysql-master1上查看
mysql> select * from mydb.t1;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)

-- 在mysql-slave1上查看
mysql> select * from mydb.t1;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)

-- 在mysql-slave2上查看
mysql> select * from mydb.t1;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.01 sec)

gs: 0

mysql> select * from t1;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)


-- 在mysql-master1上查看
mysql> select * from mydb.t1;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)

-- 在mysql-slave1上查看
mysql> select * from mydb.t1;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)

-- 在mysql-slave2上查看
mysql> select * from mydb.t1;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.01 sec)
相关推荐
Trouvaille ~4 小时前
【MySQL篇】数据类型:存储数据的基础
android·数据库·mysql·adb·字符集·数据类型·基础入门
格林威4 小时前
AI视觉检测:INT8 量化对工业视觉检测精度的影响
linux·运维·人工智能·数码相机·计算机视觉·视觉检测·工业相机
一 乐4 小时前
酒店预订|基于springboot + vue酒店预订系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·酒店预订系统
万山寒4 小时前
linux日志查询,查找某个关键词后面的内容
linux·运维·服务器
房开民4 小时前
ubuntu中安装claude code
linux·运维·ubuntu
Bert.Cai4 小时前
Linux mv命令详解
linux·运维
头铁的伦4 小时前
QNX 网络模型
linux·网络·车载系统
小贾要学习4 小时前
【Linux】TCP网络通信编程
linux·服务器·网络·c++·网络协议·tcp/ip
光泽雨5 小时前
UNION 和 UNION ALL 作用
数据库·sql