MySQL InnoDB Cluster – A Hands on Tutorial

传统上,基于MySQL配置高可用(HA)是一项具有挑战的任务,特别是对于在MySQL方面没有进阶知识的人。即使只是计划做一次测试部署,从理解相关概念和技术到相关工具的使用、具体 命令和文件的执行和编辑,有很多需要你去了解的事情(Group Replication的 快速入门指南应该会对你有所启发)。 所以很多人一直拖着不去设置HA,直到灾难性打击和宕机事件的出现。

Oracle的MySQL团队最近发布了一个解决方案的预览版本,这个解决方案的目标是:让用户很容易就能把多个MySQL实例集成在一起提供冗余,来支持MySQL数据库高可用的特性。

在本文中,我们会使用新的MySQL Shell来创建三个沙箱实例,使用它们创建一个三个节点的Group Replication,并且使用MySQL Router作为中间层来将多个MySQL实例隐藏在一个TCP端口之后。Group Replication为InnoDB提供了同步复制和内置的Failover机制,同时Router可以让应用程序始终连接到集群中合适的节点上,除了对MySQL的连接参数做些调整外,不需要修改应用程序的任何代码。

下载和安装依赖包

除MySQL 5.7.17之外,你还需要从labs.mysql.com下载MySQL InnoDB Cluster包,里面包括以下内容:

  • MySQL Router 2.1.1 labs
  • MySQL Shell 1.0.6 labs with X AdminAPI

压缩包必须要解压,然后通过特定平台的具体方法,为各个组件安装对应的包。

部署沙箱实例

第一步是部署一个MySQL Server沙箱实例,这样我们就可以安全地玩耍以及试验,而不会影响已有的MySQL数据库。

启动MySQL Shell(像平常一样,使用non-root OS用户):

然后执行:

deploySandboxInstance()的参数是MySQL Server需要监听的TCP端口。默认情况下,沙箱会被创建在名为$HOME/mysql-sandboxes/<port>(Windows里是:C:\Users\<user>mysql-sandboxes\<port>)的目录下面。

命令执行时会提示, 为当前部署的实例设置一个MySQL root用户的密码,后面需要使用这个密码连接实例。

注意:在一个集群中的所有沙箱需要使用同样的密码

再重复两次上面的命令,每次使用不同的端口。这样,就创建了一个最多可以容忍一个节点挂掉的InnoDB Cluster。

初始化InnoDB Cluster

下一步,将shell连接到刚创建的三个实例中的一个,这个实例也即成为我们的种子实例。所谓种子实例,就是具有数据库初始状态的实例,后续加入到集群中的实例会从种子实例中复制状态到本地。由于这次我们用的是新建的空沙箱实例做演示,所以刚创建的三个MySQL实例中任何一个都可以作为种子实例。

下一步,创建InnoDB cluster。

createCluster()命令需要一个参数,用来指定InnoDB cluster的名称。这个命令还会做一些其他的事情:

  • 在正在使用的实例上面部署元数据模式(mysql.mysql_innodb_cluster_metadata)
  • 检查当前配置是否符合Group Replication的要求, 有必要的话要求修改
  • 在新集群中将自身注册为种子实例
  • 创建一些必要的内置帐号,比如复制账号
  • 启动Group Replication

沙箱实例的预配置是符合Group Replication要求的。但如果使用的是一个已经存在的实例,那么实例的一些参数配置可能需要修改。createCluster() (和addInstance()) 会确保设置都是正确的。

如果服务器尚未配置为Group Replication,那可能需要修改一些重要配置,比如开启Binary log(binlog),确保binlog格式是正确的等等。为了尽可能小的影响正在运行的节点,可以通过checkLocalInstance()来检查一个服务器是不是配置正确,并通过configLocalInstance()来重新配置。另外,如果配置修改需要重启MySQL Server,那么需要选择在合适的时间来手动处理。

向InnoDB Cluster中加入节点

现在,需要向集群中加入复制节点。我们这里使用之前创建好的空沙箱节点。通常情况下,当我们向集群中加入一个复制节点时,它的状态会落后于其它在线成员,并且需要追上种子实例的当前状态。如果种子实例中的存量数据非常大,可能需要事先用一种快速的方法克隆或者拷贝这些数据。MySQL Shell工具很快会提供一种机制让用户可以轻松地完成这个步骤。否则,Group Replication会自动同步所有已经被写入种子实例的MySQL Binary 日志中的事务,并且重新执行这些事务(这被称作Recovery)。
由于例子中种子实例的数据少到几乎没有(即只有元数据模式和内部帐户),新 加入的节点只需要追很少的数据。,因为一开始就开启了Binary 日志,所以在 种子节点上面执行的任何事务,都会在每一个新加入节点中重新执行。

