mysql的扩展性设计之主辅架构

原创文章,转载请注明:上善若水 http://www.usewo.com/ 或 http://mysuim.iteye.com

 

引言

由于mysql的master/slave架构各方面优良的特性,使得在各种互联网应用中被广泛应用。它主要用于解决两方面的问题,即数据的冗余备 份和性能扩展。本文主要讲解以下几个问题:master/slave的实现原理、系统搭建、实际场景中的各种架构,以及日常管理维护和一些问题的解决和思 路。

实现原理

实现主辅架构,使用的是mysql的复制(replication)这个特性。这个特性使得可以把一个mysql服务器(master)上的数据改 变实时的传送到另一个mysql服务器(slave)上,这个过程是异步进行的。整个复制的过程通过mysql的3个线程来完成,其中一个是master 上的IO线程,另外两个是slave上的IO线程和SQL线程。我们首先要打开master服务器的bin-log功能,打开这个功能后,在master 上面执行的DML操作语句都会记录在二进制日志里面,mysql的主辅架构就是让slave服务器通过读取这些日志并执行来保证两台服务器的数据同步。

mysql复制的过程如下:
(1) slave的IO线程不断的连接master服务器,请求指定的日志文件的指定位置的内容。读取哪个日志文件、从哪个位置开始读取,这些参数都存储在slave服务器上。

(2) master接到请求后,负责复制的IO线程就去读取指定位置的日志再返回给slave的IO线程,除此之外返回的信息还会包括新的日志文件名称(如果上一个日志文件写满的话)和新的位置。

(3) slave的IO线程接到返回的信息后,将日志内容写入relay log文件,新的日志文件名称和新的位置写入到本地的配置文件(master-info)。

(4) slave的sql线程不断的检测relay log,当发生变化的时候,会马上解析该文件,还原成可执行query语句并执行。实际上,master和slave执行了同样的query,所以两端的数据是一致的。


系统搭建

我们这里把系统的搭建分为这几步,首先是master端的准备工作;然后倒出master的数据到slave,保证slave的数据和master 一致;slave端的设置。首先要准备两台服务器,一台做为master(192.168.0.245),另一台作为 slave(192.168.0.246),并且都已经安装上了相同版本的mysql。

master端的准备工作:

(1)  配置my.cnf文件
首先打开log-bin选项:log-bin=mysql-bin
设置server-id:默认配置可能已经有这个server-id了,只需要取消注释即可,值要唯一,不能和slave的server-id一样,例如server-id = 1
重启mysql服务器。

(2)  创建一个账户,slave会使用到这个帐号来连接master。
GRANT REPLICATION rep ON *.* TO ‘replication’@'%’ IDENTIFIED BY ’123456′;

倒出数据,获取当前日志文件和指定位置

(1)  flush tables with read lock;

(2) 此时再打开一个终端,用mysqldump将数据倒出:

mysqldump -h192.168.0.245(master的ip) -uexample -p –all-database > example.sql;

(3) show master status;
show-master-status

File的值和Position的值要记下来,初始化slave的时候需要用到 。

(4) unlock tables;

slave端的设置

(1) 首先检查my.cnf的设置,如果打开了server-id选项,看看它的值是否和master的server-id是否一样,一样的话一定要修改然后重启mysql服务器。

(2) 导入数据,使得slave端的原始数据和master保持一致。

mysql  -uxxx -p < example.sql

(3) 初始化配置

CHANGE MASTER TO MASTER_HOST=’192.168.0.245′,
MASTER_PORT=3306,MASTER_USER=’replication’,
MASTER_PASSWORD=’123456′,
MASTER_LOG_FILE=’mysql-bin.000018′,
MASTER_LOG_POS=503;

(4) 启动slave线程:START SLAVE;

检查是否成功:执行show slave status;   主要查看Slave_IO_Running、Slave_SQL_Running这两个选项的值,如果都为yes则说明大功告成,如果有一个为no则说明失败,我会在文章的后面给出可能的解决方法。


实际场景中的各种主辅架构

最普通的互联网应用使用上一步的方式搭建就可以满足了,不过现实环境中有各种各样的业务需求,我们一样可以利用mysql的replication特性,搭建出更多更合适的主辅架构,如s双向复制架构、级联复制架构。

常规主辅架构(master-slaves)

也就是一主多从架构,也是使用最普遍的一种架构,见下图:master-slaves

伴随着master-slaves的通常是读写分离策略。在web应用中,随着数据的不断膨胀,数据库方面自然出现了瓶颈,一般会面临着大量的读取和写入操作,而通常情况下读操作都会比写操作更密集,通过读写分离策略可以在很大程度上解决这样的问题。

我们必须让所有写入更新操作都在master上执行,这是读写分离策略需要遵循的最基本原则,而读操作都指向了slave。

master-slaves2

一旦使用了读写分离后,应用程序的代码就需要修改,主要是修改数据访问层的代码,一定程度上也就造成了数据访问层的代码复杂度。其实也可以做到不修 改或少量修改代码,这时候需要用到一个中间代理,应该程序直接访问这个代理服务器,就像以前访问mysql一样,读写分离需要配置到代理服务器上。目前可 以使用的开源中间代理有mysql proxy和amoeba for mysql,其中amoeba是中国一个开发者开发的,目前已经一些企业尝试着在使用,我试用过,确实很方便,抽空再写一篇介绍amoeba的文章。

双向复制架构(master-master)

双向复制架构也就是说,A服务器作为B服务器的master的同时,也是B的slave,B也同理。

为什么会有这样的架构呢?比方说,有时候master可能需要做一些特别的维护必须停止,如果你只有一台master就不太好办了,或者你的master宕机了呢,于是乎就衍生出了双向复制这种架构。

