1. 双主双从 主主互备
MySQL的双主双从(主主互备)架构是一种高可用性和负载均衡的解决方案,它由两台主数据库服务器和两台从数据库服务器组成。每台主服务器同时充当另一台主服务器的从服务器,形成一个互为主从的关系。这种架构可以提供以下优势:
- 高可用性:任何一台主服务器故障,另一台主服务器可以立即接管其工作,确保系统持续运行。
- 负载均衡:读操作可以分散到多台从服务器上,减轻主服务器的负担,提高整体性能。
- 数据冗余:数据在多台服务器上备份,降低了数据丢失的风险。
- 灵活扩展:可以根据需求增加从服务器,进一步提升系统的处理能力。
在配置MySQL双主双从架构时,需要考虑以下几个关键步骤:
-
环境准备:确保所有服务器上安装相同版本的MySQL,并关闭防火墙以允许服务器之间的通信。
-
配置主服务器:在每台主服务器上配置
my.cnf
文件,设置唯一的server-id
,启用二进制日志(log-bin
),并设置binlog-format
为mixed
或ROW
以支持事务完整性。同时,需要配置自增字段的起始值和递增量,以避免主键冲突。 -
配置从服务器:在从服务器上配置
my.cnf
文件,设置唯一的server-id
,并启用中继日志(relay-log
)。 -
创建复制用户并授权:在每台主服务器上创建用于复制的用户,并授权该用户在所有数据库上进行复制操作。
-
配置主从复制:在每台从服务器上使用
CHANGE MASTER TO
命令配置主服务器的信息,包括主服务器的地址、复制用户的用户名和密码、二进制日志文件名和位置。 -
启动复制并监控状态:在从服务器上启动复制过程,并定期使用
SHOW SLAVE STATUS\G
命令监控复制状态,确保复制正常进行。 -
处理自增ID冲突:在双主架构中,需要特别注意自增ID的冲突问题。可以通过设置不同的初始值和增长步长来避免冲突,或者使用全局事务ID(GTID)来简化冲突处理。
通过搭建一个稳定的MySQL双主双从架构,以实现高可用性和负载均衡。在实际部署时,还需要根据具体的业务需求和环境进行调整和优化。
2. 准备工作
编号 | 角色 | IP | 端口 |
1 | masterMysqlOne | 192.168.0.15 | 3507 |
2 | SlaveMysql1 | 192.168.0.15 | 3508 |
3 | masterMysqlTwo | 192.168.0.15 | 3509 |
4 | SlaveMysql2 | 192.168.0.15 | 3505 |
实际开发中,双主机、双从机配置完成一定要重启 mysql 服务,检查端口号是否开启 或关闭防火墙。
参考文章
3. 双主配置
3.1 部署masterMysqlOne
masterMysqlOne容器
docker run -p 3507:3306 --name masterMysqlOne -v /mysqldata/mysql-master1/log:/var/log/mysql -v /mysqldata/mysql-master1/data:/var/lib/mysql -v /mysqldata/mysql-master1/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
修改配置文件
vi /mysqldata/mysql-master1/conf/my.cnf
配置内容
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=1
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
#设置需要复制的数据库
binlog-do-db=users
## 开启二进制日志功能
log-bin=mall-mysql-bin
#设置logbin格式
binlog_format=STATEMENT
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
# 在作为从数据库的时候,有写入操作也要更新二进制日志文件
log-slave-updates
#表示自增长字段每次递增的量,指自增字段的起始值,其默认值是1,取值范围是1 .. 65535
auto-increment-increment=2
# 表示自增长字段从哪个数开始,指字段一次递增多少,他的取值范围是1 .. 65535
auto-increment-offset=1
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
masterMysqlOne主键从1开始,每次增长2。
重启容器实例
docker restart masterMysqlOne
进入容器,
docker exec -it masterMysqlOne /bin/bash
连接数据库,如果成功则数据库安装好了
3.2 部署masterMysqlTwo
创建masterMysqlTwo容器
docker run -p 3509:3306 --name masterMysqlTwo -v /mysqldata/mysql-master2/log:/var/log/mysql -v /mysqldata/mysql-master2/data:/var/lib/mysql -v /mysqldata/mysql-master2/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
修改配置文件
vi /mysqldata/mysql-master2/conf/my.cnf
配置内容
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=2
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
#设置需要复制的数据库
binlog-do-db=users
## 开启二进制日志功能
log-bin=mall-mysql-bin
#设置logbin格式
binlog_format=STATEMENT
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
# 在作为从数据库的时候,有写入操作也要更新二进制日志文件
log-slave-updates
#表示自增长字段每次递增的量,指自增字段的起始值,其默认值是1,取值范围是1 .. 65535
auto-increment-increment=2
# 表示自增长字段从哪个数开始,指字段一次递增多少,他的取值范围是1 .. 65535
auto-increment-offset=2
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
masterMysqlTwo主键从2开始,每次增长2。
重启容器实例
docker restart masterMysqlTwo
进入容器,
docker exec -it masterMysqlTwo /bin/bash
连接数据库,如果成功则数据库安装好了
如果容器没有启动,使用日志命令,查看错误,基本上都是配置文件的错误,修改数据库配置文件就可以了。
docker logs 容器ID
4. 双从配置
4.1 部署SlaveMysql1
创建SlaveMysql1容器
docker run -p 3508:3306 --name SlaveMysql1 -v /mysqldata/mysql-slave1/log:/var/log/mysql -v /mysqldata/mysql-slave1/data:/var/lib/mysql -v /mysqldata/mysql-slave1/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
[root@bogon /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2ab6da4dac4b mysql:5.7 "docker-entrypoint.s…" 14 minutes ago Up 8 minutes 33060/tcp, 0.0.0.0:3509->3306/tcp, :::3509->3306/tcp masterMysqlTwo
b3c237fe1bfc mysql:5.7 "docker-entrypoint.s…" 25 minutes ago Up 21 minutes 33060/tcp, 0.0.0.0:3507->3306/tcp, :::3507->3306/tcp masterMysqlOne
[root@bogon /]# docker run -p 3508:3306 --name SlaveMysql1 -v /mysqldata/mysql-slave1/log:/var/log/mysql -v /mysqldata/mysql-slave1/data:/var/lib/mysql -v /mysqldata/mysql-slave1/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
c26719a1d70a7266dce531c5f28bc4cd7b48c494406e15e8bfd2825dd0cb79fb
[root@bogon /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c26719a1d70a mysql:5.7 "docker-entrypoint.s…" 34 seconds ago Up 30 seconds 33060/tcp, 0.0.0.0:3508->3306/tcp, :::3508->3306/tcp SlaveMysql1
2ab6da4dac4b mysql:5.7 "docker-entrypoint.s…" 14 minutes ago Up 8 minutes 33060/tcp, 0.0.0.0:3509->3306/tcp, :::3509->3306/tcp masterMysqlTwo
b3c237fe1bfc mysql:5.7 "docker-entrypoint.s…" 25 minutes ago Up 22 minutes 33060/tcp, 0.0.0.0:3507->3306/tcp, :::3507->3306/tcp masterMysqlOne
[root@bogon /]#
修改配置文件
vi /mysqldata/mysql-slave1/conf/my.cnf
配置内容
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=3
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
## 开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用
log-bin=mall-mysql-slave1-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
## relay_log配置中继日志
relay_log=mall-mysql-relay-bin
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1
## slave设置为只读(具有super权限的用户除外)
read_only=1
重启容器实例
docker restart SlaveMysql1
进入容器
docker exec -it SlaveMysql1 /bin/bash
连接数据库,如果成功则数据库安装好了
[root@bogon /]# docker exec -it SlaveMysql1 /bin/bash
bash-4.2# 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 2
Server version: 5.7.44-log MySQL Community Server (GPL)
Copyright (c) 2000, 2023, 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>
4.2 部署SlaveMysql2
创建SlaveMysql2容器
docker run -p 3505:3306 --name SlaveMysql2 -v /mysqldata/mysql-slave2/log:/var/log/mysql -v /mysqldata/mysql-slave2/data:/var/lib/mysql -v /mysqldata/mysql-slave2/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
[root@bogon /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c26719a1d70a mysql:5.7 "docker-entrypoint.s…" 15 minutes ago Up 3 minutes 33060/tcp, 0.0.0.0:3508->3306/tcp, :::3508->3306/tcp SlaveMysql1
2ab6da4dac4b mysql:5.7 "docker-entrypoint.s…" 30 minutes ago Up 24 minutes 33060/tcp, 0.0.0.0:3509->3306/tcp, :::3509->3306/tcp masterMysqlTwo
b3c237fe1bfc mysql:5.7 "docker-entrypoint.s…" 41 minutes ago Up 37 minutes 33060/tcp, 0.0.0.0:3507->3306/tcp, :::3507->3306/tcp masterMysqlOne
[root@bogon /]# docker run -p 3505:3306 --name SlaveMysql2 -v /mysqldata/mysql-slave2/log:/var/log/mysql -v /mysqldata/mysql-slave2/data:/var/lib/mysql -v /mysqldata/mysql-slave2/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
ed600ae2684346b9e6f55c9d1f93b6203ec55220ac5f455bbb3928fa046a7c57
[root@bogon /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ed600ae26843 mysql:5.7 "docker-entrypoint.s…" 11 seconds ago Up 6 seconds 33060/tcp, 0.0.0.0:3505->3306/tcp, :::3505->3306/tcp SlaveMysql2
c26719a1d70a mysql:5.7 "docker-entrypoint.s…" 16 minutes ago Up 3 minutes 33060/tcp, 0.0.0.0:3508->3306/tcp, :::3508->3306/tcp SlaveMysql1
2ab6da4dac4b mysql:5.7 "docker-entrypoint.s…" 30 minutes ago Up 24 minutes 33060/tcp, 0.0.0.0:3509->3306/tcp, :::3509->3306/tcp masterMysqlTwo
b3c237fe1bfc mysql:5.7 "docker-entrypoint.s…" 41 minutes ago Up 37 minutes 33060/tcp, 0.0.0.0:3507->3306/tcp, :::3507->3306/tcp masterMysqlOne
[root@bogon /]#
修改配置文件
vi /mysqldata/mysql-slave2/conf/my.cnf
配置内容
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=4
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
## 开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用
log-bin=mall-mysql-slave1-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
## relay_log配置中继日志
relay_log=mall-mysql-relay-bin
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1
## slave设置为只读(具有super权限的用户除外)
read_only=1
重启容器实例
docker restart SlaveMysql2
进入容器
docker exec -it SlaveMysql2 /bin/bash
连接数据库,如果成功则数据库安装好了
[root@bogon /]# docker exec -it SlaveMysql2 /bin/bash
bash-4.2# 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 2
Server version: 5.7.44-log MySQL Community Server (GPL)
Copyright (c) 2000, 2023, 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>
5. 双主服务器创建Slave账号并授权
5.1 masterMysqlOne创建同步账号
# 创建用户
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
# 赋予权限
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
# 刷新权限
FLUSH PRIVILEGES;
5.2 masterMysqlTwo创建同步账号
# 创建用户
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
# 赋予权限
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
# 刷新权限
FLUSH PRIVILEGES;
创建步骤与sql语句一样,注意一定要刷新权限,否则可能会不生效,创建用户完成后最好查询一下,查看是否存在。
6. 双从复制主机
6.1 SlaveMysql1复制 masterMysqlOne
masterMysqlOne主数据库中查看主从同步状态,其中file,positon用于主从配置
show master status;
进入从机SlaveMysql1容器,连接数据库
docker exec -it SlaveMysql1 /bin/bash
mysql -uroot -p123456
配置主从复制
change master to master_host='192.168.0.15', master_user='slave', master_password='123456', master_port=3507, master_log_file='mall-mysql-bin.000003', master_log_pos=784,master_connect_retry=30;
master_log_file=查询状态中file
master_log_pos=查询状态中positon
mysql> change master to master_host='192.168.0.15', master_user='slave', master_password='123456', master_port=3507, master_log_file='mall-mysql-bin.000003', master_log_pos=784,master_connect_retry=30;
Query OK, 0 rows affected, 2 warnings (0.04 sec)
在从数据库中查看主从同步状态:no代表没有开始复制数据
show slave status \G;
在从数据库中开启主从同步
start slave;
mysql> start slave;
Query OK, 0 rows affected (0.03 sec)
mysql>
再次查看从数据库状态:yes表示已经同步
6.2 SlaveMysql2复制 masterMysqlTwo
masterMysqlTwo主数据库中查看主从同步状态,其中file,positon用于主从配置
show master status;
进入从机SlaveMysql2容器,连接数据库
docker exec -it SlaveMysql2 /bin/bash
mysql -uroot -p123456
配置主从复制
change master to master_host='192.168.0.15', master_user='slave', master_password='123456', master_port=3509, master_log_file='mall-mysql-bin.000001', master_log_pos=784,master_connect_retry=30;
master_log_file=查询状态中file
master_log_pos=查询状态中positon
mysql> change master to master_host='192.168.0.15', master_user='slave', master_password='123456', master_port=3509, master_log_file='mall-mysql-bin.000001', master_log_pos=784,master_connect_retry=30;
Query OK, 0 rows affected, 2 warnings (0.02 sec)
mysql>
在从数据库中查看主从同步状态:no代表没有开始复制数据
show slave status \G;
在从数据库中开启主从同步
start slave;
mysql> start slave;
Query OK, 0 rows affected (0.03 sec)
mysql>
再次查看从数据库状态:yes表示已经同步
docker配置从库配置,注意端口设置,不要混淆,最后在从库上查看状态,保证都已经开启复制
7. 主主复制
主主复制,操作与主从复制一样
7.1 masterMysqlOne复制 masterMysqlTwo
操作命令:
change master to master_host='192.168.0.15', master_user='slave', master_password='123456', master_port=3509, master_log_file='mall-mysql-bin.000001', master_log_pos=784,master_connect_retry=30;
启动复制
start slave;
查看状态
show slave status\G;
7.2 masterMysqlTwo复制 masterMysqlOne
操作命令
change master to master_host='192.168.0.15', master_user='slave', master_password='123456', master_port=3507, master_log_file='mall-mysql-bin.000003', master_log_pos=784,master_connect_retry=30;
启动复制
start slave;
查看状态
show slave status\G;
8.验证数据同步
8.1 连接四个数据库
使用数据库管理工具Navicat Premium,将配置的数据库都连接测试
主数据库masterMysqlOne:
主数据库masterMysqlTwo:
从数据库SlaveMysql1:
从主数据库SlaveMysql2
8.2 测试数据同步
主数据库masterMysqlOne创建数据库:users
CREATE DATABASE `users` CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci';
创建数据表:user
CREATE TABLE `user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(30) DEFAULT NULL COMMENT '名称',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
user写入数据
INSERT INTO `users`.`user` (`name`) VALUES ('刘洪霞');
INSERT INTO `users`.`user` (`name`) VALUES ('刘海波');
验证:主键增长从1开始,增长步长为2。
查看其他数据库是否已经同步了masterMysqlOne中的数据
masterMysqlTwo中验证
SlaveMysql1验证
SlaveMysql2验证
通过以上测试,主数据库masterMysqlOne中数据可以同步到其他主数据库与从数据库。
接下来我们在masterMysqlTwo中写入数据,测试主键增长及数据同步
INSERT INTO `users`.`user` (`name`) VALUES ('刘德华');
其他数据库数据查看
masterMysqlOne验证
SlaveMysql1验证
SlaveMysql2验证
可以看到,其他数据库也能同步到数据
9.配置文件说明
服务器唯一ID,每个mysql数据库的id唯一
server-id=3
启用二进制日志
log-bin=mysql-bin
设置不要复制的数据库,可设置多个
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
设置需要复制的数据库
binlog-do-db=users
设置logbin格式
STATEMENT:记录每条 SQL 语句
ROW:记录每行数据的变化
MIXED:结合 STATEMENT 和 ROW,根据情况自动选择最合适的格式
binlog_format=STATEMENT
在作为从数据库的时候,有写入操作也要更新二进制日志文件
log-slave-updates
自增长字段每次递增的量,指自增字段的起始值,其默认值是1,取值范围是1 .. 65535
auto-increment-increment=2
表示自增长字段从哪个数开始,指字段一次递增多少,他的取值范围是1 .. 65535
auto-increment-offset=2
跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
slave启用中继日志
relay-log=mysql-relay
slave设置为只读(具有super权限的用户除外)
read_only=1
二进制日志过期清理时间。默认值为0,表示不自动清理
expire_logs_days=7
10.最后
感谢大家,请大家多多支持!