亚马逊AWS官方博客

使用TiDB Data Migration迁移分库分表数据库到Amazon Aurora

一.概述

在传统IT时代,由于单机数据库的计算能力、存储容量、网络带宽的瓶颈限制,当表数据超过数千万条时,就会面临较严重的性能下降问题,除了提升单机硬件性能之外,常用的解决手段为;增加集中式缓存、数据库读写分离、数据库拆分。

本文主要关注数据库拆分:其指按照特定的条件和维度,将同一数据库拆分到多个数据库上以达到分布式数据库的效果,变相地降低了单个数据集的大小,本质上是以空间换时间来提升性能。数据库拆分可分为以下两种方式:

  • 数据库垂直拆分:是指按照业务耦合度,将关联性低的业务表拆分到单独的数据库。做法与所谓单体架构拆分为微服务类似,需要按业务领域进行划分。
  • 数据库水平拆分:是指将同一个表按一定策略(hash、range)分散到多个数据库或多个表中,每个表中只包含一部分数据,从而使得单个表的数据量变小,突破性能瓶颈。

对于数据库水平拆分,即我们常说的数据库分库分表(Database Sharding),通常需要借助框架或者中间件实现,具体可以归纳为如下几类:

  • CLIENT模式:借助数据库Driver层实现在客户端本地进行分库分表逻辑控制,即客户端直连多个数据库,在本地进行数据的聚合汇总等操作逻辑。代表产品有ctrip-DAL。

  • PROXY模式:即一个数据库代理,代理底层的多个数据库,且分库分表逻辑在代理端实现,对客户端透明。代表产品有MyCat、阿里云PolarDB-X(原DRDS)。

本质上,分库分表数据库是使用多个数据库+框架或者中间件实现了一个伪分布式数据库,以解决单机数据库的性能、容量瓶颈问题,但其在使用中存在诸多不便:

  • 扩容复杂度增加(需要重分布数据)。
  • 分布键选择需要谨慎,很多Sharding产品不支持多个分布键、或者不支持随机分布,导致用户不得不使用没有任何业务意义的自增序列来作为分布键。
  • 无法支持复杂查询。跨库JOIN性能差,甚至只能按分布键JOIN,其他字段不支持JOIN。
  • 分库分表代理中间件存在潜在性能风险。
  • 分布式事务性能较差,甚至不支持分布式事务。
  • SQL功能缺失,限制较多,导致应用适配成本巨大。
  • 全局一致性时间点恢复几乎不可实现,不同的数据节点处于不同的状态,没有全局统一的快照管理和恢复机制。

而在云计算时代涌现出了许多计算与存储分离的云原生数据库架构,其中的代表之一Amazon Aurora数据库,其实现了一个跨3可用区 6份数据副本的分布式存储系统,数据库卷逻辑上分为 10GB 单位大小,各个分段都分散在庞大的分布式存储队列中。如果发生故障,导致一个分段丢失,单个保护组的修复只需要移动大约10GB 的数据,几秒钟即可完成;更重要的是,Amazon Aurora 遵循日志即数据库,通过只将重做日志记录写入存储层,系统可以将网络的 IOPS 减少一个数据量级;同时将数据库系统中最复杂与关键的功能,备份恢复等等也委托给了存储层服务,与运行在类似硬件上的 Amazon RDS for MySQL 相比,Amazon Aurora MySQL 兼容版在 sysbench 基准测试中显示了5倍的写入 IOPS。

综上所述,天然生长在分布式存储上的Amazon Aurora数据库,最高容量支持128TB,完全兼容MySQL和PostgreSQL,在某些场景下5倍于MySQL的性能,相对于难以驾驭的以分库分表实现的伪分布式数据库,Amazon Aurora的优势明显。

二.方案说明

如果您也困扰于分库分表方案的繁琐复杂,那么可以尝试将您的数据库迁移到Amazon Aurora数据库,本文将对整个迁移方案和执行步骤进行详细描述:

1.    前置说明

本文示例中所使用的分库分表源端为Proxy模式,分库分表配置为2个库,每库4张表,其具体的架构以及Schema如下图所示:

请注意,使用TiDB DM迁移,对源端数据库有如下限制:

  • 源表中必须存在主键,否则DM无法迁移。
  • 源表中必须无外键关联,否则DM无法迁移。

2.  工具介绍

a.   TiDB Data Migration

本文使用的迁移合表工具为TiDB Data Migration(简称DM),可通过TiDB原生的集群运维工具TiUP完成安装和部署,DM的介绍如下:

TiDB Data Migration(DM)是一体化的数据迁移任务管理工具,支持从与 MySQL 协议兼容的数据库(MySQL、MariaDB、Aurora MySQL)到 TiDB 的数据迁移。DM工具旨在降低数据迁移的运维成本。DM数据迁移任务包含全量数据迁移、增量数据复制两个阶段:

  • 全量数据迁移:从数据源迁移对应表的表结构到 TiDB,然后读取存量数据写入到 TiDB 集群;
  • 增量数据复制:全量数据迁移完成后,从数据源读取对应的表变更然后写入到 TiDB 集群。

DM工具的核心组件如下图所示:

  • Block & allow lists

过滤规则类似于 MySQL replication-rules-db/replication-rules-table,用于过滤或指定只迁移某些数据库或某些表的所有操作。

  • Binlog event filter

用于过滤源数据库中特定表的特定类型操作,比如过滤掉表 test.sbtest 的 INSERT 操作或者过滤掉库 test 下所有表的 TRUNCATE TABLE 操作。

  • Table routing

将源数据库的表迁移到下游指定表的路由功能,比如将源数据表 test.sbtest1 的表结构和数据迁移到 TiDB 的表 test.sbtest2。

利用DM工具中Table routing模块,将上游数据按照配置的规则路由到下游,即可实现将分库分表数据库迁移到Aurora MySQL。

b.   AWS Cloud Development Kit

本文使用AWS Cloud Development Kit(CDK)一键部署DM工具到AWS EC2,并为您自动创建DM集群,实现所谓开箱即用,节省自己搭建所需的时间成本。

CDK 是一种开源软件开发框架,可让您使用熟悉的编程语言来定义云应用程序资源。预置云应用程序是一个具有挑战性的过程,您需要执行手工操作、编写自定义脚本、维护模板或学习特定领域的语言。AWS CDK 利用编程语言的常见性和表达能力为应用程序建模。CDK 提供名为结构的高级组件,使用经过验证的默认值预置云资源,因此您无需成为专家即可构建云应用程序。AWS CDK 通过 AWS CloudFormation 以安全、可重复的方式预置您的资源。它还支持您编写和分享体现组织要求的自定义结构,帮助您更快启动新项目。

3.    迁移方案

如上图所示,该方案的源库为基于某分库分表中间件,其底层为MySQL数据库,使用DM工具将其迁移到Aurora MySQL上;本质上就是使用DMWorker连接到底层的所有分库分表,然后基于所配置的数据路由规则,将所有数据路由到Aurora MySQL中的单库单表,来实现迁移,具体的步骤如下:

  1. 使用CDK脚本创建EC2集群,该EC2集群会被创建在默认VPC的Public Subnet中,通过EC2 UserData下载TiUP来安装DM程序,并部署DM集群(DMMaster + DMWorker);
  2. 基于分库分表中间件底层的所有MySQL数据库创建DM Source;
  3. 创建基于DM数据迁移任务,并且配置路由,实现合库合表;
  4. 启动任务,完成全量和增量合库合表数据迁移。

如上图所示,描述为迁移前分库分表的Schema,以及迁移后在Aurora中的Schema。

三.执行步骤

  • 安装所需软件:

找到一台Linux服务器,安装好NodeJS、Python3、PIP、CDK、AWS CLI等程序,同时完成AWS CLI的配置。具体可以参考这里

下载基于CDK实现的DM一键部署程序到本地一台Linux或者Windows服务器,下载地址https://github.com/crazyoyo/tidb-dm-autodeploy-bycdk,通过执行下述命令进行下载:

git clone https://github.com/crazyoyo/tidb-dm-autodeploy-bycdk

  • 安装所有Python的依赖:

pip install -r requirements.txt

打开config/config.json文件,进行参数配置:

参数解释:

key_pair: 创建EC2服务器的key_pair,会基于此key创建EC2集群间SSH的专用key。

instance_num: DM集群中的EC2服务器数量,即1个Master节点,其余为Worker节点;建议每个分库对应一个Worker;假设有5台分库,那么5个Worker + 1个Master,共计6。

instance_type:EC2的实例类型,生产环境的迁移建议使用M5系列实例。

ebs_volumn_size:EC2的EBS卷大小,如果使用DM执行全量迁移,本地会暂存全量导出的数据库文件,需要保证EBS卷足够大。

dm_name:DM集群的Name。

dm_version:DM集群的版本。

  • 执行CDK BootStrap:

cdk bootstrap

  • 执行CDK Deploy:

