可扩展性设计之 MySQL Replication(下)

443 阅读12分钟

四、Replication 搭建实现

MySQL Replication 环境的搭建实现比较简单,总的来说其实就是四步,第一步是做好 Master 端的准备工作。第二步是取得 Master 端数据的“快照”备份。第三步则是在 Slave 端恢复 Master 的备份“快照”。第四步就是在 Slave 端设置 Master 相关配置,然后启动复制。在这一节中,并不是列举一个搭建 Replication 环境的详细过程,因为这在 MySQL 官方操作手册中已经有较为详细的描述了,我主要是针对搭建环境中几个主要的操作步骤中可以使用的各种实现方法的介绍,下面我们针对这四步操作及需要注意的地方进行一个简单的分析。

①Master 端准备工作

在搭建 Replication 环境之前,首先要保证 MasterMySQL 记录 Binary Log 的选项打开,因为 MySQL Replication 就是通过 Binary Log 来实现的。让 MasterMySQL 记录 Binary Log 可以在启动 MySQL Server 的时候使用 —log-bin 选项或者在 MySQL 的配置文件 my.cnf 中配置 log-bin[=path for binary log]参数选项。

在开启了记录 Binary Log 功能之后,我们还需要准备一个用于复制的 MySQL 用 户 。可以通过给一个现有帐户授予复制相关的权限,也可以创建一个全新的专用于复制的帐户。当然,我还是建议用一个专用于复制的帐户来进行复制。在之前“MySQL 安全管理”部分也已经介绍过了,通过特定的帐户处理特定一类的工作,不论是在安全策略方面更有利,对于维护来说也有更大的便利性。实现 MySQL Replication 仅仅只需要“REPLICATION SLAVE”权限即可。可以通过如下方式来创建这个用户:

root@localhost : mysql 04:16:18> CREATE USER 'repl'@'192.168.0.2'
-> IDENTIFIED BY 'password';
Query OK, 0 rows affected (0.00 sec)
root@localhost : mysql 04:16:34> GRANT REPLICATION SLAVE ON *.*
-> TO 'repl'@'192.168.0.2';
Query OK, 0 rows affected (0.00 sec)

这里首先通过 CREATE USER 命令创建了一个仅仅具有最基本权限的用户 repl,然后再通过 GRANT 命令授予该用户 REPLICATION SLAVE 的权限。当然,我们也可以仅仅执行上面的第二条命令,即可创建出我们所需的用户。

②获取 Master 端的备份“快照”

这里所说的 Master 端的备份“快照”,并不是特指通过类似 LVM 之类的软件所做的 snapshot,而是所有数据均是基于某一特定时刻的,数据完整性和一致性都可以得到保证的备份集。同时还需要取得该备份集时刻所对应的 MasterBinary Log 的准确 Log Position,因为在后面配置 Slave 的时候会用到。

一般来说,我们可以通过如下集中办法获得一个具有一致性和完整性的备份集以及所对应的 Log Position

  • 通过数据库全库冷备份

对于可以停机的数据库,我们可以通过关闭 MasterMySQL,然后通过 copy 所有数据文件和日志文件到需要搭建 Slave 的主机中合适的位置,这样所得到的备份集是最完整的。在做完备份之后,然后再启动 Master 端的 MySQL

当然,这样我们还仅仅只是得到了一个满足要求的备份集,我们还需要这个备份集所对应的日志位置才能可以。对于这样的备份集,我们有多种方法可以获取到对应的日志位置。如在 Master 刚刚启动之后,还没有应用程序连接上 Master 之前,通过执行 SHOW Master STATUS 命令从 Master 端获取到我们可以使用的 Log Position。如果我们无法在 Master 启动之后控制应用程序的连接,那么可能在我们还没有来得及执行 SHOW Master STATUS 命令之前就已经有数据写进来了,这时候我们可以通过 mysqlbinlog 客户端程序分析 Master 最新的一个 Binary Log 来获取其第一个有效的 Log Position。当然,如果你非常清楚你所使用的 MySQL 版本每一个新的 Binary Log 第一个有效的日志位置,自然就不需要进行任何操作就可以。

  • 通过 LVM 或者 ZFS 等具有 snapshot 功能的软件进行“热备份”

如果我们的 Master 是一个需要满足 365 * 24 * 7 服务的数据库,那么我们就无法通过进行冷备份来获取所需要的备份集。这时候,如果我们的 MySQL 运行在支持 Snapshot 功能的文件系统上面(如 ZFS),或者我们的文件系统虽然不支持 Snapshot,但是我们的文件系统运行在 LVM 上面,那么我们都可以通过相关的命令对 MySQL 的数据文件和日志文件所在的目录就做一个 Snapshot,这样就可以得到了一个基本和全库冷备差不多的备份集。

