mysql主从延迟
1. 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线程却不可以。
2. MySQL数据库主从同步延迟是怎么产生的。
当主库的TPS并发较高时,产生的DDL数量超过slave一个sql线程所能承受的范围,那么延时就产生了,当然还有就是可能与slave的大型query语句产生了锁等待。
3. MySQL数据库主从同步延迟解决方案。
丁奇的transefer是一个不错的方案,不过一般公司受限于对mysql的代码修改能力的限制和对mysql的掌控能力,还是不太适合。
最
简单的减少slave同步延时的方案就是在架构上做优化,尽量让主库的DDL快速执行。还有就是主库是写,对数据安全性较高,比如
sync_binlog=1,innodb_flush_log_at_trx_commit = 1
之类的设置,而slave则不需要这么高的数据安全,完全可以讲sync_binlog设置为0或者关闭binlog,innodb_flushlog也
可以设置为0来提高sql的执行效率。另外就是使用比主库更好的硬件设备作为slave。
mysql-5.6.3已经支持了多线程的主从复制。原理和丁奇的类似,丁奇的是以表做多线程,oracle使用的是以数据库(schema)为单位做多线程,不同的库可以使用不同的复制线程。
sync_binlog=1 o
This makes MySQL synchronize the binary log's contents to disk each time it commits a transaction
默认情况下,并不是每次写入时都将binlog与硬盘同步。因此如果操作系统或机器(不仅仅是MySQL服务器)崩溃,有可能binlog中最后的语句丢
失了。要想防止这种情况,你可以使用sync_binlog全局变量(1是最安全的值,但也是最慢的),使binlog在每N次binlog写入后与硬盘
同步。即使sync_binlog设置为1,出现崩溃时,也有可能表内容和binlog内容之间存在不一致性。如果使用InnoDB表,MySQL服务器
处理COMMIT语句,它将整个事务写入binlog并将事务提交到InnoDB中。如果在两次操作之间出现崩溃,重启时,事务被InnoDB回滚,但仍
然存在binlog中。可以用--innodb-safe-binlog选项来增加InnoDB表内容和binlog之间的一致性。(注释:在MySQL
5.1中不需要--innodb-safe-binlog;由于引入了XA事务支持,该选项作废了),该选项可以提供更大程度的安全,使每个事务的
binlog(sync_binlog
=1)和(默认情况为真)InnoDB日志与硬盘同步,该选项的效果是崩溃后重启时,在滚回事务后,MySQL服务器从binlog剪切回滚的
InnoDB事务。这样可以确保binlog反馈InnoDB表的确切数据等,并使从服务器保持与主服务器保持同步(不接收 回滚的语句)。
innodb_flush_log_at_trx_commit (这个很管用)
抱
怨Innodb比MyISAM慢
100倍?那么你大概是忘了调整这个值。默认值1的意思是每一次事务提交或事务外的指令都需要把日志写入(flush)硬盘,这是很费时的。特别是使用电
池供电缓存(Battery backed up
cache)时。设成2对于很多运用,特别是从MyISAM表转过来的是可以的,它的意思是不写入硬盘而是写入系统缓存。日志仍然会每秒flush到硬
盘,所以你一般不会丢失超过1-2秒的更新。设成0会更快一点,但安全方面比较差,即使MySQL挂了也可能会丢失事务的数据。而值2只会在整个操作系统
挂了时才可能丢数据。
像Facebook、开心001、人人网、优酷、豆瓣、淘宝等高流量、高并发的网站,单点数据库很难支撑得住,WEB2.0类型的网站中使用MySQL的 居多,要么用MySQL自带的MySQL NDB Cluster(MySQL5.0及以上版本支持MySQL NDB Cluster功能),或者用MySQL自带的分区功能(MySQL5.1及以上版本支持分区功能),我所知道的使用这两种方案的很少,一般使用主从复 制,再加上MySQL Proxy实现负载均衡、读写分离等功能,在使用主从复制的基础上,再使用垂直切分及水平切分;或者不使用主从复制,完全使用垂直切分加上水平切分再加上 类似Memcached的系统也可以解决问题。
1.优酷的经验
数据库采用水平扩展,主从复制,随着从数据库的增多,复制延迟越来越厉害,最终无法忍受。
最终还是采用数据库的sharding,把一组用户相关的表和数据放到一组数据库上。
使用SSD来优化mysql的I/O,性能提升明显,每块16G,6块SSD做RAID。
数据库的类型选用MYISAM
数据库的拆分策略,先纵向按照业务或者模块拆分。对于一些特别大的表,再采用垂直拆分
根据用户进行分片,尽可能不要跨篇查询。如果确实要跨片查询,可以考虑搜索的方案,先索引再搜索。
分布式的数据库方案太复杂,否掉。