如果你担心采用双向复制会发生循环复制的话,大可不必了,因为每个mysql都会有一个唯一的server-id,mysql很容易判断某个变更是从那个一个mysql服务器最初产生的。

双向架构的搭建也很容易,一般的结构如下图:

dual-master_conew1

如何搭建这里就不详细写了,方法在“系统搭建”已经写过,只不过双向master架构,需要多执行几步操作而已。

实际使用中可能只会提供一台master供应用程序写操作,因为如果同时提供外部读写的话,在某些情况下可能出现错误。

级联复制(master-slaves-slaves)

在实际场景中,也许读写压力比较大,读压力特别的大,假如一个master需要10台slave才能支撑,这时候master就会比较吃力,因为连接上来的slave IO线程就会比较多,很容易造成复制的延迟。

那怎么办呢?这里就可以使用到级联复制,那什么又是级联复制呢?我们这里把最上层的master称之为顶级master,把从属于顶级master 的slaves称之为第一级slaves,而第一级slaves同时又做为master,提供给第二级的slaves进行复制。如下图:

cascade-master-slave_conew2

要搭建这种结构,需要打开第一级的log-slave-update选项。这样的结构就解决了顶级master附属了太多slave造成的问题。

这种架构也有一些不好的地方,比如数据从顶级master传送到第二级slaves需要经过的mysql更多了,当然风险就更大了。实际使用中还可以通过拆分成多个集群来解决。


主辅架构的管理维护

查看slave的状态,确认slave是否工作正常

SHOW SLAVE STATUS\G;

正常情况下可以显示这样的结果:

Slave_IO_Running: Yes        Slave_SQL_Running: Yes

Slave_IO_Running:此线程负责slave从master服务器上读取binlog日志,并写入slave服务器上的relay log中。
Slave_SQL_Running:此线程负责读取并且执行relay log中的binlog日志
只要其中有一个进程的状态是no,则表示复制进程停止,错误原因可以从Last_Errno后面看到。

IO线程停止的几种情况

网络不通了、配置slave同步时因为slave访问master没有权限导致、master上的mysql-bin.xxxxxx文件被误删除了。如果是master二进制日志被删除了,可以采取下面的方式解决:

(1) 重启master:service mysqld restart

show master status; 【获取二进制文件名和位置】

(2) 在slave上执行以下sql:

slave stop;
change master to Master_Log_File=’mysql-bin.****’,Master_Log_Pos=**;
slave start;
show slave status;

强制slave立即和master保持同步

master/slave架构经过长时间运行,可能造成slave延迟的情况,这会造成很不好的结果,所以需要我们手动的强制让他们保持一致。步骤如下:

(1) 在master上执行以下操作

mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;

记录SHOW语句的输出的日志名和偏移量。这些是复制坐标。

(2) 在从服务器上执行以下操作

mysql> SELECT MASTER_POS_WAIT(‘log_name’, log_offset);

SELECT语句阻塞直到从服务器达到指定的日志文件和偏移量。此时,从服务器与主服务器同步,语句返回。

(3) 在master执行解锁操作,unlock tables;

在master执行的sql语句在slave上却执行失败的一种解决方法

这样的问题通常会导致SQL线程停止,可以用下面的步骤试着解决。

(1) 确定是否从服务器的表与主服务器的不同。尽力了解发生的原因。然后让从服务器的表与主服务器的一样并运行START SLAVE。

(2) 如果前面的步骤不工作或不适合,尽力了解手动更新是否安全(如果需要),然后忽视来自主服务器的下一个语句。如果你确定可以跳过来自主服务器的下一个语句,执行下面的语句:
SET GLOBAL SQL_slave_SKIP_COUNTER = n;
START SLAVE;

如果来自主服务器的下一个语句不使用AUTO_INCREMENT或LAST_INSERT_ID(),n 值应为1。否则,值应为2。使用AUTO_INCREMENT或LAST_INSERT_ID()的语句使用值2的原因是它们从主服务器的二进制日志中取两个事件。

其他问题

其外,在复制实施的过程中还可能遇到很多问题,或者很多不明白的地方,目前最有效的手段就是去看mysql手册,那里面的介绍应该说是最详细的了,我在这里介绍的一些知识,也是从手册看来的。mysql手册的第六章就是复制的完整介绍。我在下面随便列举几个问题。

Q :我怎样知道从服务器与主服务器的最新比较? 换句话说,我怎样知道从服务器复制的最后一个查询的日期?

A :你可以查看SHOW SLAVE STATUS语句的Seconds_Behind_Master列的结果。

当从服务器SQL线程执行从主服务器读取的事件时,它根据事件时间戳修改自己的时间(这是TIMESTAMP能够很好复制的原因)。在 SHOW PROCESSLIST语句输出的Time列内,为从服务器SQL线程显示的秒数是最后一个复制事件的时间戳和从服务器主机的实际时间之间相差的秒数。你 可以使用它来确定最后一个复制事件的日期。注意,如果你的从服务器与主服务器连接断开一个小时,然后重新连接,在SHOW PROCESSLIST结果中,你可以立即看到从服务器SQL线程的Time值为3600。这可能是因为从服务器执行的语句是一个一小时之前的。

Q :从服务器需要始终连接到主服务器吗?

A :不,不需要。从服务器可以宕机或断开连接几个小时甚至几天,重新连接后获得更新信息。例如,你可以 在通过拨号的链接上设置主服务器/从服务器关系,其中只是偶尔短时间内进行连接。这意味着,在任何给定时间,从服务器不能保证与主服务器同步除非你执行某 些特殊的方法。将来,我们将使用选项来阻塞主服务器直到有一个从服务器同步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值