cdk deploy —require-approval never

增加—require-approval never参数可以跳过确认步骤。

  • 登录EC2查看DM集群状态:

进入CloudFormation控制台,找到tidm-migration的Stack,在右侧resources标签下找到Logical ID为“TiDMInstance00XXXXXX”的EC2,点击右侧的“Physical ID”跳转到EC2控制台,查看此EC2的公网IP。使用SSH登录此EC2,查看DM集群状态,并且记录DMMaster节点的IP。

  • 配置所有分库作为数据源:

获取分库的密码,执行如下指令,对密码进行加密,请将”中的字符串替换为您的密码,记住加密后的密码。

tiup dmctl encrypt 'abc!@#123'

针对分库创建配置文件source-sharding.yaml,具体的配置内容如下:

source-id: "source-sharding1"
enable-gtid: false
from:
  host: "database-mysql-57.xxxxxxxxxxxxxx.us-west-2.rds.amazonaws.com"
  user: "admin"
  password: "xxxxxxxxxxxxxxxxxxxxxxxx" #此处填写上述步骤中加密之后的密码
  port: 3306

执行下述命令,创建数据源,其中master-addr为之前记录的DMMaster节点IP:

tiup dmctl --master-addr 172.31.30.29:8261 operate-source create ./source-sharding1.yaml

执行下述命令,查看数据源是否创建成功:

tiup dmctl --master-addr 172.31.30.29:8261 get-config source source-sharding1

针对所有的Sharding分库,依次执行上述步骤,创建所有的数据源。

  • 创建分库分表任务:

创建task-sharding-merge.yaml,并写入如下内容:

name: "task-sharding-merge"
task-mode: all                      # 进行全量数据迁移 + 增量数据迁移
meta-schema: "dm_meta"
ignore-checking-items: ["auto_increment_ID"]

target-database:
  host: "my-aurora.cluster-xxxxxxxxxx.us-west-2.rds.amazonaws.com"
  port: 3306
  user: "admin"
  password: "xxxxxxxxxxxxxxxxxxxxxxxxxx"

mysql-instances:
  -
    source-id: "source-sharding1"    		# 数据源 ID,可以从数据源配置中获取
    route-rules: ["db-route-rule", "table-route-rule"] # 应用于该数据源的 table route 规则
    mydumper-config-name: "global"
    mydumper-thread: 16 # mydumper 用于导出数据的线程数量
    loader-thread: 16 # loader 用于导入数据的线程数量
    syncer-thread: 16 # syncer 用于同步增量数据的线程数量
  -
    source-id: "source-sharding2"
    route-rules: ["db-route-rule", "table-route-rule"]
    mydumper-config-name: "global"
    mydumper-thread: 16 # mydumper 用于导出数据的线程数量
    loader-thread: 16 # loader 用于导入数据的线程数量
    syncer-thread: 16 # syncer 用于同步增量数据的线程数量

# 所有实例共享的其他通用配置
routes:
  db-route-rule:
    schema-pattern: "trade_*"
    target-schema: "trade"
  table-route-rule:
    schema-pattern: "trade_*"
    table-pattern: "t_order_*"
    target-schema: "trade"
    target-table:  "t_order"

mydumpers:
  global:
    extra-args: "--no-locks"

执行下述指令,开始migration任务:

tiup dmctl --master-addr 172.31.30.29:8261 start-task ./task-shardingmerge.yaml

执行下述指令,查看migration任务状态:

tiup dmctl --master-addr 172.31.30.29:8261 query-status

注意,某些云数据库,由于无法获取superuser权限,导致DM在执行全量数据迁移的时候,会产生报错而退出任务,解决方案为,在任务定义文件中,为mydumpers增加”–no-locks”参数。

四.总结

TiDB Data Migration作为PingCAP开源的一款优秀的数据迁移管理工具,在经过了多个版本的迭代后,已经趋于稳定,可以用作生产级别的数据迁移;而在功能上,除了可以用来支持迁移分库分表的数据库之外,DM还能支持更多的迁移场景,本文只是抛砖引玉,具体大家可以移步DM的官方文档,做更仔细的研究。

本篇作者

陈超

AWS 迁移解决方案架构师,主要负责 AWS 迁移相关的技术支持工作,同时致力于 AWS 云服务在国内的应用及推广。加入 AWS 之前,曾在阿里巴巴工作8年,历任研发工程师、云计算解决方案架构师等,熟悉传统企业 IT 、互联网架构,在企业应用架构方面有多年实践经验。