小谈 MySQL 第三话·主从同步延迟

目录

一、MySQL 从库同步的相关参数

二、MySQL 从库同步延时出现的情况

三、MySQL 主从同步延迟的缘由

1、MySQL 主从同步原理

2、MySQL 主从同步延迟是怎么产生的

四、MySQL 主从同步延迟解决方案

1、架构方面

2、硬件方面

3、MySQL 参数调整

4、文件系统本身属性的优化(略)

5、号称永久解决复制延迟问题的并行复制


一、MySQL 从库同步的相关参数

1、Master_Log_File

slave 中的 I/O 线程当前正在读取的主服务器二进制文件的名称。

2、Read_Master_Log_Pos

在当前主服务器二进制文件中,slave 中的 I/O 线程已经读取到的位置。

3、Relay_Log_File

SQL 线程当前正在读取和执行的中继日志文件的名称。

4、Relay_Log_Pos

在当前的中继日志中,SQL 线程已经读取和执行的位置。

5、Relay_Master_Log_File

由 SQL 线程执行的包含多数近期事件的主服务器二进制日志文件的名称。

6、Slave_IO_Running

I/O 线程是否被启动,并成功的连接到主服务器上。

7、Slave_SQL_Running

SQL 线程是否被启动。

8、Seconds_Behind_Master

从服务器 SQL 线程和从服务器 I/O 线程之间的时间差距,单位以秒计。

二、MySQL 从库同步延时出现的情况

1、show slave status 显示参数 Seconds_Behind_Master 不为 0,这个数值可能会很大;

2、show slave status 参数 Relay_Master_Log_File 和 Master_Log_File 显示 binlog 的编号相差很大,说明 binlog 在从库上没有及时同步,所以近期执行的 binlog 和当前 I/O 线程所读取的 binlog 相差很大;

3、MySQL 从库日志目录下存在大量中继日志,该日志同步完成后就会被系统自动删除,存在大量日志,说明主从同步延迟很厉害。

三、MySQL 主从同步延迟的缘由

1、MySQL 主从同步原理

主服务器把数据更新记录到二进制日志中,从服务器通过 I/O 线程向主库发起 binlog 请求,主服务器通过 I/O dump 线程把二进制日志传送给从库,从库通过 I/O 线程记录到自己的中继日志中,然后再通过 SQL 线程应用中继日志中的 SQL 内容。

2、MySQL 主从同步延迟是怎么产生的

当主库的 TPS 并发较高时,产生的 DDL 数量超过 Slave 一个 SQL 线程所能承受的范围,那么延迟就产生了。

当然还有就是可能与 Slave 的大型 query 语句产生了锁等待。

一般主从复制,有三个线程,都是单线程,复制延迟一般出现在两个地方:

①主要原因:SQL 线程忙不过来(可能需要应用数据量较大;可能和从库本身一些操作有锁和资源的冲突;主库可以并发写,SQL 线程不可以)

②次要原因:网络抖动导致 I/O 线程复制延迟。

四、MySQL 主从同步延迟解决方案

1、架构方面

①业务的持久层实现采用分库架构,MySQL 服务平行扩展,分散压力;

②单个库读写分离,一主多从,分散压力;

③服务器的基础架构在业务和 MySQL 之间加入 Redis 的 cache 层,降低 MySQL 的读压力;

④不同业务的 MySQL 物理上放在不同机器,分散压力;

⑤使用比主库更好的硬件设备作为 Slave;

总结:MySQL 压力小,延迟自然会变小。

2、硬件方面

①采用好服务器,比如 4u 比 2u 性能明显好,2u 比 1u 性能明显好;

②存储用 SSD 或者盘阵,提升随机写性能;

③主从保证处在同一个交换机下面,并且是万兆环境;

总结:硬件强劲,延迟自然会变小(其实缩小延迟的解决方案就是花钱还是花时间)。

3、MySQL 参数调整

①sync_binlog 在 slave 端设置为 0;

说明:MySQL 提供了一个 sync_binlog 参数来控制数据库 binlog 刷到磁盘上去,默认sync_binlog=0,表示 MySQL 不控制 binlog 的刷新,由文件系统自己控制它的缓存的刷新,这时候性能是最好的,但风险也是最大的,一旦系统 crash,在 binlog_cache 中的所有 binlog 信息会被丢失。主库写对数据安全性较高,设置 sync_binlog=1 是必要的,而 slave 则不需要那么高的数据安全,可以考虑将 sync_binlog=0,或者直接关闭 binlog。

如果 sync_binlog>0,表示每 sync_binlog 次事物提交,MySQL 调用文件系统刷新操作将缓存持久化(看是否需要牺牲一定的一致性,可以获得更高的并发和性能)。

②-logs-slave-updates 从服务器从主服务器接收到的更新不记入它的二进制日志;

③直接禁用 slave 端的 binlog;

④slave 端,如果使用的存储引擎是 innodb,设置 innodb_flush_log_at_trx_commit=2;

说明:

  • 默认值为 1,事务每次提交都会将 log buffer 中的日志写入 os buffer 并调用 fsync()刷新到 logfile on disk 中,这种方式即使系统崩溃也不会丢失任何数据,但是因为每次提交都写入磁盘,I/O 性能较差。

  • 当设置为 0 时,事务提交时不会将 log buffer 中的日志写入到 os buffer,而是每秒写入 os buffer 并调用 fsync() 写入到 logfile on disk 中。也就是设置为 0 时(大约)每秒刷新写入磁盘中,当系统崩溃时会丢失 1 秒的数据。

  • 当设置为 2 时,每次提交仅写入到 os buffer,然后每秒调用 fsync() 将 os buffer 中的日志写入到 logfile on disk。

4、文件系统本身属性的优化(略)

5、号称永久解决复制延迟问题的并行复制

MySQL 从 5.6 开始有了 SQL Thread 多个的概念,可以并发还原数据,即并行复制技术。

MySQL 5.6 中,设置参数 slave_parallel_workers=4(>1),即可有 4 个 SQL Thread(coordinator 线程)来进行并行复制,其状态为:Waiting for an evant from Coordinator。

但是其并行只是基于 schema 的,也就是基于库的。如果数据库实例中存在多个 schema,这样设置对于 slave 复制的速度可以有比较大的提升。通常情况下单库多表是更常见的一种情形,那基于库的并发就没有卵用。

其核心思想是:不同 schema 下的表并发提交时的数据不会相互影响,即 slave 节点可以用对 relay log 中不同的 schema 各分配一个类似 SQL 功能的线程,来重放 relay log 中主库已经提交的事务,保持数据与主库一致。

在 MySQL 5.7 中,引入了基于组提交的并行复制(Enhanced Multi-threaded Slave),设置参数 slave_parallel_workers>0并且 global.slave_parallel_type='LOGICAL_CLOCK',即可支持一个 schema 下,slave_parallel_workers 个的 worker 线程并发执行 relay log 中主库提交的事务。

其核心思想是:一个组提交的事务都是可以并行回放(配合 binary log group commit),slave 机器的 relay log 中 last_committed 相同的事务(sequence_num 不同)可以并发执行。

其中,变量 slave_parallel_type 可以有两个值:DATABASE 默认值,基于库的并行复制方式;LOGICAL_CLOCK 基于组提交的并行复制方式。

MySQL 5.7 开启 Enhanced Multi-Threaded Slave 配置:

# slave
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON

猜你喜欢

转载自blog.csdn.net/weixin_42018518/article/details/107022576
今日推荐