主从复制及架构
主从复制架构和原理
-
主库记录更新事件:
- 主库(Master)的更新事件(如update、insert、delete等)会被按照顺序写入到二进制日志(binary log,简称binlog)中。这些日志记录了数据库表结构和内容的变更。
-
从库连接主库并请求更新:
- 从库(Slave)连接到主库后,会请求从主库的binlog中读取更新记录。主库会为每个连接的从库创建一个binlog dump线程,用于发送binlog中的更新记录给从库。
-
从库接收并写入中继日志:
- 从库接收到主库发送的binlog内容后,会将其写入到本地的中继日志(relay log)中。中继日志是从库用于暂存从主库接收到的binlog内容的临时文件。文件名的格式是:
从服务器名 - relay-bin.序号
。中继日志还有一个索引文件:从服务器名 - relay-bin.index
,用来定位当前正在使用的中继日志
- 从库接收到主库发送的binlog内容后,会将其写入到本地的中继日志(relay log)中。中继日志是从库用于暂存从主库接收到的binlog内容的临时文件。文件名的格式是:
-
从库执行更新:
- 从库还会创建一个SQL线程,用于读取中继日志中的内容,并将其解析成具体的SQL语句,然后在从库上执行这些SQL语句,从而实现数据的同步。
复制架构
- 主服务器(Master) :负责处理客户端的写请求(INSERT、UPDATE、DELETE等)和所有的读请求(如果配置允许)。每次数据更新后,主服务器会记录这些更改到二进制日志(Binary Log)中。
- 从服务器(Slave) :从服务器连接到主服务器,并请求从主服务器的二进制日志中读取数据更改事件。然后,从服务器会在本地重放这些事件,以确保与主服务器的数据保持同步。
主从复制根据同步方式的不同,可以分为异步复制、同步复制和半同步复制:
- 异步复制:这是MySQL默认的复制模式。主库在执行完客户端提交的事务后会立刻将结果返回给客户端,并不关心从库是否已经接收到并处理了这些事务。这种模式的优点是返回客户端无延迟,但缺点是可能会导致主从数据不一致,甚至数据丢失。
- 同步复制:在这种模式下,主库在提交事务前必须确保所有从库都已经接收到并处理了这些事务。这种模式的优点是保证了主从数据的一致性,但缺点是可能会因为等待从库处理而降低主库的性能。
- 半同步复制:半同步复制介于异步复制和同步复制之间。主库在提交事务时会等待至少一个从库确认已经接收到并写入到relay log中,然后才会提交事务。这种模式既保证了数据的一致性,又避免了同步复制可能带来的性能问题。
实现主从复制配置
-
启用二进制日志: 在MySQL的配置文件(通常是
my.cnf
或my.ini
)中,确保二进制日志被启用,并指定一个唯一的服务器ID。ini复制代码 [mysqld] log-bin=mysql-bin server-id=1
-
创建复制账户: 在主服务器上,创建一个专用的复制账户,该账户将用于从服务器连接到主服务器。
sql复制代码 CREATE USER 'replicator'@'%' IDENTIFIED BY 'password'; GRANT REPLICATION SLAVE ON *.* TO 'replicator'@'%'; FLUSH PRIVILEGES;
注意:出于安全考虑,不建议在生产环境中使用
%
作为主机名,而是应该使用具体的从服务器IP地址。 -
记录二进制日志的位置: 在主服务器上,记录下当前的二进制日志文件名和位置,这些信息将用于配置从服务器。
sql复制代码 SHOW MASTER STATUS;
2. 配置从服务器
官网参考
dev.mysql.com/doc/refman/… dev.mysql.com/doc/refman/… dev.mysql.com/doc/refman/… mariadb.com/kb/en/libra…
-
修改配置文件: 在从服务器的配置文件中,设置服务器ID(确保与主服务器不同),并启用中继日志(Relay Log)。
[mysqld] server-id=2 relay-log=mysqld-relay-bin
-
配置复制: 使用
CHANGE MASTER TO
语句在从服务器上配置复制。你需要指定主服务器的IP地址、复制账户的用户名和密码、以及从SHOW MASTER STATUS
命令中获取的二进制日志文件名和位置。CHANGE MASTER TO MASTER_HOST='master_ip', MASTER_USER='replicator', MASTER_PASSWORD='password', MASTER_LOG_FILE='recorded_log_file_name', MASTER_LOG_POS=recorded_log_position;
-
启动复制: 在从服务器上启动复制过程。
START SLAVE;
-
检查复制状态: 使用
SHOW SLAVE STATUS\G
命令来检查从服务器的复制状态。确保Slave_IO_Running
和Slave_SQL_Running
两个状态都是Yes
。
注意事项
- 安全性:确保复制账户的密码复杂且只授权必要的权限。
- 网络稳定性:主从服务器之间的网络连接应稳定可靠。
- 监控和故障转移:实施适当的监控和故障转移策略,以应对主服务器故障的情况。
- 数据一致性:定期检查和验证主从服务器之间的数据一致性。
主从复制 实战
假设主节点的数据库已经运行了一段时间,产生了一定量的数据,主从复制只能复制开启后数据,那之前的数据如何处理?
主节点
[root@localhost ~]#systemctl stop firewalld
[root@localhost ~]#setenforce 0
[root@localhost ~]#mysql -uroot -pabc123 < hellodb_innodb.sql
先备份
#开启二进制日志
[root@localhost ~]#vim /etc/my.cnf
erver-id=102
log-bin=/data/mysql/binlog/mysql-bin
[root@localhost ~]# mkdir -p /data/mysql/binlog
[root@localhost ~]# chown mysql.mysql /data/ -R
[root@localhost ~]# systemctl restart mysqld
[root@localhost ~]#mysqldump -uroot -pabc123 -A -F --master-data=1 --single-transaction |gzip > /data/all.sql.gz
[root@localhost ~]#mysql -uroot -pabc123
create user test@'192.168.10.%' identified by "Admin@123"; #新建主从复制用户
grant replication slave on *.* to test@'192.168.10.%'; # 授权主从复制用户
[root@localhost ~]#scp /data/all.sql 192.168.10.10:/opt
从节点 从节点
[root@localhost ~]#systemctl stop firewalld
[root@localhost ~]#setenforce 0
#开启二进制日志
[root@localhost ~]#vim /etc/my.cnf
server-id=102
log-bin=/data/mysql/binlog/mysql-bin
[root@localhost ~]# mkdir -p /data/mysql/binlog
[root@localhost ~]# chown mysql.mysql /data/ -R
[root@localhost ~]# systemctl restart mysqld
#修改备份脚本
[root@localhost ~]# vim /opt/all.sql
# 找到 CHANGE MASTER TO 的行修改如下
CHANGE MASTER TO
MASTER_HOST='192.168.10.10',
MASTER_USER='test',
MASTER_PASSWORD='Admin@123',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=154;
#由于之前再备份的时候加入了 --master-data=1 选项 就添加了主从复制的选项000002文件的154位置往后开始主从复制
#000002文件154位置之前的 配置由 备份文件自行实现
[root@localhost ~]#mysql -uroot -pabc123
#进入数据库
mysql> set sql_log_bin=0; #关闭二进制日志
Query OK, 0 rows affected (0.00 sec)
mysql> source /opt/all.sql #导入数据库
mysql> start slave;
mysql> show slave status\G; #查看从节点的状态
成功后可以检验主从复制的 情况
复制错误解决方法
模拟错误
在从的数据库表中查一条数据此时 会有报错
Could not execute Write_rows event on table hellodb.teachers; Duplicate entry '5' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000005, end_log_pos 1346
明确指出,主键值 5 已经存在于表中,因此无法再次插入。
1.可以在从服务器忽略几个主服务器的复制事件,此为global变量,或指定跳过事件的ID
可以跳过错误
stop slave;
set global sql_slave_skip_counter=1;
start slave;
- 重新建立从服务器 数据差过大情况下
级联 主从复制
需要在中间的从服务器启用以下配置 ,实现中间slave节点能将master的二进制日志在本机进行数据库更新,并且也同时更新本机的二进制,从而实现级联复制. 2级节点必须要添加log_slave_updates
从服务器在执行从主服务器接收到的更新操作时,也会将这些操作记录到自己的二进制日志中。
实例:
主节点
root@localhost ~]#vim /etc/my.cnf
#修改文件
[mysqld]
server_id=100
log-bin=/data/mysql/mysql-bin
[root@localhost ~]#mkdir /data/mysql/ -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld
select @@server_id;
#可以查看serverid 默认都是1
show master status;
#查看二进制日志位置
grant replication slave on *.* to test@'192.168.10.%' identified by 'Admin@123';
#建立复制用户
show processlist;
#查看线程
2级节点
root@localhost ~]#vim /etc/my.cnf
#修改文件
[mysqld]
server_id=101
log-bin=/data/mysql/mysql-bin
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
log_slave_updates #级联复制中间节点的必选项,MySQL8.0此为默认值,可以不要人为添
#read only #只读可加
[root@localhost ~]#mkdir /data/mysql/ -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld
grant replication slave on *.* to test@'192.168.91.%' identified by 'Admin@123';
#建立复制用户
下面修改配置 命令较长可以使用帮助
help change master to
CHANGE MASTER TO
MASTER_HOST='192.168.10.1',
MASTER_USER='test',
MASTER_PASSWORD='abc123',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=604;
注意最后分号
show slave status\G;
#查看设置的状态
Seconds_Behind_Master: NULL #目前数据差
start slave;
#开启线程,开启主从复制
show master logs;
#查看 从节点的复制位置
从节点
root@localhost ~]#vim /etc/my.cnf
#修改文件
[mysqld]
server_id=102
log-bin=/data/mysql/mysql-bin
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
#read only #只读可加
[root@localhost ~]#mkdir /data/mysql/ -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld
下面修改配置 命令较长可以使用帮助
help change master to
CHANGE MASTER TO
MASTER_HOST='192.168.10.10',
MASTER_USER='test',
MASTER_PASSWORD='Admin@123',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=448;
注意最后分号
show slave status\G;
#查看设置的状态
Seconds_Behind_Master: NULL #目前数据差
start slave;
#开启线程,开启主从复制
12.5 半同步复制
默认情况下,MySQL的复制功能是异步的,异步复制可以提供最佳的性能,主库把binlog日志发送给从库即结束,并不验证从库是否接收完毕。这意味着当主服务器或从服务器端发生故障时,有可能从服务器没有接收到主服务器发送过来的binlog日志,这就会造成主服务器和从服务器的数据不一致,甚至在恢复时造成数据的丢失
实现:
rpm -ql mysql-community-server |grep semisync
#需要安装插件
[root@localhost ~]#vim /etc/my.cnf
#修改文件
[mysqld]
server_id=100
log-bin=/data/mysql/mysql-bin
rpl_semi_sync_master_enabled=ON
rpl_semi_sync_master_timeout=3000
#修改此行,需要先安装semisync_master.so插件后,再重启,否则无法启动 开启半同步
#设置3s内无法同步,也将返回成功信息给客户端
[root@localhost ~]#mkdir /data/mysql/ -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld
[root@localhost ~]#mysql -uroot -pAdmin@123
mysql>INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; #永久安装插件
mysql>UNINSTALL PLUGIN rpl_semi_sync_master ;
rpm -ql mysql-community-server |grep semisync #查看插件
mysql>SET GLOBAL rpl_semi_sync_master_enabled=1; #临时修改变量
mysql>SET GLOBAL rpl_semi_sync_master_timeout = 3000; #超时长1s,默认值为10s
mysql>SHOW GLOBAL VARIABLES LIKE '%semi%';
#查看半同步状态
show global status like '%semi%';
#查看半同步客户端
show master status;
grant replication slave on *.* to test@'192.168.10.%' identified by 'Admin@123';
#建立复制用户
从节点
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
#安装插件
[root@slave1 ~]#vim /etc/my.cnf
[mysqld]
server-id=101
rpl_semi_sync_slave_enabled=ON #修改此行,需要先安装semisync_slave.so插件后,再重启,否则无法启动
CHANGE MASTER TO
MASTER_HOST='192.168.10.1',
MASTER_USER='test',
MASTER_PASSWORD='Admin@123',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000003',
MASTER_LOG_POS=448;
注意最后分号
start slave;
show global status like '%semi%';
#查看状态 主从状态
mysql>INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
mysql>SET GLOBAL rpl_semi_sync_slave_enabled=1; #临时修改变量
mysql> SHOW GLOBAL VARIABLES LIKE '%semi%';
从节点二同理
转载自:https://juejin.cn/post/7388338139633336371