How to build a master-slave backup with dual M structure?

Regarding MySQL master-slave construction, Song Ge has written many articles and recorded a video before. However, the previous one was a master-slave structure, but the friends know that in our project, a more common structure is the double-M structure, that is, two MySQL instances, each of which is the master and backup of each other, so that in the project When the master node is suddenly powered off or unavailable, the slave node can be quickly switched to the master. The architecture diagram is as follows:

In this structure, the status of two MySQL instances is equal, and they are the master and backup of each other. The way we judge who is the master and who is the slave mainly depends on readonly, and who is read-only, then who is the slave , so in this case, the master-slave switch is also very convenient, just modify the readonly attribute.

Next, let's build a dual-M master-slave backup to see what is the difference with the pure MS structure.

1. Preparations

The following configuration is based on Docker.

Here, we first prepare two machines:

  • M1:10.3.50.27:33061
  • M2:10.3.50.27:33062

1.1 M1 configuration

The configuration of M1 is only three steps, which is relatively easy:

1. Authorize the M2 server

GRANT REPLICATION SLAVE ON *.* to 'rep1'@'10.3.50.27' identified by '123';
FLUSH PRIVILEGES;
复制代码

Here it means that the M2 login user name is rep1, the password is 123, and you must log in from 10.3.50.27this address. After successful login, you can operate any table in any library. Among them, if you do not need to restrict the login address, you can replace the IP address with one %.

Note that in MySQL 8, there have been some changes in this area. User creation and authorization in MySQL8 need to be separated, and cannot be done in one step as above. The specific methods are as follows:

CREATE USER `rep1`@`10.3.50.27` IDENTIFIED WITH caching_sha2_password BY 'javaboy.COM';

GRANT Replication Slave ON *.* TO `rep1`@`10.3.50.27`;
复制代码

2. Modify the main library configuration file

Turn on binlog and set server-id. After each modification of the configuration file, the MySQL service must be restarted to take effect.

To enable binlog is to modify the MySQL configuration file mysqld.cnf, which is located in the container's /etc/mysql/mysql.conf.ddirectory .

For this configuration file, we make the following modifications:

[mysqld]
# 这个参数表示启用 binlog 功能,并指定 binlog 的存储目录
log-bin=javaboy_logbin
# 设置 binlog_format 格式,注意不要使用 STATEMENT
binlog_format=ROW
# 设置一个 binlog 文件的最大字节
# 设置最大 100MB
max_binlog_size=104857600

# 设置了 binlog 文件的有效期(单位:天)
expire_logs_days = 7

# binlog 日志只记录指定库的更新(配置主从复制的时候会用到)
binlog-do-db=javaboy_db

# binlog 日志不记录指定库的更新(配置主从复制的时候会用到)
#binlog-ignore-db=javaboy_no_db

# 写缓存多少次,刷一次磁盘,默认 0 表示这个操作由操作系统根据自身负载自行决定多久写一次磁盘
# 1 表示每一条事务提交都会立即写磁盘,n 则表示 n 个事务提交才会写磁盘
sync_binlog=0

# 为当前服务取一个唯一的 id(MySQL5.7 开始需要)
server-id=1
复制代码

Song Ge has already explained the meaning of each configuration in his gaze. Screenshot below:

As shown below:

  • log-bin:同步的日志路径及文件名,一定注意这个目录要是 MySQL 有权限写入的(我这里是偷懒了,直接放在了下面那个datadir下面)。
  • binlog-do-db:要同步的数据库名,当从机连上主机后,只有这里配置的数据库才会被同步,其他的不会被同步。
  • server-id: MySQL 在主从环境下的唯一标志符,给个任意数字,注意不能和 M2 重复,因为将来 server-id 用于标志 binlog 是由哪个库产生的,所以主从数据库的 server-id 千万不能一样,不然可能导致主从数据库 binlog 的循环复制问题。
  • 注意 binlog_format 的值为 ROW,具体原因在之前的文章中松哥已经和大家聊过了,这里就不再赘述。

配置完成后重启 MySQL 服务端:

