数据迁移 #
当业务持续快速发展,数据量和并发量达到一定程度,传统单体数据库可能面临性能、可扩展性及可用性等问题。业界曾提出 NoSQL 解决方案,通过数据分片和水平扩容解决以上问题,但是 NoSQL 数据库通常不支持事务和 SQL。
SphereEx-DBPlusEngine 支持对传统单机数据库进行数据分片,同时还支持分布式事务和 SQL,可以解决以上问题。SphereEx-DBPlusEngine 提供的数据迁移方案可以助力传统单体数据库平滑切换到 SphereEx-DBPlusEngine 分布式集群中。
概述 #
SphereEx-DBPlusEngine 数据迁移插件实现了同构数据库由单体到分布式的拆分迁移,该迁移操作可在线完成,同时支持源端目标段的数据比对。SphereEx-DBPlusEngine 数据库迁移可减少数据迁移时的业务影响,提供一站式的通用数据迁移解决方案。
目前 SphereEx-DBPlusEngine 数据迁移插件所支持的数据库产品为 MySQL、MySQL分支版本、PostgreSQL 和 openGauss,具体版本、环境要求和权限要求如下。
数据库 | 版本支持 | 环境要求 | 权限要求 | |
---|---|---|---|---|
1 | MySQL | 5.1.15 ~ 8.x | my.cnf 配置[mysqld] server-id=1 log-bin=mysql-bin binlog-format=row binlog-row-image=full –确认命令如下 show variables like ‘%log_bin%’; show variables like ‘%binlog%’; | GRANT REPLICATION SLAVE, REPLICATION CLIENT ON . TO ${username}@${host} –确认命令如下 SHOW GRANTS FOR ‘user’; |
2 | Aurora MySQL | 3.02.2 | my.cnf 配置[mysqld] server-id=1 log-bin=mysql-bin binlog-format=row binlog-row-image=full –确认命令如下 show variables like ‘%log_bin%’; show variables like ‘%binlog%’; | GRANT REPLICATION SLAVE, REPLICATION CLIENT ON . TO ${username}@${host} –确认命令如下 SHOW GRANTS FOR ‘user’; |
3 | PostgreSQL | 9.4 或以上版本 | postgresql.conf 配置:wal_level = logical max_wal_senders = 10 max_replication_slots = 10 max_connections = 600 | pg_hba.conf 配置:host replication repl_acct 0.0.0.0/0 md5 |
4 | openGauss | 2.0.1 ~ 3.0.0 | postgresql.conf 配置:wal_level = logical max_wal_senders = 10 max_replication_slots = 10 max_connections = 600 | pg_hba.conf 配置:host replication repl_acct 0.0.0.0/0 md5 |
5 | MariaDB | 5.1 及以上 | my.cnf 配置log-bin=mysql-bin binlog-format=row binlog-row-image=full –确认命令如下 show variables like ‘%log_bin%’; show variables like ‘%binlog%’; | GRANT REPLICATION SLAVE, REPLICATION CLIENT ON . TO ${username}@${host} –确认命令如下 SHOW GRANTS FOR ‘user’; |
在作业执行过程中,SphereEx-DBPlusEngine 能够根据集群资源情况及进行合理地调度,尽可能提高整体资源利用率,避免资源争夺,从而保作业执行效率。同时也支持任务的自动故障转移,给长时间运行的任务提供必要保障。
基本概念 #
- 节点
运行计算层或存储层组件进程的实例,可以是物理机、虚拟机和容器等。
- 集群
为了提供特定服务而集合在一起的多个节点。
- 源端
原始数据所在的存储集群。
- 目标端
原始数据将要迁移的目标存储集群。
- 数据迁移作业
把数据从某一个存储集群复制到另一个存储集群的完整流程。
- 存量数据
在数据迁移作业开始前,数据节点中已有的数据。
- 增量数据
在数据迁移作业执行过程中,业务系统所产生的新数据。
适用场景 #
单体数据库存储容量或连接数不足的情况,满足同构数据库由单体迁移拆分至分片环境的场景。
如一个应用系统中的传统单体数据库,单表记录数过亿且还在快速增长,单体数据库负载持续在高位,成为系统瓶颈,需要对数据库进行迁移拆分。
源端 -> 目标端 | 全量迁移 | 增量迁移 | 数据校验 | |
---|---|---|---|---|
1 | MySQL -> MySQL | 支持 | 支持 | 支持 |
2 | PostgreSQL -> PostgreSQL | 支持 | 支持 | 支持 |
3 | openGauss -> openGauss | 支持 | 支持 | 支持 |
4 | Oracle -> MySQL | 支持 | 不支持 | 支持 |
5 | Oracle -> PostgreSQL | 支持 | 不支持 | 支持 |
6 | Aurora -> Aurora | 支持 | 支持 | 支持 |
使用前提 #
- 已完成 SphereEx-DBPlusEngine 和目标端数据库环境部署,网络通畅且服务正常。
- 迁移作业流程中需要依赖 Zookeeper,需提前完成部署。
- 在增量追数据阶段,请务必确保数据库日志不能被清除。
- 数据迁移后需要对数据进行一致性校验,该阶段需要窗口时间,需提前规划。
使用限制 #
支持项 #
- 将外围数据迁移至 Apache ShardingSphere 所管理的数据库;
- 目标端 proxy 不配置规则或配置任意规则;
- 迁移单字段主键或唯一键的表,首字段类型:整型、字符型、部分二进制类型(比如 MySQL VARBINARY);
- 迁移复合主键或复合唯一键的表;
- 支持断点续传。
不支持项 #
- 不支持在当前存储节点之上做迁移,需要准备一个全新的数据库集群作为迁移目标库;
- 不支持目标端 proxy 使用 HINT 分片策略;
- 不支持目标端表结构和源端不一致;
- 源端表结构变更不会自动同步。
注意事项 #
在存量和增量数据迁移的阶段,可在线进行传输,对业务无影响。而流量切换阶段,需要一定窗口时间,来确保源端和目标端数据已追平,该阶段需要短暂的停止业务。
目前
mode
必须是Cluster
,需要提前启动对应的注册中心。
配置示例:
mode:
type: Cluster
repository:
type: ZooKeeper
props:
namespace: governance_ds
server-lists: localhost:2181
retryIntervalMilliseconds: 500
timeToLiveSeconds: 60
maxRetries: 3
operationTimeoutMilliseconds: 500
原理介绍 #
SphereEx-DBPlusEngine 数据迁移通过 4 个阶段来完成单体库到分片的数据迁移:准备阶段、存量数据迁移阶段、增量数据同步阶段及流量切换阶段。
- 准备阶段
在准备阶段,数据迁移模块会进行数据源连通性及权限的校验,同时进行存量数据的统计、日志位点的记录,最后根据数据量和用户设置的并行度,对任务进行分片。
- 存量数据迁移阶段
执行在准备阶段拆分好的存量数据迁移任务,存量迁移阶段采用 JDBC 查询的方式,直接从源端读取数据,基于配置的分片等规则写入到目标端。
- 增量数据同步阶段
由于存量数据迁移耗费的时间受到数据量和并行度等因素影响,此时需要对这段时间内业务新增的数据进行同步。 不同的数据库使用的技术细节不同,但总体上均为基于复制协议或 WAL 日志实现的变更数据捕获功能。
MySQL:订阅并解析 binlog;
PostgreSQL:采用官方逻辑复制 test_decoding。
这些捕获的增量数据,同样会由数据迁移模块写入到新数据节点中。当增量数据基本同步完成时(由于业务系统未停止,增量数据是不断的),则进入流量切换阶段。
- 流量切换阶段
在此阶段,可能存在一定时间的业务只读窗口期,通过 SphereEx-DBPlusEngine 的停写功能或者设置数据库只读、控制源头写流量等方式,让源端数据节点中的数据短暂静态,确保增量同步完全完成。
这个只读窗口期时长取决于用户是否需要对数据进行一致性校验以及数据量。一致性校验是独立的任务,支持单独启停,支持断点续传。
确认完成后,数据迁移完成。 然后用户可以把读流量或者写流量切换到 SphereEx-DBPlusEngine。
使用指南 #
- 制定分片策略
在数据迁移前,需要结合业务制定合理的分片策略,相关内容请参考分片插件。
- 优化数据迁移配置(可选)
SphereEx-DBPlusEngine 提供了数据迁移的优化配置,可对数据抽取及数据写入的线程进行控制。在资源充沛的情况下,可最大限度使用资源,高效完成迁移作业。同时,为了尽量减少对业务系统的影响,也可对迁移流量进行限制。
具体可参考迁移作业定义。
- 数据一致性校验(可选)
为了确保数据的一致性,可通过数据校验功能进行确认,该过程通常在窗口时间进行。同一时间只允许同时运行一个一致性校验作业,用户可以对一致性校验进行查询、中断、重启和删除。
算法描述可参考数据一致性校验算法。
- 切换元数据
确认目标环境具备上线条件后,可触发集群流量切换,完成数据迁移。
操作指南 #
数据迁移拆分的关键操作步骤如下所示,为确保两端数据一致性,切换业务前需要一定窗口时间。具体操作命令请参考数据迁移 DisSQL。
迁移规划,确认目标端数据库架构,以及分片数量
在 Proxy 中构建集群,注册目标端数据库
在 Proxy 中配置分片规则
优化迁移配置(可选)
注册源端数据源
启动数据迁移
确认迁移状态
停止业务
执行数据校验
修改业务 url
切换数据源后恢复业务
配置示例 #
本示例为通过 SphereEx-DBPlusEngine 将 MySQL 单体库迁移到 2 库 4 分片场景的操作演示。具体操作命令请参考数据迁移 DisSQL。
环境说明 #
实例 | IP 地址 | 服务端口 | 主机名 | 备注 | |
---|---|---|---|---|---|
1 | DBPlusEngine 1.3.0 | 192.168.xx.102 | 3307 | dbplusengine | |
2 | Zookeeper 3.6.3 | 192.168.xx.102 | 2181 | dbplusengine | |
3 | MySQL 5.7.26 | 192.168.xx.103 | 3306 | mysql_0 | |
4 | MySQL 5.7.26 | 192.168.xx.104 | 3306 | mysql_1 | |
5 | MySQL 5.7.26 | 192.168.xx.105 | 3306 | mysql_2 |
拓扑图 #
配置过程 #
- 准备源端环境
创建源端数据库,建表后插入若干条测试数据。
mysql -utest -p -h192.168.xx.106
mysql> CREATE DATABASE product;
mysql> SHOW DATABASES;
mysql> USE product;
mysql> CREATE TABLE `t_user` (
`user_id` int NOT NULL,
`order_id` int NOT NULL,
`status` varchar(45) DEFAULT NULL,
PRIMARY KEY (`user_id`)
);
mysql> INSERT INTO t_user VALUES
(1,1,'active'),
(2,2,'active'),
(3,3,'active'),
(4,4,'active');
mysql> SELECT * FROM t_user ORDER BY user_id;
+---------+----------+--------+
| user_id | order_id | status |
+---------+----------+--------+
| 1 | 1 | active |
| 2 | 2 | active |
| 3 | 3 | active |
| 4 | 4 | active |
+---------+----------+--------+
4 rows in set (0.00 sec)
- 准备目标端环境
在目标端中分别创建 product_1
和 product_2
数据库。
mysql -utest -p -h192.168.xx.104
mysql> CREATE DATABASE product_1;
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| product_1 |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql -utest -p -h192.168.xx.105
mysql> CREATE DATABASE product_2;
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| product_2 |
| sys |
+--------------------+
5 rows in set (0.00 sec)
- 创建逻辑库
创建逻辑库 sharding_db
。
# mysql -uroot -p -P3307
mysql> CREATE DATABASE sharding_db;
mysql> SHOW DATABASES;
在完成注册目标端数据源后,创建分片规则。
mysql> USE sharding_db;
mysql> REGISTER STORAGE UNIT ds_1 (
URL="jdbc:mysql://192.168.xx.104:3306/product_1?serverTimezone=UTC&useSSL=false",
USER="test",
PASSWORD="Test@123",
PROPERTIES("minPoolSize"="1","maxPoolSize"="20","idleTimeout"="60000")
), ds_2 (
URL="jdbc:mysql://192.168.xx.105:3306/product_2?serverTimezone=UTC&useSSL=false",
USER="test",
PASSWORD="Test@123",
PROPERTIES("minPoolSize"="1","maxPoolSize"="20","idleTimeout"="60000")
);
Query OK, 0 rows affected (0.79 sec)
mysql> SHOW STORAGE UNITS\G
mysql> CREATE SHARDING TABLE RULE t_user(
STORAGE_UNITS(ds_1,ds_2),
SHARDING_COLUMN=user_id,
TYPE(NAME="hash_mod",PROPERTIES("sharding-count"="4")),
KEY_GENERATE_STRATEGY(COLUMN=user_id,TYPE(NAME="snowflake"))
);
Query OK, 0 rows affected (18.00 sec)
mysql> SHOW SHARDING TABLE RULE t_user;
- 注册源端数据源
通过 REGISTER MIGRATION SOURCE STORAGE UNIT
命令注册源端数据源。
mysql> REGISTER MIGRATION SOURCE STORAGE UNIT ds_0 (
URL="jdbc:mysql://192.168.xx.103:3306/product?serverTimezone=UTC&useSSL=false",
USER="test",
PASSWORD="Test@123",
PROPERTIES("minPoolSize"="1","maxPoolSize"="20","idleTimeout"="60000")
);
Query OK, 0 rows affected (0.15 sec)
- 启动数据迁移
当源端和目标端环境准备好以后,即可开始启动数据迁移。
启动迁移前,可结合资源情况对迁移线程进行调整,请参考迁移作业定义。
mysql> MIGRATE TABLE ds_0.t_user INTO t_user;
Query OK, 0 rows affected (1.01 sec)
如需同时迁移多张表,可使用逗号分隔多张表的名称,格式如下。
MIGRATE TABLE ds_0.t_user INTO sharding_db.t_user,ds_0.t_user1 INTO sharding_db.t_user1,ds_0.t_t_user2 INTO sharding_db.t_user2;
迁移开始后,可通过 SHOW 命令查看迁移列表。
mysql> SHOW MIGRATION LIST;
+---------------------------------------+--------+----------------------+--------+---------------------+-----------+
| id | tables | sharding_total_count | active | create_time | stop_time |
+---------------------------------------+--------+----------------------+--------+---------------------+-----------+
| j010171e761478594bdab280c55014650e5f6 | t_user | 1 | true | 2022-09-16 15:11:34 | NULL |
+---------------------------------------+--------+----------------------+--------+---------------------+-----------+
1 row in set (0.75 sec)
根据列表中迁移 ID 的内容,进一步查看该迁移任务的状态。
mysql> SHOW MIGRATION STATUS 'j010171e761478594bdab280c55014650e5f6';
+------+-------------+-----------+--------+-------------------------------+--------------------------+
| item | data_source | status | active | inventory_finished_percentage | incremental_idle_seconds |
+------+-------------+-----------+--------+-------------------------------+--------------------------+
| 0 | | PREPARING | true | 0 | 0 |
+------+-------------+-----------+--------+-------------------------------+--------------------------+
1 row in set (0.16 sec)
mysql> SHOW MIGRATION STATUS 'j010171e761478594bdab280c55014650e5f6';
+------+-------------+--------------------------+--------+-------------------------------+--------------------------+
| item | data_source | status | active | inventory_finished_percentage | incremental_idle_seconds |
+------+-------------+--------------------------+--------+-------------------------------+--------------------------+
| 0 | ds_0 | EXECUTE_INCREMENTAL_TASK | true | 100 | 0 |
+------+-------------+--------------------------+--------+-------------------------------+--------------------------+
1 row in set (0.06 sec)
当状态为 EXECUTE_INCREMENTAL_TASK
时,可停业务对数据进行一致性校验。
停止业务,避免新数据写入源端
数据一致性校验
SphereEx-DBPlusEngine 可对源端和目标端的数据一致性进行校验,也包括两端记录数比对。
mysql> CHECK MIGRATION 'j010171e761478594bdab280c55014650e5f6' BY TYPE (NAME='CRC32_MATCH');
Query OK, 0 rows affected (0.08 sec)
目标端开启数据加密或异构迁移的情况需要使用 DATA_MATCH
或 SphereEx:DATA_DIFF
,查看数据校验算法的方法如下。
mysql> SHOW MIGRATION CHECK ALGORITHMS;
算法描述可参考数据一致性校验算法。
为进一步验证数据迁移的情况,可在物理库中对分片表依次确认。
- product_1
mysql> USE product_1;
mysql> SHOW TABLES;
+---------------------+
| Tables_in_product_1 |
+---------------------+
| t_user_0 |
| t_user_2 |
+---------------------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM t_user_0;
+---------+----------+--------+
| user_id | order_id | status |
+---------+----------+--------+
| 4 | 4 | active |
+---------+----------+--------+
1 row in set (0.00 sec)
mysql> SELECT * FROM t_user_2;
+---------+----------+--------+
| user_id | order_id | status |
+---------+----------+--------+
| 2 | 2 | active |
+---------+----------+--------+
1 row in set (0.00 sec)
- product_2
mysql> USE product_2;
mysql> SHOW TABLES;
+---------------------+
| Tables_in_product_2 |
+---------------------+
| t_user_1 |
| t_user_3 |
+---------------------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM t_user_1;
+---------+----------+--------+
| user_id | order_id | status |
+---------+----------+--------+
| 1 | 1 | active |
+---------+----------+--------+
1 row in set (0.00 sec)
mysql> SELECT * FROM t_user_3;
+---------+----------+--------+
| user_id | order_id | status |
+---------+----------+--------+
| 3 | 3 | active |
+---------+----------+--------+
1 row in set (0.00 sec)
- 修改业务 url
将 url 地址变更为 Proxy 的地址,应用程序将访问目标端环境。
- 提交迁移作业
完成迁移作业。
mysql> COMMIT MIGRATION 'j010171e761478594bdab280c55014650e5f6';
Query OK, 0 rows affected (0.57 sec)
FAQ #
- 单表到分片表,是否可能存在分片键重复的问题?
不会发生。
- 索引是否一同迁移过来?如果有自增字段,是否会存在问题?
没有问题。索引会和表结构一同迁移过来。自增字段不影响数据,所有数据会一块迁移,包括自增字段。