MySQL:如何为MySQL搭建一套主从复制架构

准备

  • 首先,它应该搭建在两台机器上,一台机器放主库,一台机器放从库。
  • 然后,要确保主库和从库的server-id是不同的,另外,主库必须打开binlog功能

异步复制

(1) 首先在主库上要创建一个用于主从复制的账号:

create user 'backup_user'@'192.168.31.%' identified by 'backup_123';
grant replication slave on . to 'backup_user'@'192.168.31.%';
flush privileges;

(2) 在凌晨的时候,宣布系统进入维护状态,然后对主库和从库做一个数据备份和导入

  • 可以使用如下的mysqldump工具把主库在这个时刻的数据做一个全量备份,但是此时一定不能允许系统操作主库了,主库的数据此时是不能有变动的
/usr/local/mysql/bin/mysqldump --single-transaction -uroot -proot --master-data=2 -A >
backup.sql
  • mysqldump工具就在你的MySQL安装目录的bin目录下,然后用上述命令就可以对你主库所有的数据都做一个备份,备份会以SQL语句的方式进入指定的backup.sql文件,只要执行这个backup.sql文件,就可以恢复出来跟主库一样的数据。
  • 上面命令里的–master-data=2,意思是说备份SQL文件里,要记录一下此时主库的binlog文件和position号。这是为主库复制做准备的
  • 接着你可以通过scp之类的命令把这个backup.sql文件拷贝到你的从库服务器上去就行了

(3)

  • 在从库上执行命令,把backup.sql文件里的语句都执行一遍,这就相当于把主库所有的数据都还原到从库上去了,主库上的所有database、table以及数据,在从库里全部都有了。
  • 接着在从库上执行下面的命令去指定从主库进行复制
CHANGE MASTER TO MASTER_HOST='192.168.31.229',
MASTER_USER='backup_user',MASTER_PASSWORD='backup_123',MASTER_LOG_FILE='mysqlbin.000015',MASTER_LOG_POS=1689;
  • 可能有人会疑惑master的binlog文件和position是怎么知道的?这不就是之前我们mysqldump导出的backup.sql里就有,大家在执行上述命令前,打开那个backup.sql就可以看到如下内容:
MASTER_LOG_FILE='mysql-bin.000015',MASTER_LOG_POS=1689

(4)

  • 接着执行一个开始进行主从复制的命令:start slave,再用show slave status查看一下主从复制的状态,主要看到Slave_IO_Running和Slave_SQL_Running都是Yes就说明一切正常了,主从开始复制了。
  • 接着就可以在主库插入一条数据,然后在从库查询这条数据,只要能够在从库查到这条数据,就说明主从复制已经成功了。

这仅仅是一种最简单的主从复制----异步复制。通过从库异步拉取binlog来同步的。所以可能会出现短暂的主从不一致的问题。比如你在主库刚插入数据,结果在从库立马查询,可能是查不到的

主从复制架构搭建好之后,就可以实现读写分离了。

比如可以用mycat或者sharding-sphere之类的中间件,就可以实现你的系统写入主库,从从库去读取了。

但是现在搭建出来的主从复制架构有一个问题,那就是:

  • 这是一种异步复制,也就是说,主库把日志写入binlog了,接着自己就提交事务返回了,不会管从库到底有没有收到日志
  • 万一此时主库的binlog还没有同步到从库,结果主库宕机了,此时数据不就丢失了吗?即使你做了高可用自动切换,但是里面是没有刚才写入的数据的,所以这种方式是有问题的。

因此一般来说搭建主从复制,都是采取半同步的方式复制的。这个半同步的意思是,你主库写入数据,日志进入binlog之后,起码得确保binlog日志复制到从库了,你再告诉客户端说本次写入事务成功了

这样起码你主库突然崩了,它之前写入成功的数据的binlog日志都是到从库了,从库切换为主库,数据也不会丢的。

半同步复制

半同步复制有两种方式:

  • 一种是AFTER_COMMIT方式,它不是默认的,它的意思是说,主库写入日志到binlog,等待binlog复制到从库了,主库就提交自己的本地事务,接着等待从库返回给自己一个成功的响应,然后主库返回提交事务成功的响应给客户端。
  • 另外一种是现在MySQL5.7默认的方式,主库把日志写入binlog,并且复制给从库,然后开始等待从库的响应,反馈返回说成功给主库了,主库再提交事务,接着返回提交事务成功的响应给客户端。

总之,这种方式可以确保你每个事务在提交成功之前,binlog日志一定都复制到从库了,所以只要事务提交成功,就可以认为数据在从库也有一份了,那么主库崩溃,已经提交的事务的数据绝对不会丢失的