当然,为了保证我们的备份集数据能够完整且一致,我们需要在进行 Snapshot 过程中通过相关命令(FLUSH TABLES WITH READ LOCK)来锁住所有表的写操作,也包括支持事务的存储引擎中 commit 动作,这样才能真正保证该 Snapshot 的所有数据都完整一致。在做完 Snapshot 之后,我们就可以 UNLOCK TABLES 了。可能有些人会担心,如果锁住了所有的写操作,那我们的应用不是就无法提供写服务了么?确实,这是无法避免的,不过,一般来说 Snapshot 操作所需要的时间大都比较短,所以不会影响太长时间。

Log Position 怎么办呢?是的,通过 Snapshot 所做的备份,同样需要一个该备份所对应的 Log Position 才能满足搭建 Replication 环境的要求。不过,这种方式下,我们可以比进行冷备份更容易获取到对应的 Log Position。因为从我们锁定了所有表的写入操作开始到解锁之前,数据库不能进行任何写入操作,这个时间段之内任何时候通过执行 SHOW MASTER STATUS 明令都可以得到准确的 Log Position

由于这种方式在实施过程中并不需要完全停掉 Master 来进行,仅仅只需要停止写入才做,所以我们也可以称之为“热备份”。

  • 通过 mysqldump 客户端程序

如果我们的数据库不能停机进行冷备份,而且 MySQL 也没有运行在可以进行 Snapshot 的文件系统或者管理软件之上,那么我们就需要通过 mysqldump 工具来将 Master 端需要复制的数据库(或者表)的数据 dump 出来。为了让我们的备份集具有一致性和完整性,我们必须让 dump 数据的这个过程处于同一个事务中,或者锁住所有需要复制的表的写操作。要做到这一点,如果我们使用的是支持事务的存储引擎(如 Innodb),我们可以在执行 mysqldump 程序的时候通过添加 —single-transaction 选项来做到,但是如果我们的存储引擎并不支持事务,或者是需要 dump 表仅仅只有部分支持事务的时候,我们就只能先通过 FLUSH TABLES WITH READ LOCK 命令来暂停所有写入服务,然后再 dump 数据。当然,如果我们仅仅只需要 dump 一个表的数据,就不需要这么麻烦了,因为 mysqldump 程序在 dump 数据的时候实际上就是每个表通过一条 SQL 来得到数据的,所以单个表的时候总是可以保证所取数据的一致性的。

上面的操作我们还只是获得了合适的备份集,还没有该备份集所对应的 Log Position,所以还不能完全满足搭建 Slave 的要求。幸好 mysqldump 程序的开发者早就考虑到这个问题了,所以给 mysqldump 程序增加了另外一个参数选项来帮助我们获取到对应的 Log Position,这个参数选项就是 —master-data 。当我们添加这个参数选项之后,mysqldump 会在 dump 文件中产生一条 CHANGE MASTER TO 命令,命令中记录了 dump 时刻所对应的详细的 Log Position 信息。如下:

测试 dump example 数据库下的 group_message 表:

sky@sky:~$ mysqldump --master-data -usky -p example group_message >
group_message.sql
Enter password:

然后通过 grep 命令来查找一下看看:

sky@sky:~$ grep "CHANGE MASTER" group_message.sql
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000035', MASTER_LOG_POS=399;

CHANGE MASTER TO 的命令都已经给我们准备好了,还真够体贴的,呵呵。

如果我们是要一次性 dump 多个支持事务的表的时候,可能很多人会选择通过添加 —single-transaction 选项来保证数据的一致性和完整性。这确实是一个不错的选择。但是,如果我们需要 dump 的数据量比较大的时候,可能会产生一个很大的事务,而且会持续较长的时间。

  • 通过现有某一个 Slave 端进行“热备份”

如果现在已经有 Slave 从我们需要搭建 Replication 环境的 Master 上进行复制的话,那我们这个备份集就非常容易取得了。我们可以暂时性的停掉现有 Slave(如果有多台则仅仅只需要停止其中的一台),同时执行一次 FLUSH TABLES 命令来刷新所 有表和索引的数据。这时候在该 Slave 上面就不会再有任何的写入操作了,我们既可以通过 copy 所有的数据文件和日志文件来做一个全备份,同时也可以通过 Snapshot(如果支持)来进行备份。当然,如果支持 Snapshot 功能,还是建议大家通过 Snapshot 来做,因为这样可以使 Slave 停止复制的时间大大缩短,减少该 Slave 的数据延时。

通过现有 Slave 来获取备份集的方式,不仅仅得到数据库备份的方式很简单,连所需要 Log Position,甚至是新 Slave 后期的配置等相关动作都可以省略掉,只需要新的 Slave 完全基于这个备份集来启动,就可以正常从 Master 进行复制了。