优酷使用的是数据库分片技术,而抛弃了由于数据量的越来越多导致复制延迟的问题。按照user_id进行分片,这样必须有一个全局的表来管理用户与shard的关系,根据user_id可以得到share_id,然后根据share_id去指定的分片查询指定的数据。
假
如此表的表名为sharding_manager,如果网站的用户数太多,比如千万级的或甚至更大比如亿级的用户,此时此表也许也会成为一个瓶颈,因为查
询会非常频繁,所有的动态请求都要读此表,这时可以用其它的解决方案,比如用Memcached、Tokyo Cabinet、Berkeley
DB或其它的性能更高的方案来解决。
具体怎么定位到哪台db服务器,定位到哪个数据库,定位到哪个shard(就是userN,msgN,videoN),优酷网的架构文档中说得不是很仔细,这里只能猜测一下了。
根据优酷的架构图,一共有2台db服务器,每台db服务器有2个数据库,每个数据库有3个shard,这样一共是2 * 2 * 3 = 12个shard。
user_id
一般是自增型字段,用户注册的时候可以自动生成,然后看有几台db服务器,假如有m台db服务器,则用 user_id %
m便可以分配一台db服务器(例如0对应100,1对应101,以此类推,字段mysql_server_ip的值确定),假设每台服务器有n个数据库,
则用user_id % n可以定位到哪个数据库(字段database_name的值确定),假设每个数据库有i个shard,则用user_id %
i可以定位到哪个shard(字段shard_id的值确定),这样就可以进行具体的数据库操作了。
user_id share_id mysql_server_ip database_name
101 2 192.168.1.100 shard_db1
105 0 192.168.1.100 shard_db2
108 0 192.168.1.101 shard_db3(或shard_db1)
110 1 192.168.1.101 shard_db4(或shard_db2)
如上述user_id为101的用户,连接数据库服务器192.168.1.100,使用其中的数据库为shard_db1,使用其中的表系列为user2,msg2,video2
如果上述的m,n,i发生变化,比如网站的用户不断增长,需要增加db服务器,此时则需要进行数据库迁移,关于迁移,参见这儿。
因为表位于不同的数据库中,所以不同的数据库中表名可以相同
server1(192.168.1.100)
shard_db1
user0
msg0
video0
user1
msg1
video1
...
userN
msgN
videoN
shard_db2
user0
msg0
video0
user1
msg1
video1
...
userN
msgN
videoN
因为表位于不同的数据库服务器中,所以不同的数据库服务器中的数据库名可以相同
server2(192.168.1.101)
shard_db3(这里也可以用shard_db1)
user0
msg0
video0
user1
msg1
video1
...
userN
msgN
videoN
shard_db4(这里也可以用shard_db2)
user0
msg0
video0
user1
msg1
video1
...
userN
msgN
videoN
2.豆瓣的经验
由于从主库到辅库的复制需要时间
更新主库后,下一个请求往往就是要读数据(更新数据后刷新页面)
从辅库读会导致cache里存放的是旧数据(不知道这个cache具体指的是什么,如果是Memcached的话,如果更新的数据的量很大,难道把所有更新过的数据都保存在Memcached里面吗?)
解决方法:更新数据库后,在预期可能会马上用到的情况下,主动刷新缓存
不完美,but it works
豆瓣后来改为双MySQL Master+Slave说是能解决Replication Delay的问题,不知道是怎么解决的,具体不太清楚。
3.Facebook的经验
下面一段内容引用自www.dbanotes.net
大量的 MySQL + Memcached 服务器,布署简示:
California (主 Write/Read)............. Virginia (Read Only)
主
数据中心在 California ,远程中心在 Virginia 。这两个中心网络延迟就有 70ms,MySQL 数据复制延迟有的时候会达到
20ms. 如果要让只读的信息从 Virginia 端发起,Memcached 的 Cache 数据一致性就是个问题。
1 用户发起更新操作,更名 "Jason" 到 "Monkey" ;
2 主数据库写入 "Monkey",删除主端 Memcached 中的名字值,但Virginia 端 Memcached 不删;(这地方在 SQL 解析上作了一点手脚,把更新的操作"示意"给远程);
3 在 Virginia 有人查看该用户 Profile ;
4 在 Memcached 中找到键值,返回值 "Jason";
5 复制追上更新 Slave 数据库用户名字为 "Monkey",删除 Virginia Memcached 中的键值;
6 在 Virginia 有人查看该用户 Profile ;
7 Memcache 中没找到键值,所以从 Slave 中读取,然后得到正确的 "Monkey" 。
Via
从上面3可以看出,也仍然存在数据延迟的问题。同时master中数据库更新的时候不更新slave中的memcached,只是给slave发个通知,说数据已经改变了。
那是不是可以这样,当主服务器有数据更新时,立即更新从服务器中的Memcached中的数据,这样即使有延迟,但延迟的时间应该更短了,基本上可以忽略不计了。
4.Netlog的经验
对
于比较重要且必须实时的数据,比如用户刚换密码(密码写入 Master),然后用新密码登录(从 Slaves
读取密码),会造成密码不一致,导致用户短时间内登录出错。所以在这种需要读取实时数据的时候最好从 Master 直接读取,避免 Slaves
数据滞后现象发生。还好,需要读取实时数据的时候不多,比如用户更改了邮件地址,就没必要马上读取,所以这种 Master-Slaves
架构在多数情况下还是有效的。
= = =
http://blogold.chinaunix.net/u3/116107/showart_2364757.html
= = =
0_php_whc 17:28:20
http://koda.javaeye.com/blog/682547
0_php_whc 17:29:51
http://blog.csdn.net/MPU/archive/2010/06/23/5689225.aspx
0_php_whc 17:29:58
http://apps.hi.baidu.com/share/detail/17180907
0_php_whc 17:32:19
我们现在采用的是
4.Netlog的经验
对
于比较重要且必须实时的数据,比如用户刚换密码(密码写入 Master),然后用新密码登录(从 Slaves
读取密码),会造成密码不一致,导致用户短时间内登录出错。所以在这种需要读取实时数据的时候最好从 Master 直接读取,避免 Slaves
数据滞后现象发生。还好,需要读取实时数据的时候不多,比如用户更改了邮件地址,就没必要马上读取,所以这种 Master-Slaves
架构在多数情况下还是有效的。
mysql主从延迟的更多相关文章
- MySQL主从延迟如何解决?
我们知道生产环境中经常会遇到MySQL主从延迟问题,从原理上也能看出主库的事务提交是并发模式,而从库只有一个SQL线程负责解析,所以本身上就可能存在延迟. 延迟的主要原因在于: 1.从库的配置往往没有 ...
- 架构师必备:MySQL主从延迟解决办法
上一篇文章介绍了MySQL主从同步的原理和应用,本文总结了MySQL主从延迟的原因和解决办法.如果主从延迟过大,会影响到业务,应当采用合适的解决方案. MySQL主从延迟的表现 先insert或upd ...
- mysql主从延迟高的原因
1.1.1故障1:从库数据与主库冲突 1 2 3 4 5 6 show slave status; 报错:且show slave status\G Slave_I/O_Running:Yes Slav ...
- MySQL 主从延迟几万秒 Queueing master event to the relay log(转)
数据库版本Server version: 5.6.24-log Source distribution 问题描述 数据采集平台业务数据库由于批量灌数据导致主从延迟上万秒. 复制线程长期处于Que ...
- 一次线上MySQL主从延迟排查
今天早上来上班,发现zabbix一直告警主从延迟,mysql slave Seconds_Behind_Master (mysql.slave_status[Seconds_Behind_Master ...
- 面试官:咱们来聊一聊mysql主从延迟
背景 前段时间遇到一个线上问题,后来排查好久发现是因为主从同步延迟导致的,所以今天写一篇文章总结一下这个问题希望对你有用.如果觉得还不错,记得加个关注点个赞哦 思维导图 思维导图 常见的主从架构 随着 ...
- 减少MySQL主从延迟的神器--并行复制大揭密
1. 简介 MySQL 5.6引入了基于schema的并行复制,即如果binlog events操作的是不同schema的对象,不是DDL,且操作的对象没有对其他schema的foreign key关 ...
- mysql主从延迟复制
需求描述 正常情况下我们是不会有刻意延迟从库的需求的,因为正常的线上业务自然是延迟越低越好.但是针对测试场景,业务上偶尔需要测试延迟场景下业务是否能正常运行. 解决方案 针对这种场景mysql有一个叫 ...
- 影响mysql主从延迟速度的相关参数
1.sync-binlog MySQL提供一个sync_binlog参数来控制数据库的binlog刷到磁盘上去. 默认,sync_binlog=0,表示MySQL不控制binlog的刷新,由文件系统自 ...
随机推荐
- Keras GRU 文字识别
GRU(Gated Recurrent Unit)是LSTM的一个变体,也能克服RNN无法很好处理远距离依赖的问题. GRU的结构跟LSTM类似,不过增加了让三个门层也接收细胞状态的输入,是常用的LS ...
- 数据结构之最小生成树Kruskal算法
1. 克鲁斯卡算法介绍 克鲁斯卡尔(Kruskal)算法,是用来求加权连通图的最小生成树的算法. 基本思想:按照权值从小到大的顺序选择n-1条边,并保证这n-1条边不构成回路. 具体做法:首先构造一个 ...
- bzoj 2131 免费的馅饼
Written with StackEdit. Description Input 第一行是用空格隔开的二个正整数,分别给出了舞台的宽度\(W\)(\(1\)到\(10^8\)之间)和馅饼的个数\(n ...
- Docker从入门到安装MySQL
Docker 的简介 Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源. Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后 ...
- LeetCode Split Array into Consecutive Subsequences
原题链接在这里:https://leetcode.com/problems/split-array-into-consecutive-subsequences/description/ 题目: You ...
- idea的有些路径问题
resource文件在xml的路径 http://www.cnblogs.com/zqr99/p/7642712.html resource文件在io流的读取 this.getClass().getR ...
- BZOJ1355:[Baltic2009]Radio Transmission
浅谈\(KMP\):https://www.cnblogs.com/AKMer/p/10438148.html 题目传送门:https://lydsy.com/JudgeOnline/problem. ...
- FPGA中计数器设计探索
FPGA中计数器设计探索,以计数器为32位为例: 第一种方式,直接定义32位计数器. reg [31:0]count; quartus ii 下的编译,资源消耗情况. 85C模型下的时钟频率. 0C模 ...
- HDU 5705 Clock(模拟,分类讨论)
Clock Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submi ...
- xunsearch全文检索初体验
目录 测试添加数据 测试搜索 简单搜索 稍微复杂的搜索 搜索建议 测试添加数据 ./Indexer.php --source=csv --clean demo 清空现有索引数据 ... 初始化数据源 ...