docker restart mysql33061
复制代码

3. 查看 M1 当前二进制日志名和偏移量

这个操作的目的是为了在 M2 启动后,从这个点开始进行数据的恢复:

show master status;
复制代码

至此,M1 配置完成。

1.2 M2 配置

M2 的配置和 M1 一模一样,唯一不同的地方在于,M2 的 mysqld.cnf 这个文件中的 server-id=2,其他都一模一样,我就不重复了。

配置完成后,相当于 M2 现在也是一个主机,我们在 M2 上也可以执行 show master status; 命令,结果如下:

1.3 主从配置

接下来配置 M1 和 M2 分别为对方的主机。

M1 配置

先来配置给 M1 配置吧,执行如下命令设置主机:

change master to master_host='10.3.50.77',master_port=33062,master_user='rep1',master_password='123',master_log_file='javaboy_logbin.000001',master_log_pos=154;
复制代码

这里配置了主机地址、端口以及从机登录主机的用户名和密码,注意最后两个参数要和 M2 中的保持一致。

注意,由于 MySQL8 密码插件的问题,这个问题同样会给主从配置带来问题,所以在 MySQL8 配置主从上,上面这行命令需要添加 get_master_public_key=1,完整命令如下:

change master to master_host='10.3.50.77',master_port=33062,master_user='rep1',master_password='123',master_log_file='javaboy_logbin.000001',master_log_pos=154,get_master_public_key=1;
复制代码

3. 启动 slave 进程

start slave;
复制代码

启动之后查看从机状态:

show slave status\G;
复制代码

4. 查看 slave 的状态

主要是下面两项值都要为为 YES,则表示配置正确:

Slave_IO_Running: Yes
Slave_SQL_Running: Yes
复制代码

至此,配置完成,主机创建库,添加数据,从机会自动同步。

如果这两个有一个不为 YES ,表示主从环境搭建失败,此时可以阅读日志,查看出错的原因,再具体问题具体解决。

M2 配置

接下来再来配置 M2,M2 和 M1 的配置基本上是一致的,change master 中记得把地址和端口写对:

change master to master_host='10.3.50.77',master_port=33061,master_user='rep1',master_password='123',master_log_file='javaboy_logbin.000001',master_log_pos=154;
复制代码

配置完成后,现在 M1 和 M2 就互为主备了。

1.4 测试

测试分两步:

  • M1 中新建 javaboy_db 库,库中建 user 表,表中插入一条记录,然后查看 M2 中是否将数据同步过来了。
  • M2 中向 user 表中添加一条记录,查看 M1 中是否有对应的值。

经过测试,我们发现没问题,现在可以两边互相同步对方的数据了。

2. 谁主谁从

虽然是双 M 结构,但是在实际应用中还是得分个主从,那么双 M 该怎么分主从呢?

在生产环境中,我们一般会将备份节点设置为 read_only,也就是只读,防止有误操作,当然不用担心设置为 read_onlybinlog 的写入也被阻止,super 用户依然拥有写入权限。

设置全库只读的办法也很简单,首先我们执行如下 SQL 先看看对应变量的值:

show variables like 'read_only';
复制代码

可以看到,默认情况下,read_only 是 OFF,即关闭状态,我们先把它改为 ON,执行如下 SQL:

set global read_only=1;
复制代码

1 表示 ON,0 表示 OFF,执行结果如下:

这个 read_only 对 super 用户无效,所以设置完成后,接下来我们退出来这个会话,然后创建一个不包含 super 权限的用户,用新用户登录,登录成功之后,执行一个插入 SQL,结果如下:

可以看到,这个错误信息中说,现在的 MySQL 是只读的(只能查询),不能执行当前 SQL。

如此设置之后,在 master 发生异常需要主从切换的时候再将 slave 临时顶替上来。为了更好的做到主从同步,binlog 的类型建议使用 row 模式,关于 binlog 的三种模式,可以参考666!MySQL 的 binlog 的三种格式这么好玩!一文。

好啦,有问题欢迎留言讨论。

Guess you like

Origin juejin.im/post/7084174261715206158