当前位置: 首页 > news >正文

Mysql 主从复制实现原理

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

mysql replication 实现原理

一、replication 线程

Mysql 的Replication是一个异步的复制过程,从一个 mysql Instance(master)复制到另一个mysql Instance(slave)。在Master与Slave之间的整个复制过程主要由三个线程来完成,其中两个线程 SQL线程和IO线程在Slave端,另外一个线程 IO线程在Master端。

要实现Mysql Relication,首先必须打开Master的 Binary Log功能。因为整个复制功能实际上就是Slave从Master端获取二进制日志,然后在自己身上完全按照产生的顺序依次执行日志中所记录的各种操作。

MYSQL 复制的基本过程如下:

(1)Slave的IO线程连接上Master,并请求日志文件的指定位置(或者从最开始的日志)之后的日志内容;

(2)Master接收到来自Slave的IO线程请求后,负责复制的IO线程根据请求信息读取指定日志位置之后的日志信息,返回给Slave端的IO线程。返回信息中除了日志所包含的信息外,还包括本次返回的信息在Master端的Binary Log 文件的名称和位置;

(3)Slave的IO线程接收到信息后,将日志内容依次写入Slave端的Relay Log(中继日志)文件的最末端,并将读取到的Master端的Binary Log 文件名和位置记录到master-info文件中,以便在下次读取时能清楚地告诉master “我需要从某个bin-log文件的哪个位置开始完后的日志内容,发给我”;

(4)Slave的Sql线程检测到Relay Log中新内容后,会马上解析该Log文件中的内容,还原成在Master端真实执行的可执行Query语句,并执行这些Query。实际上就是在Master端和Salve端执行了同样的Query,所以两端的数据是完全一样的。

二、复制实现级别

(1)Row Level

Binary Log会记录成每一行数据被修改的形式,然后在Slave端再对相同的数据进行修改。

优点:在Row Level模式下,Binary Log可以不记录执行的Query语句的上下文相关信息,只需要记录哪一条记录被修改了,修改成什么样了。所以 Row Level的日志内容会非常清楚地记录下每一行数据修改的细节,非常容易理解。而且不会出现某些特定情况下的存储过程,或 function,以及 Trigger的调用和触发无法正确复制的问题。

缺点:在Row Level模式下,当所有的执行语句记录到Binary Log 中时,都将被记录成每条记录被修改的形式,这样就会产生大量的日志内容。比如有这样的一条 update语句:UPDATE group_message SET group_id = 1 WHERE group_id=2,执行后,日志记录的不是该语句而是产生影响的 表中的每条记录,即:如果group_message 中有 group_id=1 的记录100条,那么Binary Log中记录了这100条记录的变化情况。尤其执行 Alter Table 之类的语句时,产生的日志量更大的惊人。因为MYSQL对于Alter Table之类的DDL变更语句是重建整个表的所有数据,即表中每一条记录都要变动,那么该表中所有记录都要记录到日志中。

 

(2)Statement Level

每一条会修改数据的Query都会记录到Master的Binary Log中以及执行语句时上下文的信息。Slave 在复制的时候,SQL线程会解析成和原来 Master 端执行过的相同的 Query,并再次执行。

有点:首先解决了Row Level的缺点,不需要记录每一行记录的变化,减少了Binary Log 日志量,节约了IO成本,提高了性能。

缺点:由于记录的是执行语句,为了能让这些语句在Slave端也能正确执行,就需要记录每条语句在执行时的一些相关信息,即上下文信息。另外由于MYSQL发展比较快,很多新功能的加入,也使得mysql复制遇到不少挑战,复制时涉及的内容越复杂越容易出现bug。在修改数据时使用了默写特定的函数或功能后会出现问题。如 sleep()函数在默写版本中不能正确复制,在存储过程中使用 last_insert_id()函数,可能会使Slave 和Master得到不一致的ID,由于Row Level是基于每一行变化的所以不会出现这种情况。

(3) Mixed Level

在Mixed模式下,mysql会根据执行的每一条具体的Query语句来区分对待记录的日志形式,也就是在 Statement和Row之间选择一种。从5.1.8版本开始,Mysql提供了Statement Level 和 Row Level之外的第三种复制模式 Mixed Level

 

三、Replication 常用架构

(1) 常规复制架构 (Master - Slave)

主从复制架构,可以实现写读分离,只要Master端和 Slave端的压力不是很大,异步复制的延时一般都很少很少。尤其是自从Slave端的复制方式改成两个线程处理之后。

 

(2)Dual Master复制架构(Master - Master)

如果简单用常规复制架构 切换的话,就会造成原来Master端数据的不一致性,当原来的Master启动可以正常提供服务时,不得不通过反转Master - Slave 关系重新搭建Replication 环境,并以 原 Master 作为 Slave来对外提供服务。这将增加很多工作量。为了避免这个问题,可以搭建 Dual Master (双 Master),即两个Mysql Server互相将对方作为自己的Master,自己作为对方的Slave来进行复制。这样任何一方做的变更,都会通过复制应用到另一方数据库中。

