背景
如果,初次配置完成了 mySQL数据库的读写分离操作
那么,后面遇到稍大流量访问时;
首先遭遇到的便是 【“主从同步延迟”】 造成的后果
环境
Linux系统: CentOS7.2
mySQL版本: mySQL5.7.32
MySQL数据库主从同步延迟原理 (摘抄经验)
DDL : 数据定义语言, DML :数据操纵语言
MySQL的主从复制都是单线程的操作,
主库对所有 DDL 和 DML 产生的日志写进 binlog,由于binlog是顺序写,所以效率很高。
Slave的SQL Thread线程将主库的DDL和DML操作事件在slave中重放。
DML和DDL的IO操作是随即的,不是顺序的,成本高很多。
另一方面,由于SQL Thread也是单线程的,
当主库的并发较高时,产生的DML数量超过slave的SQL Thread所能处理的速度,
或者当slave中有大型query语句产生了锁等待那么延时就产生了
有朋友会问:“主库上那个相同的DDL也需要执行10分,为什么slave会延时?”,答案是 master 可以并发,Slave_SQL_Running 线程却不可以
常见原因:Master负载过高、Slave负载过高、网络延迟、机器性能太低、MySQL配置不合理
情景模拟
简单理解为,主库遇到了高并发情况,比如短时间内大量用户触发注册逻辑
执行代码如下:
function testMysql(){
$randID = rand(500,600);
$tag = Db::name('xtest_logs')
->where('open_id',$randID)->count('id');
if ($tag){
return 0;
}else{
$tag = Db::name('xtest_logs')
->insert(['open_id'=>$randID,'add_time'=>time()]);
return $tag;
}
}
此时使用 ab 工具进行模拟高并发状态: ab -c 10 -n 1000 http://tp5pro.com/index/test
那么,此时数据库出现如下问题(对于业务来说,可是个大问题!):
主从延时排查方法
第一种方法:
1. show master status\G; # 查看主库的 position 号记录到多少了.
2. 从库中执行 show slave status\G; # 查看从库现在获取到哪个 position 号了.
3. 如果从库的 postion 号远小于主库的 position 号,则表示主库 dump 线程传送二进制出问题了.
第二种方法(推荐):
通过监控 show slave status 命令输出的 “Seconds_Behind_Master” 参数的值来判断
NULL,表示 io_thread 或是 sql_thread 有任何一个发生故障;
0,该值为零,表示主从复制良好;
正值,表示主从已经出现延时,数字越大表示从库延迟越严重。
为了再现这种高并发时刻,测试指令为 : ab -c 12 -n 10000 http://tp5pro.com/index/test
从库同步的延迟解决方案
①. 架构方面
1.业务的持久化层的实现采用分库架构,mysql 服务可平行扩展,分散压力。
2.单个库读写分离,一主多从,主写从读,分散压力。这样从库压力比主库高,保护主库。
3.服务的基础架构在业务和 mysql 之间加入memcache 或者r edis 的 cache 层。降低 mysql 的读压力。
4.不同业务的mysql物理上放在不同机器,分散压力。
5.使用比主库更好的硬件设备作为 slave
②. 硬件方面
1.采用好服务器,比如 4u比 2u性能明显好
2.存储用 ssd 或者盘阵或者 san,提升随机写的性能。
3.主从间保证处在同一个交换机下面,并且是万兆环境
4.优化网络,光纤、带宽等
主库配置sync_binlog=1,innodb_flush_log_at_trx_commit=1
sync_binlog的默认值是0,MySQL不会将binlog同步到磁盘,其值表示每写多少binlog同步一次磁盘。
innodb_flush_log_at_trx_commit为1表示每一次事务提交或事务外的指令都需要把日志flush到磁盘。
附录
本文同步分享在 博客“moTzxx”(CSDN)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。