整个过程中我们仅仅只是在短暂时间内停止了某台现有 Slave 的复制线程,对系统的正常服务影响很小,所以这种方式也基本可以称之为“热备份”。

③Slave 端恢复备份“快照”

上面第二步我们已经获取到了所需要的备份集了,这一步所需要做的就是将上一步所得到的备份集恢复到我们的 Slave 端的 MySQL 中。

针对上面四种方法所获取的备份集的不同,在 Slave 端的恢复操作也有区别。下面就针对四种备份集的恢复做一个简单的说明:

  • 恢复全库冷备份集

由于这个备份集是一个完整的数据库物理备份,我们仅仅只需要将这个备份集通过 FTP 或者是 SCP 之类的网络传输软件复制到 Slave 所在的主机,根据 Slavemy.cnf 配置文件的设置,将文件存放在相应的目录,覆盖现有所有的数据和日志等相关文件,然后再启动 Slave 端的 MySQL,就完成了整个恢复过程。

  • 恢复对 Master 进行 Snapshot 得到的备份集

对于通过对 Master 进行 Snapshot 所得到的备份集,实际上和全库冷备的恢复方法基本一样,唯一的差别只是首先需要将该 Snapshot 通过相应的文件系统 mount 到某个目录下,然后才能进行后续的文件拷贝操作。之后的相关操作和恢复全库冷备份集基本一致,就不再累述。

  • 恢复 mysqldump 得到的备份集

通过 mysqldump 客户端程序所得到的备份集,和前面两种备份集的恢复方式有较大的差别。因为前面两种备份集的都属于物理备份,而通过 mysqldump 客户端程序所做的备份属于逻辑备份。恢复 mysqldump 备份集的方式是通过 mysql 客户端程序来执行备份文件中的所有 SQL 语句。

使用 mysql 客户端程序在 Slave 端恢复之前,建议复制出通过 —master-data 所得到的 CHANGE MASTER TO 命令部分,然后在备份文件中注销掉该部分,再进行恢复 。因为该命令并不是一个完整的 CHANGE MASTER TO 命令,如果在配置文件(my.cnf)中没有配置 MASTER_HOSTMASTER_USERMASTER_PASSWORD 这三个参数的时候,该语句是无法有效完成的。

通过 mysql 客户端程序来恢复备份的方式如下:

sky@sky:~$ mysql -u sky -p -Dexample < group_message.sql

这样即可将之前通过 mysqldump 客户端程序所做的逻辑备份集恢复到数据库中了。

  • 恢复通过现有 Slave 所得到的热备份

通过现有 Slave 所得到的备份集和上面第一种或者第二种备份集也差不多。如果是通过直接拷贝数据和日志文件所得到的备份集,那么就和全库冷备一样的备份方式,如果是通过 Snapshot 得到的备份集,就和第二种备份恢复方式完全一致。

④配置并启动 Slave

在完成了前面三个步骤之后, Replication 环境的搭建就只需要最后的一个步骤了,那就是通过 CHANGE MASTER TO 命令来配置 然后再启动 Slave 了。

CHANGE MASTER TO 命令总共需要设置 5 项内容,分别为:

  • MASTER_HOSTMaster 的主机名(或者 IP 地址);
  • MASTER_USERSlave 连接 Master 的用户名,实际上就是之前所创建的 repl 用户;
  • MASTER_PASSWORDSlave 连接 Master 的用户的密码;
  • MASTER_LOG_FILE:开始复制的日志文件名称;
  • MASTER_LOG_POS:开始复制的日志文件的位置,也就是在之前介绍备份集过程中一致提到的 Log Position

下面是一个完整的 CHANGE MASTER TO 命令示例:

CHANGE MASTER TO
root@localhost : mysql 08:32:38> CHANGE MASTER TO
-> MASTER_HOST='192.168.0.1',
-> MASTER_USER='repl',
-> MASTER_PASSWORD='password',
-> MASTER_LOG_FILE='mysql-bin.000035',
-> MASTER_LOG_POS=399;

执行完 CHANGE MASTER TO 命令之后,就可以通过如下命令启动 SLAVE 了:

root@localhost : mysql 08:33:49> START SLAVE;

至此,我们的 Replication 环境就搭建完成了。读者朋友可以自己进行相应的测试来尝试搭建,如果需要了解 MySQL Replication 搭建过程中更为详细的步骤,可以通过查阅 MySQL 官方手册。

总结

在实际应用场景中,MySQL Replication 是使用最为广泛的一种提高系统扩展性的设计手段。 众多的 MySQL 使用者通过 Replication 功能提升系统的扩展性之后,通过简单的增加价格低廉的硬件设备成倍甚至成数量级的提高了原有系统的性能,是广大 MySQL 中低端使用者最为喜爱的功能之一,也是大量 MySQL 使用者选择 MySQL 最为重要的理由之一。