为避免循环复制,Mysql的Binary Log中记录了当前Mysql的server-id ,mysql很容易判断某个变更是从哪一个mysql server最初产生的。另外如果不打开Slave的Binary Log选项(--log-slave-update)时,mysql根本就不会记录复制过程中产生的变更多 Binary Log中。

为了避免数据冲突一般指开启一端写服务,因为两端如果同时更新一条记录,会产生冲突 覆盖。

(3)级联复制架构(Master - Slave - Slave ...)

在有些应用场景中,也许读写压力差别比较大,读压力特别大,一台Master 可能需要10台甚至更多的Slave才能支撑读的压力。

这时可利用MYSQL可以在 Slave端记录复制所产生的变更的 Binary Log 信息的功能,也就是打开 -log-slave-update 选项。然后通过二级复制来减少 Master端因为复制所带来的压力。也就是说,首先通过少数几台Mysql从Master来进行复制,这几台机器我们称为第一级Slave 集群,然后其他的Slave再通过第一级Slave集群来进行复制。从第一级Slave进行复制的Slave,称之为第二级Slave集群。如果有需要还可以继续往下增加更多层次的复制。

(4)Dual Master 与级联复制结合架构(Master-Master-Slaves)

级联复制在一定程度上确实解决了 Master因为所附属的Slave过多而成为瓶颈的问题,但并不能解决人工维护和出现异常需要切换时可能存在重新搭建 Replication的问题。

和Master - Salve - Salve 架构相比,区别只是将第一级的Slave集群换成了一台单独的Master,作为备用Master,然后再从这个Master复制到一个Slave集群,这样避免了主Master的写操作受到Slave集群的复制所带来的影响,同时主Master需要切换的时候也基本上不会出现重搭Replication的情况。但这个架构也有一个弊端,那就是备用的Master有可能成为瓶颈,如果后面Slave集群比较大的话,备用Master可能会因为过多的Slave IO线程请求而成为瓶颈。该备用Master不可供任何读服务时,瓶颈出现的可能性并不是很高。

 

转载于:https://my.oschina.net/shilijun/blog/124231

相关文章:

  • 网站整体变灰色
  • oracle中 all any in的用法
  • HDU-4473 Exam 数学分析
  • 通过iTunes检测更新,使用NSJSONSerialization解析JSON格式版本信息
  • jQuery页面滚动图片等元素动态加载实现
  • Java 聚合 组合 is-a has-a 关系学习
  • ZenCoding
  • nginx下使用Django
  • 五款超实用的开源SVG工具
  • solr dataimport 数据导入源码分析(十二)
  • secucrt相关技巧
  • [经典语录][电影]全民情敌/Hitch
  • iPhone私有API学习笔记
  • NS2源码图示---物理层 (转帖)
  • 火狐浏览器的一些常用设置
  • 【每日笔记】【Go学习笔记】2019-01-10 codis proxy处理流程
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • Apache Pulsar 2.1 重磅发布
  • egg(89)--egg之redis的发布和订阅
  • Git初体验
  • JavaScript 基础知识 - 入门篇(一)
  • JDK 6和JDK 7中的substring()方法
  • laravel 用artisan创建自己的模板
  • Linux Process Manage
  • React-redux的原理以及使用
  • React系列之 Redux 架构模式
  • Redux 中间件分析
  • Service Worker
  • Webpack 4x 之路 ( 四 )
  • 大整数乘法-表格法
  • 面试遇到的一些题
  • 驱动程序原理
  • 微信公众号开发小记——5.python微信红包
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • #include<初见C语言之指针(5)>
  • (1)(1.19) TeraRanger One/EVO测距仪
  • (一)Neo4j下载安装以及初次使用
  • (最简单,详细,直接上手)uniapp/vue中英文多语言切换
  • * CIL library *(* CIL module *) : error LNK2005: _DllMain@12 already defined in mfcs120u.lib(dllmodu
  • *(长期更新)软考网络工程师学习笔记——Section 22 无线局域网
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • .bashrc在哪里,alias妙用
  • .cfg\.dat\.mak(持续补充)
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .Mobi域名介绍
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • .NET Core6.0 MVC+layui+SqlSugar 简单增删改查
  • .NET 反射 Reflect
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .NET 使用 ILMerge 合并多个程序集,避免引入额外的依赖
  • @configuration注解_2w字长文给你讲透了配置类为什么要添加 @Configuration注解
  • [ 隧道技术 ] 反弹shell的集中常见方式(四)python反弹shell
  • [2008][note]腔内级联拉曼发射的,二极管泵浦多频调Q laser——
  • [ajaxupload] - 上传文件同时附件参数值
  • [AutoSar]BSW_Memory_Stack_003 NVM与APP的显式和隐式同步