搭建半同步复制也很简单,在之前搭建好异步复制的基础之上,安装一下半同步复制插件就可以了

(1)先在主库中安装半同步复制插件,同时还得开启半同步复制功能:

install plugin rpl_semi_sync_master soname 'semisync_master.so';
set global rpl_semi_sync_master_enabled=on;
show plugins;

可以看到你安装了这个插件,那就ok了。

(2)接着在从库也是安装这个插件以及开启半同步复制功能:

install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
set global rpl_semi_sync_slave_enabled=on;
show plugins;

(3)重启从库的IO线程

stop slave io_thread; start slave io_thread;

(4)在主库上检查一下半同步复制是否正常运行

show global status like '%semi%';

如果看到了Rpl_semi_sync_master_status的状态是ON,那么就可以了。

到此半同步复制就开启成功了,其实一般来说主从复制都建议做成半同步复制,因为这样配合高可用切换机制,就可以保证数据库有一个在线的从库热备份主库的数据了,而且主要主库宕机,从库立马切换为主库,数据不丢失,数据库还高可用。

GTID搭建方式

一般大家在生成中都会采用半同步的复制模式,但是其实除了这种传统搭建模式之外,还有一些跟简单的搭建方式,比如GTID搭建方式。

(1)首先在主库进行配置:

gtid_mode=on
enforce_gtid_consistency=on
log_bin=on
server_id=单独设置一个
binlog_format=row

接着在从库进行配置:

gtid_mode=on
enforce_gtid_consistency=on
log_slave_updates=1
server_id=单独设置一个

(2)接着按照之前讲解的步骤在主库创建好用于复制的账号之后,就可以跟之前一样进行操作了,比如在主库dump出来一份数据,在从库里导入这份数据,利用mysqldump备份工具做的导出,备份文件里会有SET @@GLOBAL.GTID_PURGED=***一类的字样,可以照着执行一下就可以了。

接着其余步骤都是跟之前类似的,最后执行一下show master status,可以看到executed_gtid_set,里面记录的是执行过的GTID,接着执行一下SQL:select * from gtid_executed,可以查询到,对比一下,就会发现对应上了。
那么此时就说明开始GTID复制了。

主从复制架构中的数据延迟问题,应该如何解决

主从复制可能会有比较大的延迟。这个延迟是什么意思呢?

就是说主库可能已经写入了100条数据,结果从库才复制了50条数据,那么从库就比主库落后了50条数据。

这就是所谓的主从延迟。

可是为什么会产生这个主从延迟呢?

其实主库是多线程并发写入的,所以主库写入数据的速度可能是很快的

但是从库是单个线程缓慢拉取数据的,所以才会导致从库复制数据的速度比较慢

主从之间到底延迟了多少时间呢?

这个可以用一个工具来进行监控,比较推荐的是perconatoolkit工具集里的pt-heartbeat工具,它会在主库里创建一个heartbeat表,然后会有一个线程定时更新这个表里的时间戳字段,从库上就会有一个monitor线程会负责检查从库同步过来的heartbeat表里的时间戳。

把时间戳跟当前时间戳比较一下,其实就知道主从之间同步落后了多长时间了

那么这个主从同步延迟的问题,会导致一些什么样的不良情况呢?

如果你做了读写分离架构,写都往主库写,读都从从库读,那么你的系统刚写入一条数据到主库,接着代码里立即就在从库里读取,可能此时从库复制有延迟,你会读不到刚写入进去的数据!

另外就是有可能你的从库同步数据太慢了,导致你从库读取的数据都是落后和过期的,也可能会导致你的系统产生一定的业务上的bug。

怎么解决

(1)首先,应该尽可能的缩小主从同步的延迟时间。

  • 其实就是让从库也用多线程并行复制数据就可以了,这样从库复制数据的速度快了,延迟就会很低了。 MySQL 5.7就已经支持并行复制了,可以在从库里设置slave_parallel_workers>0,然后把slave_parallel_type设置为LOGICAL_CLOCK,就ok了。

  • 另外,如果你觉得还是要求刚写入的数据你立马强制必须一定可以读到,那么此时你可以使用一个办法,就是在类似MyCat或者Sharding-Sphere之类的中间件里设置强制读写都从主库走,这样你写入主库的数据,强制从主库里读取,一定立即可以读到的。

如果说你对数据丢失并不是强要求不能丢失的话,可以用异步模式来复制,再配合一下从库的并行复制机制。

如果说你要对MySQL做高可用保证数据绝对不丢失的话,建议还是用半同步机制比较好一些,同理最好是配合从库的并行复制机制。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值