向集群中加入两个空实例:

现在我们检查一下集群的当前状态:

这个命令访问InnoDB Cluster的当前状态并且输出一个简短的报告。每一个实例的状态应该是ONLINE或RECOVERING。 RECOVERING状态的意思是当前实例正在从种子节点中接收更新,并且最终会转换为ONLINE状态。

另一篇文章”How to navigate the InnoDB Cluster”里解释了如何解读不同状态 以及如何去影响它们。

另一个需要注意的点是,有一个实例(PRIMARY)被标记为R/W (可读/可写),而其它两个被标记为R/O (只读)。只有被标记为R/W的实例才可以执行更新数据库的事务。如果PRIMARY实例由于某种原因连不上了(如一次系统Crash),余下两个实例中的一个会自动取代它的位置并切换为新的PRIMARY。

部署MySQL Router

为了能处理Failover,应用程序需要了解InnoDB Cluster的拓扑结构,需要在任何时候都知道哪个实例是PRIMARY。尽管应用程序可以自己实现这些逻辑,但使用MySQL Router可以最小化工作量并 且不需要修改应用程序代码。

推荐的部署方式是将MySQL Router和应用程序部署在同一台机器上。在演示中,我们将所有的实例以及脚本运行在同一台机器上,对MySQL Router也一样。在引导过程中,MySQL Router需要连接集群并且有权限访问performance_schema、mysql_innodb_cluster_metadat,同时会创建一个被限制的只读帐号供自己使用。

如果MySQL Router已经安装好了,我们需要做的就是使用元数据服务器来引导它。在shell中通过执行下面的命令行选项来调用mysqlrouter:

MySQL Router会连接到InnoDB cluster,取到它元数据并配置它自己,以供使用。 它将自己配置为从自包含的目录运行,这样就可以在不需要root权限条件下,在同一台机器上部署多个MySQL Router实例。MySQL Router生成的配置中创建了4个端口,分为两组:每组中有一个读写会话 (它会将连接重定向到PRIMARY),和一个只读会话(它会以轮询的方式,将 连 接重定向到其中一个SECONDARY实例上)。一组是经典的MySQL连接,另一组连接 为X protocol。

如果你的应用建立了非常多的数据库连接导致PRIMARY过载,并且这些连接上不需要执行更新操作,这种情况下,可以限制连接使用只读会话来减少PRIMARY的压力。

一旦引导并配置完成,就可以启动MySQL Router(或者设置一个服务,在系统启动时自动将它启动):

现在可以使用MySQL client连接MySQL Router的一个端口,可以看到客户端是如何透明地连接到InnoDB Cluster中的实例的。为了找到客户端实际连接的实例是哪个,我们简单的访问一下port状态变量:

这里我们连接的是读写端口(6446),因而Router将我们连接到了PRIMARY实 例,这个实例监听的端口是3310。 现在,你可以尝试连接只读端口(6447),观察一下可以获得什么信息。

\sql命令可以将MySQL Shell从默认的JavaScript方式切换到SQL方式,这样就可以直接执行SQL语句了。

检查InnoDB Cluster的状态

为了检查InnoDB Cluster的状态,你可以连接到Router或者是直连到一个实例上 面去获取一个Cluster对象的引用。 如果想要对集群做修改,连接的时候必须使用Router的读写端口。

测试InnoDB Cluster

下一步,我们将要测试一下InnoDB Cluster,检验failover是否真的可以正常工作。我们将会把PRIMARY kill掉,然后观察是不是有其它节点自动取代它。为了这个目的我们使用了dba.killLocalInstance() 函数 (\js 模式下)。

之后我们再检查一下(从测试会话到MySQL Router)现在连接的是哪一个实例。第一个SELECT失败了是因为我们之前对PRIMARY的连接已经断掉了,MySQL Shell 会自动的重连。我们再次执行命令即可:

这说明了InnoDB Cluster可以为我们提供自动的failover,MySQL Router已经自动地连接到了新的PRIMARY实例,从而我们有了高可用。

通过这篇文章的介绍,你应该可以开始使用MySQL InnoDB clusters,轻松体验高可用了。

如果你在预览版中发现了问题或者有功能需求 ,请在 bugs.mysql.com上面创建一个bug。如果你不确定该怎么归类,请使用MySQL Server: Document Store: X Shell。

Leave a Reply