黄东旭解析 TiDB 的核心优势
483
2024-02-24
因降本的原因,需要将流量较小的 TiDB 集群下线,并将其数据合并到新的 TiDB 集群。
schemaversion上游 TiDB 集群v5.4.0下游 TiDB 集群v5.4.3此次合并集群用的工具有:
dumpling 导出 + loader 导入 + TiCDC 增量数据实时同步;
TiCDC 数据同步原理可参考TiCDC 架构和数据同步链路解析 。
1、部署上下游 TiDB 集群,分别扩容 TiCDC 节点。
编写 vim scale-out-ticdc.yaml 文件:
cdc_servers: - host: 10.1.1.1 gc-ttl: 86400 data_dir: /data04/deploy/install/data/cdc-8300 - host: 10.1.1.2 gc-ttl: 86400 data_dir: /data04/deploy/install/data/cdc-8300运行扩容命令:
tiup cluster scale-out prod-tidb-004 /home/tidb/prod-tidb-004/scale-out-ticdc.yaml2、查看集群拓扑,确认上下游集群 TiCDC 节点都已经扩容完成。
tiup cluster display prod-tidb-004Cluster name: prod-tidb-004 Cluster version: v5.4.2 ...... 10.1.1.1:8300 cdc 10.1.1.1 8300 linux/x86_64 Up /data04/deploy/install/data/cdc-8300 /data/tidb-deploy/cdc-8300 10.1.1.2:8300 cdc 10.1.1.2 8300 linux/x86_64 Up /data04/deploy/install/data/cdc-8300 /data/tidb-deploy/cdc-8300 ......1、关闭 GC。
SELECT @@global.tidb_gc_enable; SET GLOBAL tidb_gc_enable=false; SELECT @@global.tidb_gc_enable;2、备份数据。
使用 Dumpling 工具导出上游集群多个库的全量数据。
cd /data01/tidb-toolkit-v5.2.2-linux-amd64/bin/ ./dumpling -u dba -p passwd -h 10.1.1.xx -P 4000 -F 64MiB -t 4 -B db1,db2,db3,db4 --params "tidb_distsql_scan_concurrency=5,tidb_mem_quota_query=8589934592" -o /data01/tidb_backup/migrate_to_prod004_4db/2.1、导出完毕后,查看备份文件,确认多个库均已导出完成。
2.2、查看备份的点位, 执行如下命令查看导出数据的元信息,metadata 文件中的 Pos 就是导出快照的 TSO,将其记录为 BackupTS:
cat metadata Started dump at: 2022-10-12 17:25:15 SHOW MASTER STATUS: Log: tidb-binlog Pos: 436618321009573893 GTID: Finished dump at: 2022-10-12 17:35:143、恢复数据。
使用 Loader 将 Dumpling 导出的上游全量数据导入到下游 TiDB 实例:
cd /data01/tidb-enterprise-tools-nightly-linux-amd64/bin ./loader -u dba -p passwd -h 10.1.1.xx -P 4002 -t 2 -d /data01/tidb_backup/migrate_to_prod004_4db/loader可以断点续传真是太棒了! 遇到上下游TiDB版本不一致导致表结构导入有报错时,方便统一表结构后再次导入下游。
这里也可以采用 TiDB Lightning 工具做导入(TiDB v5.3.0 及以上可使用),为避免影响下游可使用 TiDB-backend 模式(配置文件中设置 backend = "tidb")。
1、创建 CDC 同步任务。
【编写配置文件】:
cd /home/tidb/ticdc vim migrate_to_prod004_ticdc_config.toml#cat migrate_to_prod004_4db_ticdc_config.toml # 指定配置文件中涉及的库名、表名是否为大小写敏感 # 该配置会同时影响 filter 和 sink 相关配置,默认为 true case-sensitive = true # 是否输出 old value,从 v4.0.5 开始支持,从 v5.0 开始默认为 true enable-old-value = true [filter] # 过滤器规则 # 过滤规则语法:https://docs.pingcap.com/zh/tidb/stable/table-filter#表库过滤语法 rules = [db1.*, db2.*, db3.*, db4.*] [mounter] # mounter 线程数,用于解码 TiKV 输出的数据 worker-num = 8【创建任务】:
--sort-engine="unified" --start-ts=436612662618488841 --config /home/tidb/ticdc/migrate_to_prod004_ticdc_config.toml以上命令中:
--pd:实际的上游集群的地址
--sink-uri:同步任务下游的地址
--changefeed-id:同步任务的 ID,格式需要符合正则表达式 ^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$
--start-ts:TiCDC 同步的起点,需要设置为实际的备份时间点,也就是第 2 步:迁移全量数据中 “备份数据” 提到的 BackupTS
更多关于 changefeed 的配置,可以参考官网【同步任务配置文件】。
【查看 TiCDC 同步任务的状态】:
$ tiup ctl:v5.4.0 cdc changefeed list --pd=http://10.1.xx.xx:2379Starting component `ctl`: /home/tidb/.tiup/components/ctl/v5.4.0/ctl cdc changefeed list --pd=http://10.1.xx.xx:2379 [ { "id": "task-migrate-to-prod004", "summary": { "state": "normal", "tso": 436641144642469889, "checkpoint": "2022-10-13 17:36:20.527", "error": null } } ]checkpoint:==即为 TiCDC 已经将该时间点前的数据同步到了下游==。
state 为该同步任务的状态:
normal:正常同步。
stopped:停止同步(手动暂停或出错)。
removed:已删除任务。
2、上游重新开启 GC。
SELECT @@global.tidb_gc_enable; SET GLOBAL tidb_gc_enable=TRUE; SELECT @@global.tidb_gc_enable;3、查看 TiCDC 任务状态
【查看指定的任务】:
tiup ctl:v5.4.0 cdc changefeed query -s --pd=http:10.1.xx.xx:2379 --changefeed-id=task-migrate-to-prod004【查看任务详细信息】:
tiup ctl:v5.4.0 cdc changefeed query --pd=http://10.1.xx.xx:2379 -c task-migrate-to-prod004Starting component `ctl`: /home/tidb/.tiup/components/ctl/v5.4.0/ctl cdc changefeed query --pd=http://10.1.xx.xx:2379 -c task-migrate-to-prod004 { "info": { "sink-uri": "mysql://dba:passwd@10.1.xx.xx:4002/", "opts": { "_changefeed_id": "sink-verify" }, "create-time": "2022-10-13T16:28:29.526804276+08:00", "start-ts": 436639195916664835, "target-ts": 0, "admin-job-type": 0, "sort-engine": "unified", "sort-dir": "", "config": { "case-sensitive": true, "enable-old-value": true, "force-replicate": false, "check-gc-safe-point": true, "filter": { "rules": [ "db1.*", "db2.*", "db3.*", "db4.*" ], "ignore-txn-start-ts": null }, "mounter": { "worker-num": 8 }, "sink": { "dispatchers": null, "protocol": "", "column-selectors": null }, "cyclic-replication": { "enable": false, "replica-id": 0, "filter-replica-ids": null, "id-buckets": 0, "sync-ddl": false }, "scheduler": { "type": "table-number", "polling-time": -1 }, "consistent": { "level": "none", "max-log-size": 64, "flush-interval": 1000, "storage": "" } }, "state": "normal", "error": null, "sync-point-enabled": false, "sync-point-interval": 600000000000, "creator-version": "v5.4.0" }, "status": { "resolved-ts": 436641687359455233, "checkpoint-ts": 436641687044882437, "admin-job-type": 0 }, "count": 0, "task-status": [ { "capture-id": "3786de8d-b1e4-40f8-927c-88e2e56665f5", "status": { "tables": { "311": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "333": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "346": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "348": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "363": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "366": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "423": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "427": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "429": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "431": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "446": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "448": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "450": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "456": { "start-ts": 436640265844293633, "mark-table-id": 0 } }, "operation": {}, "admin-job-type": 0 } }, { "capture-id": "5df19b4c-e31d-4f81-a757-95551b1cd3c2", "status": { "tables": { "335": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "350": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "354": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "356": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "373": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "383": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "421": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "425": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "433": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "435": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "437": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "444": { "start-ts": 436640265844293633, "mark-table-id": 0 }, "458": { "start-ts": 436640265844293633, "mark-table-id": 0 } }, "operation": {}, "admin-job-type": 0 } } ] }【暂停任务】:
tiup ctl:v5.4.0 cdc changefeed pause --pd=http://10.1.xx.xx:23799 --changefeed-id=task-migrate-to-prod004 #然后确认"state": "stopped" tiup ctl:v5.4.0 cdc changefeed query --pd=http://10.1.xx.xx:2379 --changefeed-id=task-migrate-to-prod004【恢复任务】:
tiup ctl:v5.4.0 cdc changefeed resume --pd=http://10.1.xx.xx:23799 --changefeed-id=task-migrate-to-prod0044、校验同步情况
查看上下游数据内容是否一致;
测试过滤是否生效:上游建表,测试表DML/DDL 是否同步到下游。
#上游建表 use db1;#本次迁移的多库之一 CREATE TABLE `zlz001` ( `id` bigint(20) NOT NULL auto_random COMMENT 主键, `params` varchar(100) NOT NULL COMMENT 值, `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, `updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 修改时间, PRIMARY KEY (`id`) /*T![clustered_index] NONCLUSTERED */ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT=测试表; create database zlz;#非本次迁移的库 use zlz; CREATE TABLE `zlz002` ( `id` bigint(20) unsigned NOT NULL auto_random COMMENT 主键ID, `content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT COMMENT 短信内容, `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, `updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */ ) ENGINE=InnoDB COMMENT=测试表; insert into db1.zlz001(params) values(params),(paramsparams),(paramsparamsparamsparamsparams); insert into zlz.zlz002(content) values(heeha); #查看数据是否同步到下游 #有 timestamp 字段,需关注上下游集群的时区是否一致 select * from db1.zlz001;#本次同步的库,应查到数据 select * from zlz.zlz002;#非本次TiCDC同步的库,下游应查不到数据 #删表,查看数据是否同步到下游 drop table if exists db1.zlz001; drop table if exists zlz.zlz002; #清理测试库 drop database zlz;这里就不写详细过程了。
通过 TiCDC 创建上下游的同步链路后,原集群的写入数据会以非常低的延迟同步到新集群,此时可以逐步将读流量迁移到新集群了。观察一段时间,如果新集群表现稳定,就可以将写流量接入新集群,步骤如下:
1、停止上游集群的写业务。
2、确认上游数据已全部同步到下游后,停止上游到下游集群的 changefeed。
停止旧集群到新集群的 changefeed :
tiup ctl:v5.4.0 cdc changefeed pause --pd=http://10.1.xx.xx:2379 --changefeed-id=task-migrate-to-prod004查看 changefeed 状态:
tiup ctl:v5.4.0 cdc changefeed query --pd=http://10.1.xx.xx:2379 --changefeed-id=task-migrate-to-prod004[ { "id": "task-migrate-to-prod004", "summary": { "state": "stopped",# 需要确认这里的状态为 stopped "tso": 436640265844293633, "checkpoint": "2022-10-13 17:40:28.178",# 确认这里的时间晚于停写的时间 "error": null } } ]3、将写业务迁移到下游集群
3.1 写业务更新数据源IP
3.2 更新对应的数据源配置
4、观察一段时间后,等新集群表现稳定,便可以弃用原集群
5、删除 TiCDC 同步任务
【删除同步任务】:
tiup ctl:v5.4.0 cdc changefeed remove --pd=http://10.1.xx.xx:2379 --changefeed-id=task-zlz【查看所有任务】:
tiup ctl:v5.4.0 cdc changefeed list --pd=http://10.1.xx.xx:2379在测试上下游集群时,发现一个诡异的时区问题:
在执行 select now(); 时,下游集群的时间比系统时间少了 8 小时。
在以往 v5.0 版本的 TiDB 集群,是可以在集群配置文件中增加 timezone 参数来设置时区的。比如:
server_configs: tidb: timezone:Asia/Ahanghai但是,到了 v5.4.0 的版本,配置文件中不支持这个timezone 参数了。 所以,新集群安装好后,如果不通过系统变量设置一遍,就会出现这样时区默认是UTC 的问题。为什么会是 UTC 可以参考这篇 记一次 TiDB 时区设置异常问题排查 。(测试了下,在 v6.1.2 中没这个问题了。)
所以,在迁移 TiDB 集群时,需要关注上下游集群时区是否一致。
查看新集群时区设置:
mysql> SELECT @@global.time_zone, @@session.time_zone, @@global.system_time_zone; +--------------------+---------------------+---------------------------+ | @@global.time_zone | @@session.time_zone | @@global.system_time_zone | +--------------------+---------------------+---------------------------+ | SYSTEM | SYSTEM | UTC | +--------------------+---------------------+---------------------------+ 1 row in set (0.01 sec)发现 system_time_zone 是 UTC 。而我们是东八区,需要+8:00 。如何修改时区呢?
更新 mysql.tidb 中 system_tz 为正确的时区,并重启 tidb-server 。
mysql> update mysql.tidb set VARIABLE_VALUE=Asia/Shanghai where VARIABLE_NAME=system_tz; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from mysql.tidb where variable_name=system_tz; +---------------+----------------+------------------------------+ | VARIABLE_NAME | VARIABLE_VALUE | COMMENT | +---------------+----------------+------------------------------+ | system_tz | Asia/Shanghai | TiDB Global System Timezone. | +---------------+----------------+------------------------------+ 1 row in set (0.00 sec)根据官方文档修改时区,设置 time_zone 变量,问题也可以得到解决。如果有需要,可以把 system_tz 也修改了,因为tidb-server 不会自行进行调整。
【修改时区】:
set global time_zone=Asia/Shanghai;mysql> SELECT @@global.time_zone, @@session.time_zone, @@global.system_time_zone; +--------------------+---------------------+---------------------------+ | @@global.time_zone | @@session.time_zone | @@global.system_time_zone | +--------------------+---------------------+---------------------------+ | Asia/Shanghai | Asia/Shanghai | UTC | +--------------------+---------------------+---------------------------+ 1 row in set (0.00 sec)也可以在 JDBC 链接中指定时区 serverTimezone=Asia/Shanghai。比如:
本次迁移目的是做 TiDB 集群的合并(顺便升级TiDB版本), 使用到的工具有Dumpling +Loader +TiCDC 。
TiCDC 是一款通过拉取 TiKV 变更日志实现的,用于上游是 TiDB 集群的增量数据同步工具。 所以,这个实践手册也适用于从 TiDB 回迁一些小库回 MySQL。
TiCDC 的输入:TiDB 集群
TiCDC 的输出:TiDB 集群、MySQL、Kafka、Apache Pulsar、Confluent
适用 TiDB 版本:v4.0.6 及以上
PS:想到 TiDB 集群的迁移,第一反应是头疼。但是有工具,瞬间看到了光亮。虽然第一遍部署因为不熟有点畏惧心理,但是任务部署好,不免多次感叹 TiCDC 真好用啊!
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。