前提说明
优先明确一点:数据迁移必须使用DistSQL操作。
ShardingSphere提供的数据迁移方案为:使用全新的数据库集群作为迁移目标。因此,需要冗余的服务器资源支持,并且在数据迁移过程中,所有的数据都会发生移动。
实战内容:将192.168.49.110:3306/user中的t_user表,迁移到192.168.49.119:3306/user中并且进行数据分片。将源端t_user表的数据以user_id为分片键,分布在10张表中。
数据迁移阶段划分
-
准备阶段;
-
存量数据迁移阶段;
-
增量数据同步阶段,提供数据一致性校验;
-
流量切换阶段;
从存量迁移到增量迁移阶段,Proxy组件会自动帮助我们完成过渡。在增量数据迁移阶段,Proxy会不断读取源端写入的最新数据,保持目标端数据和源端数据的基本一致。而数据想要从基本一致过渡到完全一致,需要源端将服务暂时改为只读,之后proxy继续读取源端信息,进而使数据完全同步(有内置的校验规则)。之后,完成线上流量的切换。
1.迁移前准备
-
校验MySQL账号的权限
-
源端账号是否开启binlog、是否拥有replication权限和查询权限。
-
目标端账号是否拥有赋予增删改查、创建索引权限。【不能是ALL PRIVILEGE,要给具体的权限,不然会报错】
-
-
以集群模式启动proxy,并配置Proxy的分片规则
a. 账号权限检查
-- 检查源端是否开启binlog,以及源端账户是否具有replication和Select权限
show variables like 'log_bin'; -- 需要是ON
show variables like 'binlog_format'; -- 需要是ROW
show variables like 'binlog_row_image'; -- 需要是FULL
SHOW GRANTS FOR 'chatbot';
-- 缺少那个权限执行下面那一条命令
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON `chatbot`.* TO 'chatbot'@'%';
GRANT SELECT ON `chatbot`.* TO 'chatbot'@'%';
-- 检查目标端账户的权限,需要DML和索引权限
SHOW GRANTS FOR 'chatbot_shard'@'%';
GRANT CREATE, DROP, INDEX, SELECT, INSERT, UPDATE, DELETE ON 'chatbot_shard'.* TO 'chatbot_shard'@'%';
b. Proxy 配置
启动Proxy
采用zk集群模式进行数据迁移和分库分表。
对应的Dockerfile、启动命令和global.yaml配置如下:
想要详细了解可以看以下文章:
1. 定制满足业务需求ShardingSphere-Proxy镜像
2. 解决Docker环境变量的配置的通用方法
# Dockerfile文件内容
FROM apache/shardingsphere-proxy:5.5.1
RUN mkdir -p /opt/shardingsphere-proxy/ext-lib/
RUN wget -P /opt/shardingsphere-proxy/ext-lib/
https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.11/mysql-connector-java-8.0.11.jar
#制作镜像
docker build -t sharding:1.0 .
# Docker启动命令
docker run -d \
--name sharding1 \
-p 3309:3307 \
-e JAVA_MEM_COMMON_OPTS='-Xms256m -Xmx400m -Xss1m' \
-v /root/sharding/conf/:/opt/shardingsphere-proxy/conf \
sharding:1.0
# global.yaml文件内容
mode:
type: Cluster
repository:
type: ZooKeeper
props:
namespace: governance_db
server-lists: zk0:2181,zk1:2181,zk2:2181
retryIntervalMilliseconds: 500
timeToLiveSeconds: 60
maxRetries: 3
operationTimeoutMilliseconds: 500
authority:
users:
- user: root@%
password: root
privilege:
type: ALL_PERMITTED
props:
sql-show: true
数据分片规则配置
连接proxy,进行分片规则的配置。这时候,我们只需要关注目标表的分片规则就可以了,不需要关注旧表的情况。
-- 在proxy中执行
create database sharding_user;
use chatbot_shard;
REGISTER STORAGE UNIT server_target (
URL="jdbc:mysql://192.168.49.110:3306/user?useUnicode=true&characterEncoding=utf8",
USER="root",
PASSWORD="123456",
PROPERTIES("minPoolSize"="1","maximumPoolSize"=20,"idleTimeout"="6000")
);
CREATE SHARDING TABLE t_user(
STORAGE_UNITS(server_target),
SHARDING_COLUMN=user_id,
TYPE(NAME="mod",PROPERTIES("sharding-count"="10"))
);
-- 比对,我们的配置是否和预期一致。
EXPORT DATABASE CONFIGURATION;
-- 执行对应的建表语句
CREATE TABLE `user`(
id bigint primary key auto_increment,
user_id bigint not null,
name varchar(10),
);
-- 自此,我们的分片规则已经配置完成,并且sharding也帮助我们在节点中创建了对应的表。
2. 数据迁移
--1.按需更改迁移配置,主要是从旧表中读取线程的数量和向新表中写入线程的数量。
-- 不要因为数据迁移对线上业务造成过大的读取压力。
SHOW MIGRATION RULE;
ALTER MIGRATION RULE (
READ(
WORKER_THREAD=5,
BATCH_SIZE=500,
SHARDING_SIZE=10000,
RATE_LIMITER (TYPE(NAME='QPS',PROPERTIES('qps'='200')))
),
WRITE(
WORKER_THREAD=5,
BATCH_SIZE=500,
RATE_LIMITER (TYPE(NAME='TPS',PROPERTIES('tps'='200')))
),
STREAM_CHANNEL (TYPE(NAME='MEMORY',PROPERTIES('block-queue-size'='200')))
);
--2.添加迁移的数据源【源端】
REGISTER MIGRATION SOURCE STORAGE UNIT origin (
URL="jdbc:mysql://192.168.49.110:3306/user?useUnicode=true&characterEncoding=utf8",
USER="wang",
PASSWORD="123456",
PROPERTIES("minPoolSize"="1","maxPoolSize"="20","idleTimeout"="60000")
);
--3.执行迁移命令,可以并发
MIGRATE TABLE origin.t_user INTO t_user;
--4.查看迁移进度
SHOW MIGRATION LIST;
SHOW MIGRATION STATUS 'j0102p00002333dcb3d9db141cef14bed6fbf1ab54';
-- SHOW MIGRATION LIST重要数据解读
-- 迁移作业的状态有三种:准备、存量迁移、增量迁移,只有在增量迁移阶段,才能够使用校验算法。
id |tables |job_item_count |active |create_time |stop_time|
------------------------------------------+----------------------+--------------+------+---------
当前迁移任务的id |源端.源表 |迁移job的分片数 |是否活跃 |迁移任务开始时间 |迁移任务停止时间
j01021212324 |origin.conversation |1 |true |2024-11-19 03:20:21 |
-- SHOW MIGRATION STATUS 重要数据解读
item|data_source|tables |status |active |processed_records_count|inventory_finished_percentage|incremental_idle_seconds|error_message|
----+-----------+---------------+------------------------+------+-----------------------+-----------------------------+------------------------+-------------+
编号 |数据源 |源端.源表 |迁移作业状态 |是否活跃 |处理数据行数 |迁移作业完成度 |增量闲置时间 | 错误信息提示 |
0 |origin |origin.question|EXECUTE_INCREMENTAL_TASK|true |37450 |100 |2 | |
--5.验证迁移前后数据的一致性
--先执行算法,再查看进度。MySQL支持的校验算法有CRC32_MATCH||DATA_MATCH
--CRC32_MATCH:循环冗余校验,通过校验码来判断是否存在数据不一致,效率快,但是不支持断点续传,且只支持MySQL
--DATA_MATCH:逐行挨个比对数据,效率稍慢但是支持断点续传和异构数据库,如果有加密数据,需要使用该算法。
CHECK MIGRATION j0102p000041c4912117c302e9facd92f9a74a478c BY TYPE (NAME='DATA_MATCH');
SHOW MIGRATION CHECK STATUS 'j0102p00000211a23d148fe8cc6c42ce4a445ad5b3';
--SHOW MIGRATION CHECK STATUS重要信息解读
tables |result |check_failed_tables|active|inventory_finished_percentage|inventory_remaining_seconds|incremental_idle_seconds|check_begin_time |check_end_time |duration_seconds|algorithm_type|algorithm_props|error_message|
---------------+------+-------------------+------+-----------------------------+---------------------------+------------------------+-----------------------+-----------------------+----------------+--------------+---------------+-------------+
校验表 |校验结果,true通过,false失败,空白运行中 |校验失败的表 |false |进度 |预估完成时间 | |开始时间 |结束时间 |1 |算法类型 | | |
origin.question|true | |false |100 |0 | |2024-11-19 04:04:16.911|2024-11-19 04:04:18.520|1 |DATA_MATCH | | |
--当准备流量切换的时候,采用 COUNT(*) 进行数据校验,防止校验时间过长,影响线上业务。
--使用 COUNT(*) 进行校验,可能造成一定的数据不一致,但是比较快,对线上影响下。
SELECT count(*) FROM user.t_user; --源端执行
SELECT count(*) FROM user.t_user; --proxy中执行
--5.提交迁移作业
COMMIT MIGRATION 'j0102p00000211a23d148fe8cc6c42ce4a445ad5b3';
SROLLBACK MIGRATION 'j0102p00000211a23d148fe8cc6c42ce4a445ad5b3';
数据迁移过程中的注意点
-
如果我们迁移的目标表中已经存在数据,需要把数据清空,再进行数据迁移。
-
迁移任务回滚不仅仅会把目标端迁移的数据删除,而且还会将proxy中的分片规则以及proxy创建在物理节点的真实表删除。