从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数据库的负载均衡呢?答案是:可以.接下来,就让我们一 ...
随机推荐
- URLConnection 和 HttpClients 发送请求范例
. java.net.URLConnection package test; import java.io.BufferedReader; import java.io.IOException; im ...
- RabbitMQ 学习记录
rabbit mq知识点:1.消费时可以通过acknowledge设定消费是否成功,消费不成功时在server端requeue2.需要注意两个持久化:queue持久化和消息持久化(通过代码设定,默认即 ...
- jQuery -> bind / live / delegate 的终结者 - on
Bind()方法: 给元素绑定事件 形式: .bind(eventType[,eventData],handler(eventObject)) eventType,string类型,一个或多个DOM事 ...
- UILabel的常用属性
UILabel常用属性1——实例化和设置文字 // 实例化UILabel并指定其边框 UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake ...
- MongoDB文档、集合、数据库简介
文档 概述 文档是MongoDB的核心概念,是数据的基本单元,非常类似于关系数据库中的行.在MongoDB中,文档表示为键值对的一个有序集.MongoDB使用Javascript shell,文档的表 ...
- Antenna Placement poj 3020(匹配)
http://poj.org/problem?id=3020 题意:给定一个n*m的矩阵,'*'代表城市,现在想要用1*2的矩阵将所有的城市覆盖,问最少需要多少个矩阵? 分析:先为每个城市进行标号,再 ...
- 【随笔】ARP和RARP
ARP协议是什么? ARP协议是"Address Resolution Protocol"(地址解析协议)的缩写.在局域网中,网络中实际传输的是"帧",帧里面是 ...
- 問題排查:行動裝置網頁前端 UI 設計 (1)
這是最近開始接手的一個微信公眾平台專案, 在重整後端程式碼時,因為也需要透過前端來看效果, 所以就因此在前端的部分遇到了不少問題, 畢竟這是以前沒接觸過的領域 (早年的網頁應用程式開發沒有那麼多分工) ...
- "2013":爱你不容易
2013对我来说确实像年初时曾给自己定义的那样,真的是非常不平常的一年.依稀记得去年年终时,BOSS和我深聊了1多钟头,谈到职业规划.人生还有家庭的林林种种.春节在家时也仔细考虑过2013自己该如何规 ...
- SparkContext的初始化(叔篇)——TaskScheduler的启动
<深入理解Spark:核心思想与源码分析>一书前言的内容请看链接<深入理解SPARK:核心思想与源码分析>一书正式出版上市 <深入理解Spark:核心思想与源码分析> ...