MySQL复制原理

来源:互联网 发布:淘宝折扣卷哪里找 编辑:程序博客网 时间:2024/06/10 04:11

复制概述:
Mysql内建的复制功能是构建大型高性能应用程序的基础。将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台主机的数据复制到其它主机(Slaves)上,并重新执行一遍来实现的。复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志可以记录发送到从服务器的更新。当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,然后封锁并等待主服务器通知新的更新。
注意: 进行复制时,所有对复制中的表的更新必须在主服务器上进行。否则,用户对主服务器上的表进行的更新与对从服务器上的表所进行的更新之间会有冲突。
MySQL复制技术特性:

  • 数据分布 (Data distribution )
  • 负载平衡(load balancing)
  • 备份(Backups)
  • 高可用性和容错行性(High availability and failover)

Replication线程:
   Mysql的 Replication 是一个异步的复制过程,从一个 Mysql instace(Master)复制到另一个 Mysql instance( Slave)。在 Master 与 Slave 之间的实现整个复制过程主要由三个线程来完成,其中两个线程(Sql线程和IO线程)在 Slave 端,另外一个线程(IO线程)在 Master 端。
这里写图片描述
当发出start slave时,从服务器创建一个I/O线程,以连接主服务器并让它发送记录在其二进制日志中的语句。主服务器创建一个线程将二进制日志中的内容发送到从服务器。该线程即为主服务器上show process list输出中的Binlog Dump线程。
从服务器I/O线程读取主服务器Binlog Dump线程发送的内容并将该数据拷贝到从服务器数据目录中的本地文件中,即中继日志。
从服务器SQL线程读取中继日志并执行日志中包含的更新。在从服务器上,读取和执行更新语句被分成两个独立的任务。当从服务器启动时,其I/O线程可以很快地从主服务器索取所有二进制日志内容。
复制线程状态
通过show slave status\G和show master status可以查看复制线程状态。常见的线程状态有:

  • 主服务器Binlog Dump线程
    Has sent all binlog to slave; waiting for binlog to be updated 线程已经从二进制日志读取所有主要的更新并已经发送到了从服务器。线程现在正空闲,等待由主服务器上新的更新导致的出现在二进制日志中的新事件。
  • 从服务器I/O线程
    Waiting for master to send event线程已经连接上主服务器,正等待二进制日志事件到达。如果主服务器正空闲,会持续较长的时间。如果等待持续slave_read_timeout秒,则发生超时。此时,线程认为连接被中断并企图重新连接。
  • 从服务器SQL线程
    Reading event from the relay log线程已经从中继日志读取一个事件,可以对事件进行处理了。
    Has read all relay log; waiting for the slave I/O thread to update it 线程已经处理了中继日志文件中的所有事件,现在正等待I/O线程将新事件写入中继日志。

要实现 MySQL 的 Replication ,首先必须打开 Master 端的Binary Log(mysql-bin.xxxxxx)功能,否则无法实现。因为整个复制过程实际上就是Slave从Master端获取该日志然后再在自己身上完全顺序的执行日志中所记录的各种操作。打开 MySQL 的 Binary Log 可以通过在启动 MySQL Server 的过程中使用 “—log-bin” 参数选项,或者在 my.cnf 配置文件中的 mysqld 参数组([mysqld]标识后的参数部分)增加 “log-bin” 参数项。
MySQL 复制的基本过程:
Master将改变binary log events记录到二进制日志(binary log)中;
Slave将Master的binary log events拷贝到它的中继日志(relay log);
Slave重做中继日志中的事件,将改变反映它自己的数据。
这里写图片描述
 1. Slave 上面的IO线程连接上 Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;
 2. Master 接收到来自 Slave 的 IO 线程的请求后,通过负责复制的 IO 线程根据请求信息读取指定日志指定位置之后的日志信息,返回给 Slave 端的 IO 线程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息在 Master 端的 Binary Log 文件的名称以及在 Binary Log 中的位置;
 3. Slave 的 IO 线程接收到信息后,将接收到的日志内容依次写入到 Slave 端的Relay Log文件(mysql-relay-bin.xxxxxx)的最末端,并将读取到的Master端的bin-log的文件名和位置记录到master- info文件中,以便在下一次读取的时候能够清楚的高速Master“我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我”
 4. Slave 的 SQL 线程检测到 Relay Log 中新增加了内容后,会马上解析该 Log 文件中的内容成为在 Master 端真实执行时候的那些可执行的 Query 语句,并在自身执行这些 Query。这样,实际上就是在 Master 端和 Slave 端执行了同样的 Query,所以两端的数据是完全一样的。
复制相关的文件:

  • mysql-bin.index:服务器一旦开启二进制日志,会产生一个与二日志文件同名且以.index结尾的文件,它用于跟踪磁盘上存在哪些二进制日志文件;MySQL用它来定位二进制日志文件。
  • mysql-relay-bin.index:该文件的功能与mysql-bin.index类似,即中继日志的索引。
  • master.info:保存master的相关信息。不要删除它,否则,slave重启后不能连接master;I/O线程更新master.info文件。
  • relay-log.info:包含slave中当前二进制日志和中继日志的信息。

