从MySQL 5.5到5.7看复制的演进
概要:MySQL 5.5 支持单线程模式复制,MySQL 5.6 支持库级别的并行复制,MySQL 5.7 支持事务级别并行复制。结合这个主线我们可以来分析一下MySQL以及社区发展的一个前因后果。
MySQL5.5,对于复制我们可以这样理解:主库有个 dump binlog thread 不停的 dump binlog,然后以event为单位发送给从库 的 iothread,iothread 收到主库传过来的event写入relaylog ,随后sql_thread 读取relaylog 对这些event以事务为单位进行回放。
那么对于MySQL 5.5这个版本,在我们的使用过程中遇到那些问题,或者有那些不便呢?
首先DB压力偏大时,从库带来的延迟较大,影响只读业务
由于新硬件的发展,SSD的引入和多core的CPU,master节点的并发处理能力持续提升,slave节点完全按照binlog写入顺序的单线程回放,已完全跟不上master节点的吞吐能力。
在不考虑主从硬件配置差异情况下,延迟大的其根本原因在于:Master压力过大,而Slave是单线程回放日志。那么要解决这个问题,从技术上来说可以把单线程变为多线程,利用并行带来的优势;从业务上来说可以进行拆库,把一些业务线或者功能模块独立出去;更进一步我们可以拆表,把压力分担到多个Master上去。
假如我们在不变动业务的情况下,从技术面来解决这个问题有哪些方向呢:
社区的解决方案:阿里开源的canal,基于表级别并行同步,可以减小同步延迟时间
官方的解决方案:在2011年10月份发布了一个里程碑版本基于schema级别的并行复制[MySQL5.6.3 (multi-threaded slave)],以及基于group Commit的 MySQL5.7版本,最大化还原主库并行度。
MySQL5.6,对于复制我们可以这样理解,主库有个 dump binlog thread 不停的 dump binlog,然后以event为单位发送给从库 的 iothread,iothread 收到主库传过来的event写入relaylog。【随后的事情和MySQL5.5就发生了一些变化】,由coordinator线程来读取relaylog,然后根据不同的db以事务为单位分配到不同的work线程。如果binlog row event操作的是不同的schema的对象,在确定没有DDL和foreign key依赖的情况下,就可以实现并行复制。
MySQL5.7可以说是最大还原了主库上的并行,在基于Group Commit的基础上,所有在主库上能够完成prepared的语句表示没有数据冲突,分配成相同的lastcommitted,就可以在slave节点并行复制。 那么它是如何识别那些事务是一起提交的呢?其实就是在gtid event 中增加了两个字段【int64 lastcommitted;int64 sequencenumber】,当slave的coordinator线程在分发这些event的时候,具有相同lastcommitted 的事务(event的集合)就可以同时发送给不同的work线程,达到并行同步的目的。
小结:就并行复制,按粒度区分有三种策略,粒度从粗到细是按库、按表、按行。 这三个的对比中,并行度越来越大,额外损耗也是。无关大事务不会影响并发度。按照commit_id 的策略,适用范围更广,额外消耗也低。5.7的改进策略并发性更优。但出现大事务会拖后腿。
那么我们只有一实例只有一个database,这种情况下我们就只有拆库拆表了:
对于这种情况下,我们可以选择在应用层做分库分表,也可以选择搞个中间层。不同的方案有不同的优劣。
应用层具有较好的性能,但是代码耦合在业务,如果后续扩容还需该代码,不能做到平滑扩容拆分,假如有多个业务都需要实现同样的功能,那么会带来重复的工作量,而且工作难度也上升一个台阶。
中间件层具有较好的扩展性,低耦合性,如果DB扩容拆分,应用可以做到无感知,无改动。那么也有一些成熟的开源方案,比如MyCAT,Cobar,Atlas,kingshard等。
其次主从切换时带来的复杂度较大,需要计算position或者重做从库
一般情况下我们的MySQL都是一主多从架构,这样既能给我们提供读写分离、负载均衡的便利,也能给我们提供容灾的能力。但是假如我们的主库挂掉,这时我们会把从库提升为主库,但是在把从库提升为新主的时候带来了架构的微变化。为了还能利用以上便利、提供容灾能力我们还得重新构建这个新主的多个从库。此时问题就来了,我们从库必须知道我当前应该从Master 的那个位置开始复制,也就是说必须拿到Master的position 。为了拿到这个位置我们有两种办法,一种简单粗暴,重做Slave;另一种是通过一些列复杂计算、补回差异数据,算出当前数据和新主数据的差异点,从而得到新主库position,导致HA切换和数据保护带来巨大的挑战。
- MMM架构(Master-Master replication manager for MySQL)
MMM是一套支持双主故障切换和双主日常管理的脚本程序,可以再主库故障时保证热备切换为新主库,并且自动的将从库指向新主。但是这个架构本身不能保证数据的一致性。
MHA架构(Master High Availability)
MHA目前在MySQL高可用方面是一个相对成熟的解决方案,在自动进行故障切换的过程中,能最大程度上保证数据的一致性,以达到真正意义上的高可用。
那么HMA是如何最大程度保证数据一致的呢?当主库down掉时,MHA试图从宕机的主服务器上保存二进制日志,最大程度的保证数据的不丢失,但这并不总是可行的。如果主库发送down机,日志会出现不同程度的丢失,有个解决办法就是设置半同步复制。MHA在把从提升为主的过程中,会进行一系列日志对比,找到最接近主库的从库提升为新主库,把从库间差异化的数据拿出来进行应用等等。
GTID (Global Transaction ID)
在MySQL 5.6 以后官方引入了GTID,即在整个集群内部,每个事务都有全局唯一的一个标识,这样一来,当我们主库发送down掉,或者MySQL架构有调整的时候,我们就不用很头疼的去计算position;或者去配置略为复杂的MHA。我们只需要轻轻松松敲个CHANGE MASTER 命令带上AUTO_POSITION就可以了,然后关于MASTER该从哪个binlog开始推送event给Slave这个完全由MySQL来帮我们计算。这个真是DBA们的福音啊。
简单看看,为什么这么GTID这么神奇吧。在MySQL内部帮我们记录着 gtidpurged 和gtidexecuted 两个集合。顾名思义,gtidexecuted 代表的时当前已经执行过的GTID的集合;一般情况下我们binlog不可能永久保存,那么gtidpurged代表的就是当前binlog已经没有的GTID集合,它是gtidexecuted的子集。我们知道在事务是不能跨binlog存在的,意味着每个binlog都会有一个完整的事务集合,同样每个binlog文件的 header 部分,也都存放着这个binlog以前的 gtidexecuted 集合。我们的Slave 在应用Binlog的时候都会记录自己当前已经执行过的最后一个事务GTID,那么我们在切换主库的时候,Slave就会把这个ID给带上,然后Master端就会拿到这个GTID和自己当前的gtidexecuted、gtidpurged 集合进行对比,从而给到Slave一个合理的解释。
- MMM架构(Master-Master replication manager for MySQL)
OK,到这里MySQL从5.5的单线程复制,到5.6基于Schema级别的复制,再到5.7最大化还原主库的并行就接近尾声了。同时在这期间我们还给出了一些社区上、或者非技术上的解决方案。
从MySQL 5.5到5.7看复制的演进的更多相关文章
- mysql进阶(二十六)MySQL 索引类型(初学者必看)
mysql进阶(二十六)MySQL 索引类型(初学者必看) 索引是快速搜索的关键.MySQL 索引的建立对于 MySQL 的高效运行是很重要的.下面介绍几种常见的 MySQL 索引类型. 在数 ...
- MySQL 5.7主从复制与主主复制实现细节分析
0.简介: MySQL作为世界上使用最为广泛的数据库之一,免费是其原因之一.但不可忽略的是它本身的功能的确很强大.随着技术的发展,在实际的生产环境中,由单台MySQL数据库服务器不能满足实际的需求.此 ...
- 使用innobackupex进行mysql的差异备份还原和延迟复制
使用innobackupex进行mysql的差异备份还原和延迟复制 背景: 有同事执行update语句没有添加where条件,导致大量脏数据,需要将这张表恢复到前一天 数据库上有备份,每周一次完整备份 ...
- MySQL 5.7 基于GTID主从复制+并行复制+半同步复制
环境准备 IP HOSTNAME SERVICE SYSTEM 192.168.131.129 mysql-master1 mysql CentOS7.6 192.168.131.130 mysql- ...
- MySQL开发总结(有点长..耐心看)
一.理解MySQL基本概念 1.MySQL软件:MySQL实际上就是一软件,是一工具,是关系型数据库管理系统软件 2.MySQL数据库:就是按照数据结构来组织.存储和管理数据的仓库 3.MySQL数据 ...
- 从MySQL和MongoDB的对比,看SQL与NoSQL的较量
张家江,网易乐得高级工程师. 贵金属(注:贵金属为笔者部门业务)的行情系统提供的接口通过Redis获取数据,目前使用Redis最多只存储了大概8000条左右的分钟k的行情数据,考虑到将来可能会有更大数 ...
- 100道MySQL常见面试题总结,看完直接收藏
前言 本文主要受众为开发人员,所以不涉及到MySQL的服务部署等操作,且内容较多,大家准备好耐心和瓜子矿泉水. 前一阵系统的学习了一下MySQL,也有一些实际操作经验,偶然看到一篇和MySQL相关的面 ...
- 面试问烂的 MySQL 四种隔离级别,看完吊打面试官!
阅读本文大概需要 5.6 分钟. 来源:网络 什么是事务 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.也就是事务具有原子性,一个事务中的一系列的操 ...
- 【Nginx】如何使用Nginx实现MySQL数据库的负载均衡?看完我懂了!!
写在前面 Nginx能够实现HTTP.HTTPS协议的负载均衡,也能够实现TCP协议的负载均衡.那么,问题来了,可不可以通过Nginx实现MySQL数据库的负载均衡呢?答案是:可以.接下来,就让我们一 ...
随机推荐
- Linux 批量替换文件名
find -name "*parsed" |awk '{print $1}' |xargs -i{} mv {} {}.44
- iOS改变NavigationBar的返回键和标题颜色、大小
UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom]; [UIPubic initHeadViewBackImgWithBt ...
- 韩服MU
※◆☆★☆◆※欢迎使用!!!如有问题或新功能需求请联系作者QQ:82850696*4*您使用的测试版已到期,如需继续使用,请联系作者 QQ : 82850696*0*2015-1-7 23:59:59 ...
- iOS遍历程序内某个文件夹下所有文件的属性
项目中有个文件管理系统,在做本地文件管理操作的时候,遇到了遍历本地文件的问题 遍历到的文件有些不需要显示,而且需要得到文件的相关属性,在此总结下. //查找需要遍历文件夹的目录 NSString *k ...
- sqlite数据库中 保存和读取UIData对象
+ (void)getPersonByID:(int)ID { sqlite3 *db = [DB open]; sqlite3_stmt *stmt = nil; int result = sqli ...
- java堆内存与栈内存
java的内存分为两种,堆内存与栈内存: 堆内存用来存放数组和new的对象,比如一个文件,字节流是存放在堆中,栈内存为这个文件开辟一个索引,也就是这个文件的地址,并且保存在栈中.对象由GC处理释放内存 ...
- c# 中定时器的用法
来源于:http://blog.sina.com.cn/s/blog_62c501440100fog1.html System.Threading.Timer 是一个非常常用的定时器类,关于这个类的使 ...
- 『TCP/IP详解——卷一:协议』读书笔记——07
2013-08-20 17:51:49 第三章 IP:网际协议 3.1 引言 IP是TCP/IP协议族中最为核心的协议.所有的TCP.UDP.ICMP和IGMP数据都以IP数据报格式传输.再来看一下图 ...
- Linq To Object
//SelectMany List<List<int>> Numbers = new List<List<int>>() { new List<i ...
- [ASE][Daily Scrum]11.17
这两天感冒了没有第一时间更新blog和tfs,给大家抱歉了! 上周五我们已经将服务器搭建完成并成功通讯,周六周日大家非常给力的完成了很多内容! View Shilin Liu 处理来自服务器的数据 显 ...