当我们的业务越来越来越庞大的时候,如果是单个MySQL服务器的情况下,负载过重的时候就容易造成服务宕机,这个时候我们该怎么解决呢?可以使用MySQL自带的主从复制(主服务器负责写,从服务器负责读),可以帮助我们实现负载均衡和读写分离。
主从复制分为:
一主多从是目前最多的主从架构,实现了HA(高可用),也可以读写分离
多主一从可以将多个MySQL数据可备份到一个性能好的从服务器上
类似于主从复制,每个master既是master,又是另外一台服务器的slave(既当爹又当娘),每一方做的变更,也会同步到另一方的数据库中。
部分slave不连接主节点,而是连接从节点,如果主节点有太多的从节点,会损耗部分性能用于复制数据,我们可以让部分从节点连接主节点,部分从节点连接从节点,这样可以缓解主节点的压力,并且不影响数据一致性。
MySQL主从复制是基于主服务器在binlog中记录了所有对数据库的更改(insert,update,delete,create/alter/drop table, grant 等等),因此要进行复制,必须在主服务器上启用binlog
主从复制的原理其实就是把主服务上的binlog日志复制到从服务器上执行一遍,这样从服务器上的数据就和主服务器上的数据同步了。
1.从库会生成两个线程,一个IO线程,一个SQL线程
2.IO线程会去请求主线程的binlog,并将得到的数据写到Relaylog(中继日志)中。
3.主库会生成一个log dump thread,用于给从库IO thread 传输binlog。
4.从库的SQL线程会读取Relaylog(中继日志)的数据,并解析成具体操作,来实现主从的最终数据一致。
主库配置, Linux 配置下是/etc/my.cnf,windows是my.ini文件
我的主服务器是部署在阿里云上,从服务器在本地,需要注意阿里的安全策略以及服务器的防火墙
主服务器
[mysqld]
# 根目录
basedir = /usr/local/mysql
# 数据目录
datadir = /usr/local/mysql/data
# 主机服务器唯一id,主从环境下必须配置且唯一
server-id = 1103
# 免密登录,当忘记密码后可以使用
#skip-grant-tables
#default_authentication_plugin=mysql_native_password
# binarylog,二进制日志文件位置,主从必须配置
log-bin = /usr/local/mysql/data/mysqlbin
# errorlog,错误日志
log-error = /usr/local/mysql/data/mysql
# 当mysql主从版本不一致的时候(一般来说主版本低)
binlog-checksum = none
socket = /usr/local/mysql/mysql.sock
character-set-server=utf8
# 表名不区分大小写(linux下默认区分,windows默认不区分),但需要注意的是linux环境下mysql在8.0以上版本必须在初始化时就进行设置
lower_case_table_names=1
port = 3306
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
[client]
socket = /usr/local/mysql/mysql.sock
#mysql 8.0 以下
#第一个*代表数据库名,第二个*代表表名,*代表任意,zhangsan为创建给从库的用户,从库ip可以用具体ip,也可以用%代表任意,password 为创建的 用户密码
grant replication slave on *.* to 'zhangsan'@'从库IP' identified by 'password';
# 刷新配置
flush privileges;
# mysql 8.0以上
# mysql 8 以上必须先创建用户再进行授权
CREATE USER 'zhangsan'@'从库ip' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'zhangsan'@'%'
flush privileges;
我们平时可以用一些命令来查看主从的状态
#查看主状态
show master status;
#查看从状态
show slave status;
# 在cmd下或者linux 下可以使用
show master\G
show slave\G
从服务器
# 我们只需要添加这些即可
server-id = 1
log-bin = C:/ProgramData/MySQL/MySQL Server 8.0\Data\binlog
# 连接主库
CHANGE MASTER TO MASTER_HOST='主服务Ip'
#上面配置的用户名和密码
MASTER_USER=‘zhangsan’
MASTER_PASSWORD='password'
# 可以在主服务下通过show master status; 或者 show master\G 查看 File 和 Position
MASTER_LOG_FILE='File', MASTER_LOG_POS=Position;
配置完之后
# 启动主从
start slave;
# 停止主从
stop slave;
当启动后我们通过 show slave status;
查看状态,如果Slave_IO_Running
和Slave_IO_Running
都是YES,那么恭喜你配置成功了。
一个主库,对应多个或者单个从库,数据异步的同步
到从库。
异步复制模式下,主节点不会主动推送数据到从节点,主库在处理完客户端提交的事务后会立即将结果返回给客户端,并不关心从库是否接收并处理,但这样也面临着风险,如果主节点崩溃,如果强行将从库提升为主,可能会导致数据不一致。
MySQL cluster 中特有的复制方式。
当主库执行完一个事务,然后所有的从库都复制了该事务并成功执行完才返回成功信息给客户端,性能较低
在异步复制的基础上,确保主库上的事务在提交之前至少有一个从库已经收到该事务并执行完成。
介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到 relay log 中才返回成功信息给客户端(只能保证主库的 Binlog 至少传输到了一个从节点上),否则需要等待直到超时时间然后切换成异步模式再提交
半同步模式不是 MySQL 内置的,从 MySQL 5.5
开始集成,需要 master 和 slave 安装插件开启半同步模式。
在异步复制的基础上,设置主库和从库的数据同步延迟时间,保证数据同步最少是这个时间。
基于语句的复制模式下,主库会记录那些造成数据更改的查询,当备库读取并重放这些事件时,实际上只把主库上执行过的SQL再执行一遍。这种方式简单,二进制文件小,传输带宽占用小,但是语句更新依赖于某些因素,例如时间戳,所以一般我们应该在代码的层面做好处理,而不是在MySQL中。
MySQL5.1开始支持基于行的复制,这种方式会将实际数据记录在二进制日志中。这样导致复制的压力比较大,日志占用的空间大,传输带宽占用大。但是这种方式比基于语句的复制要更加精确。
MySQL默认情况下使用的是基于语句的复制方式,但如果发现语句无法呗正确地复制,就切换基于行的复制模式