MySQL支持的复制类型:

  • 基于行:把改变的内容复制过去,而不是把命令在从服务器上执行一遍. 从mysql5.0开始支持
  • 基于语句: 在主服务器上执行的SQL语句,在从服务器上执行同样的语句。MySQL默认采用基于语句的复制,效率比较高;
    一旦发现没法精确复制时,会自动选着基于行的复制。
  • 混合类型: 默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制。

基于语句的复制(Statement-Based Replication)
MySQL 5.0及之前的版本仅支持基于语句的复制(logical replication),这在数据库并不常见。master记录下改变数据的查询,然后,slave从中继日志中读取事件,并执行它,这些SQL语句与master执行的语句一样。基于语句的复制的二进制日志可以很好的进行压缩,而且日志的数据量也较小,占用带宽少——例如,一个更新GB的数据的查询仅需要几十个字节的二进制日志。而mysqlbinlog对于基于语句的日志处理十分方便。
但是,基于语句的复制并不是像它看起来那么简单,因为一些查询语句依赖于master的特定条件,例如,master与slave可能有不同的时间。所以,MySQL的二进制日志的格式不仅仅是查询语句,还包括一些元数据信息,例如,当前的时间戳。还有一些语句,比如CURRENT USER函数也不能正确的进行复制。此外,存储过程和触发器也是一个问题。
基于语句的复制必须是串行化的。这要求大量特殊的代码,配置,例如InnoDB的next-key锁等。并不是所有的存储引擎都支持基于语句的复制。
基于记录的复制(Row-Based Replication)
MySQL增加基于记录的复制,在二进制日志中记录下实际数据的改变,这与其它一些DBMS的实现方式类似。这种方式的优点就是可以对任何语句都能正确工作,一些语句的效率更高。主要的缺点就是二进制日志可能会很大,而且不直观,所以,不能使用mysqlbinlog来查看二进制日志。
对于一些语句,基于记录的复制能够更有效的工作,另一方面,有些基于语句的复制更有效:由于两种方式不能对所有情况都能很好的处理,所以,MySQL 5.1支持在基于语句的复制和基于记录的复制之前动态交换。可以通过设置session变量binlog_format来进行控制。
发送复制事件到其它slave
这里写图片描述
当设置log_slave_updates时,Slave可以扮演其它Slave的Master。此时,Slave把SQL线程执行的事件写进行自己的二进制日志(binary log),然后,它的Slave可以获取这些事件并执行它。
复制过滤(Replication Filters)
复制过滤可以只复制服务器中的一部分数据,有两种复制过滤:在Master上过滤二进制日志中的事件;在Mlave上过滤中继日志中的事件。
这里写图片描述
复制的常用拓扑结构
复制的体系结构有以下一些基本原则:
每个Slave只能有一个Master;
这里写图片描述
每个Slave只能有一个唯一的服务器ID;
每个Master可以有很多Slave;
这里写图片描述
MySQL不支持多主服务器复制——即一个Slave从多个Master来进行复制的架构,主要是为了避免冲突的问题,防止多个数据源之间的数据出现冲突,而造成最后数据的不一致性。以后是否会支持就不清楚了。但是,通过一些简单的组合,采用MySQL Cluster,以及将Cluster和Replication结合起来,却可以建立灵活而强大的高性能的数据库平台。
主动模式的Master-Master in Active-Active Mode
Master-Master复制的两台服务器,既是Master,又是另一台服务器的Slave。这样,任何一方所做的变更,都会通过复制应用到另外一方的数据库中。
可能有些读者朋友会有一个担心,这样搭建复制环境之后,难道不会造成两台MySQL之间的循环复制么?
实际上MySQL自己早就想到了这一点,所以在MySQL的BinaryLog中记录了当前MySQL的server-id,而且这个参数也是我们搭建MySQLReplication的时候必须明确指定,而且Master和Slave的server-id参数值比需要不一致才能使MySQLReplication搭建成功。一旦有了server-id的值之后,MySQL就很容易判断某个变更是从哪一个MySQLServer最初产生的,所以就很容易避免出现循环复制的情况。而且,如果我们不打开记录Slave的BinaryLog的选项(–log-slave-update)的时候,MySQL根本就不会记录复制过程中的变更到BinaryLog中,就更不用担心可能会出现循环复制的情形了。
主动的Master-Master复制有一些特殊的用处。例如,地理上分布的两个部分都需要自己的可写数据副本。这种结构最大的问题就是更新冲突。假设一个表只有一行(一列)的数据,其值为1,如果两个服务器分别同时执行如下语句:
在第一个服务器上执行:
mysql> UPDATE tbl SET col=col + 1;
在第二个服务器上执行:
mysql> UPDATE tbl SET col=col * 2;
那么结果是多少呢?一台服务器是4,另一个服务器是3,造成数据不同步,但是这并不会产生错误。
主动-被动模式的Master-Slave in Active-Passive Mode
由一个Master和一个Slave组成复制系统是最简单的架构,由Master-Master结构变化而来的,它避免了M-M的缺点,具有容错和高可用性的系统。它与M-M不同点在于其中一个服务只能进行只读操作。
这里写图片描述
单一Master和多slave
在实际应用场景中,MySQL复制90%以上都是一个Master复制到一个或者多个Slave的架构模式,Slave之间并不相互通信,只与Master进行通信。一主多从的架构主要用于读压力比较大的应用的数据库端廉价扩展解决方案。因为只要Master和Slave的压力不是太大(尤其是Slave端压力)的话,异步复制的延时一般都很少很少。尤其是自从Slave端的复制方式改成两个线程处理之后,更是减小了Slave端的延时问题。而带来的效益是,对于数据实时性要求不是特别Critical的应用,只需要通过廉价的pcserver来扩展Slave的数量,将读压力分散到多台Slave的机器上面,即可通过分散单台数据库服务器的读压力来解决数据库端的读性能瓶颈,毕竟在大多数数据库应用系统中的读压力还是要比写压力大很多。这在很大程度上解决了目前很多中小型网站的数据库压力瓶颈问题,甚至有些大型网站也在使用类似方案解决数据库瓶颈。
这里写图片描述
如果写操作较少,而读操作很时,可以采取这种结构,将读操作分布到其它的Slave,从而减小Master的压力。但是,当Slave增加到一定数量时,Slave对Master的负载以及网络带宽都会成为一个严重的问题。
这种结构虽然简单,但是,它却非常灵活,足够满足大多数应用需求。一些建议:

  • 不同的Slave扮演不同的作用(例如使用不同的索引,或者不同的存储引擎);
  • 用一个Slave作为备用Master,只进行复制;
  • 用一个远程的Slave,用于灾难恢复;

