MySQL的主从同步是一个很成熟的架构,优点为:
①在从服务器可以执行查询工作(读),降低主(master)服务器压力;
②在从主服务器进行备份,避免备份期间影响主服务器服务;
③当主服务器出现问题时,可以切换到从服务器。
但是MySQL的主从同步一直有从库延迟的问题,那么为什么会有这种问题。这种问题如何解决呢?
内容:
1. 主从原理
2. MySQL数据库主从同步延迟现象。
3. MySQL数据库主从同步延迟原因。
4. MySql数据库从库同步的延迟解决方案
1、主从原理
1. master服务器将数据的改变都记录到二进制binlog日志中,只要master上的数据发生改变,则将其改变写入二进制日志;
2. salve服务器会在一定时间间隔内对master二进制日志进行探测其是否发生改变,如果发生改变,则开始一个I/O Thread请求master二进制事件
3. 同时主节点为每个I/O线程启动一个dump线程,用于向其发送二进制事件,并保存至从节点本地的中继日志中
4. 从节点将启动SQL线程从中继日志中读取二进制日志,在本地重放,使得其数据和主节点的保持一致
5.最后I/O Thread和SQL Thread将进入睡眠状态,等待下一次被唤醒.
需要理解:
1)从库会生成两个线程,一个I/O线程,一个SQL线程;
2)I/O线程会去请求主库的binlog,并将得到的binlog写到本地的relay-log(中继日志)文件中;
3)主库会生成一个log dump线程,用来给从库I/O线程传binlog;
4)SQL线程,会读取relay log文件中的日志,并解析成sql语句逐一执行;
相关参数:
首先在服务器上执行show slave satus;可以看到很多同步的参数:
Master_Log_File: SLAVE中的I/O线程当前正在读取的主服务器二进制日志文件的名称Read_Master_Log_Pos: 在当前的主服务器二进制日志中,SLAVE中的I/O线程已经读取的位置
Relay_Log_File: SQL线程当前正在读取和执行的中继日志文件的名称
Relay_Log_Pos: 在当前的中继日志中,SQL线程已读取和执行的位置
Relay_Master_Log_File: 由SQL线程执行的包含多数近期事件的主服务器二进制日志文件的名称
Slave_IO_Running: I/O线程是否被启动并成功地连接到主服务器上
Slave_SQL_Running: SQL线程是否被启动
Seconds_Behind_Master: 从属服务器SQL线程和从属服务器I/O线程之间的时间差距,单位以秒计。
2、MySQL数据库主从同步延迟现象。
show slave status显示参数Seconds_Behind_Master不为0,这个数值可能会很大
show slave status显示参数Relay_Master_Log_File和Master_Log_File显示bin-log的编号相差很大,说明bin-log在 从库上没有及时同步,所以近期执行的bin-log和当前IO线程所读的bin-log相差很大
mysql的从库数据目录下存在大量mysql-relay-log日志,该日志同步完成之后就会被系统自动删除,存在大量日志,说明主从同步延迟很厉害
3. MySQL数据库主从同步延迟原因。
答:谈到MySQL数据库主从同步延迟原理,得从mysql的数据库主从复制原理说起,mysql的主从复制都是单线程的操作,主库对所有DDL和DML产生binlog,binlog是顺序写,所以效率很高,slave的Slave_IO_Running线程到主库取日志,效率比较高,下一步,问题来了,slave的Slave_SQL_Running线程将主库的DDL和DML操作在slave实施。DML和DDL的IO操作是随机的,不是顺序的,成本高很多,还可能与slave上的其他查询产生lock争用,由于Slave_SQL_Running也是单线程的,所以一个DDL卡主了,需要执行10分钟,那么所有之后的DDL会等待这个DDL执行完才会继续执行,这就导致了延时。有朋友会问:“主库上那个相同的DDL也需要执行10分,为什么slave会延时?”,答案是master可以并发,Slave_SQL_Running线程却不可以。
当主库的TPS并发较高时,产生的DDL数量超过slave一个sql线程所能承受的范围,那么延时就产生了,当然还有就是可能与slave的大型query语句产生了锁等待。
4. MySql数据库从库同步的延迟解决方案
1)、架构方面
1.业务的持久化层的实现采用分库架构,mysql服务可平行扩展,分散压力。
2.单个库读写分离,一主多从,主写从读,分散压力。这样从库压力比主库高,保护主库。
3.服务的基础架构在业务和mysql之间加入memcache或者redis的cache层。降低mysql的读压力。
4.不同业务的mysql物理上放在不同机器,分散压力。
5.使用比主库更好的硬件设备作为slave总结,mysql压力小,延迟自然会变小。
2)、硬件方面
1.采用好服务器,比如4u比2u性能明显好,2u比1u性能明显好。
2.存储用ssd或者盘阵或者san,提升随机写的性能。
3.主从间保证处在同一个交换机下面,并且是万兆环境。
总结,硬件强劲,延迟自然会变小。一句话,缩小延迟的解决方案就是花钱和花时间。
3)、mysql主从同步加速
1、sync_binlog在slave端设置为0
2、–logs-slave-updates 从服务器从主服务器接收到的更新不记入它的二进制日志。
3、直接禁用slave端的binlog
4、slave端,如果使用的存储引擎是innodb,innodb_flush_log_at_trx_commit =2
5、innodb_flushlog也可以设置为0来提高sql的执行效率。