0
1
0
0
专栏/.../

TiCDC 实践:TiDB 到 TiDB 增量数据迁移

 Hacker_小峰  发表于  2022-10-14
原创迁移

背景

因降本等原因,需要将流量较小的 TiDB 集群下线,将数据合并到其他 TiDB 集群。

上游 TiDB 集群版本:5.4.0

下游 TiDB 集群版本:5.4.2

此次合并集群用的工具有:

dumpling 导出 + loader 导入 + TiCDC 增量数据实时同步

TiCDC 数据同步原理可参考TiCDC 架构和数据同步链路解析

第 1 步:搭建环境

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.yaml

2、查看集群拓扑,确认上下游集群 TiCDC 节点都已经扩容完成。

$ tiup cluster display prod-tidb-004
Cluster 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
......

第 2 步:迁移全量数据

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:14

3、恢复数据

使用 Loader 将 Dumpling 导出的上游全量数据导入到下游 TiDB 实例:

# loader 可以断点续传真是太棒了!
#遇到上下游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/

这里也可以采用 TiDB Lightning 工具做导入(TiDB v5.3.0 及以上可使用),为避免影响下游可使用 TiDB-backend 模式(配置文件中设置 backend = "tidb")。

第 3 步:迁移增量数据

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

【创建同步任务】:

$ tiup ctl:v5.4.0 cdc changefeed create --pd=http://10.1.xx.xx:2379 --sink-uri="mysql://dba:passwd@10.1.xx.xx:4000/?worker-count=16&max-txn-row=5000&time-zone=SYSTEM" --changefeed-id="task-migrate-to-prod004" --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 的配置,可以参考官网【同步任务配置文件】

【查看所有任务】:

$ tiup ctl:v5.4.0 cdc changefeed list --pd=http://10.1.xx.xx:2379
Starting 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
    }
  }
]

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-prod004
Starting 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-prod004

4、校验同步情况

  • 查看上下游数据内容是否一致;
  • 测试过滤是否生效:上游建表,测试表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');

#查看数据是否同步到下游
select * from db1.zlz001;#本次同步的库,应查到数据
select * from zlz.zlz002;#非本次TiCDC同步的库,下游应查不到数据

#删表,查看数据是否同步到下游
drop table if exists db1.zlz001;
drop table if exists zlz.zlz002;

#清理测试库
drop database zlz;

这里就不写详细过程了。

第 4 步:平滑切换业务

通过 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、将写业务迁移到下游集群

更新库对应的数据源配置为下游新集群。

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

其他

需要关注上下游集群时区是否一致

time_zone 的默认值是 System 。

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)

修改时区:

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,比如:

 jdbc:mysql://10.1.1.1:4002/dbname?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useServerPrepStmts=true&cachePrepStmts=true&allowMultiQueries=true&useConfigs=maxPerformance&useSSL=false&serverTimezone=Asia/Shanghai

参考文档

https://docs.pingcap.com/zh/tidb/stable/migrate-from-tidb-to-tidb

https://asktug.com/t/topic/813124

0
1
0
0

版权声明:本文为 TiDB 社区用户原创文章,遵循 CC BY-NC-SA 4.0 版权协议,转载请附上原文出处链接和本声明。

评论
暂无评论