级联复制架构 Master –Slaves - Slaves
在有些应用场景中,可能读写压力差别比较大,读压力特别的大,一个Master可能需要上10台甚至更多的Slave才能够支撑注读的压力。这时候,Master就会比较吃力了,因为仅仅连上来的SlaveIO线程就比较多了,这样写的压力稍微大一点的时候,Master端因为复制就会消耗较多的资源,很容易造成复制的延时。
这时候就可以利用MySQL可以在Slave端记录复制所产生变更的BinaryLog信息的功能,也就是打开—log-slave-update选项。然后,通过二级(或者是更多级别)复制来减少Master端因为复制所带来的压力。也就是说,首先通过少数几台MySQL从Master来进行复制,这几台机器称之为第一级Slave集群,然后其他的Slave再从第一级Slave集群来进行复制。从第一级Slave进行复制的Slave,称之为第二级Slave集群。如果有需要,可以继续往下增加更多层次的复制。这样,很容易就控制了每一台MySQL上面所附属Slave的数量。这种多层级联复制的架构,很容易就解决了Master端因为附属Slave太多而成为瓶颈的风险。
这里写图片描述
当然,如果条件允许,更倾向于建议通过拆分成多个Replication集群来解决
上述瓶颈问题。毕竟Slave并没有减少写的量,所有Slave实际上仍然还是应用了所有的数据变更操作,没有减少任何写IO。相反,Slave越多,整个集群的写IO总量也就会越多,仅仅只是因为分散到了多台机器上面,所以不是很容易表现出来。此外,增加复制的级联层次,同一个变更传到最底层的Slave所需要经过的MySQL也会更多,同样可能造成延时较长的风险。而如果通过分拆集群的方式来解决的话,可能就会要好很多了,当然,分拆集群也需要更复杂的技术和更复杂的应用系统架构。
带从服务器的Master-Master结构(Master-Master with Slaves)
这种结构的优点就是提供了冗余。在地理上分布的复制结构,它不存在单一节点故障问题,而且还可以将读密集型的请求放到slave上。
这里写图片描述
级联复制在一定程度上面确实解决了Master因为所附属的Slave过多而成为瓶颈的问题,但是并不能解决人工维护和出现异常需要切换后可能存在重新搭建Replication的问题。这样就很自然的引申出了DualMaster与级联复制结合的Replication架构,称之为Master-Master-Slaves架构,和Master-Slaves-Slaves架构相比,区别仅仅只是将第一级Slave集群换成了一台单独的Master,作为备用Master,然后再从这个备用的Master进行复制到一个Slave集群。
这种DualMaster与级联复制结合的架构,既可以避免主Master的写入操作不会受到Slave集群的复制所带来的影响,同时主Master需要切换的时候也基本上不会出现重搭Replication的情况。但是,这个架构也有一个弊端,那就是备用的Master有可能成为瓶颈,因为如果后面的Slave集群比较大的话,备用Master可能会因为过多的SlaveIO线程请求而成为瓶颈。当然,该备用Master不提供任何的读服务的时候,瓶颈出现的可能性并不是特别高,如果出现瓶颈,也可以在备用Master后面再次进行级联复制,架设多层Slave集群。当然,级联复制的级别越多,Slave集群可能出现的数据延时也会更为明显,所以考虑使用多层级联复制之前,也需要评估数据延时对应用系统的影响。
参考文章:http://blog.csdn.net/hguisu/article/details/7325124

0 0
原创粉丝点击