背景
见上次写的sysbench压测文章,专栏 - 通过 Sysbench 在低配置低数据基础上分别压测 MySQL 和 TiDB,实际结果 TiDB 出乎我的想象。 | TiDB 社区
我们有个项目,最开始时提供的是一个主从mysql数据库,两台16C64G的主机(还有个预发环境也是mysql主从,2个4C8G主机),后来经过上面压测之后,切换成了三台16C64G的云主机,混合部署的tidb集群,压测记录见上面的文章,但是,虽然混合部署的tidb集群性能相比原来的主从mysql数据库性能要好很多,但是压测效果还是很差,后来对机器上给的号称高性能磁盘的通过fio进行io测试后发现,还是io性能不过关,于是要求另换了3台带ssd的物理机来安装tidb集群。
备注:fio性能测试命令示例
磁盘顺序读
fio --bs=8k --ioengine=libaio --direct=1 --rw=read --numjobs=16 --iodepth=256 --time_based --runtime=60 --group_reporting --size=10G --name=fio-seqr-vdb --filename=/data/fio_seqw
磁盘随机读
fio --bs=8k --ioengine=libaio --direct=1 --rw=randread --numjobs=16 --iodepth=256 --time_based --runtime=60 --group_reporting --size=10G --name=fio-randr-vdb --filename=/data/fio_seqr
磁盘顺序写
fio --bs=8k --ioengine=libaio --direct=1 --rw=write --numjobs=16 --iodepth=256 --time_based --runtime=60 --group_reporting --size=10G --name=fio-seqw-vdb --filename=/data/fio_randr
磁盘随机写
fio --bs=8k --ioengine=libaio --direct=1 --rw=randwrite --numjobs=16 --iodepth=256 --time_based --runtime=60 --group_reporting --size=10G --name=fio-randw-vdb --filename=/data/fio_randw
磁盘随机读写
fio --bs=8k --ioengine=libaio --direct=1 --rw=randrw --rwmixread=70 --numjobs=16 --iodepth=256 --time_based --runtime=60 --group_reporting --size=10G --name=fio-randrw-vdb --filename=/data/fio_randrw
另:如果已安装tiup,可以通过tiup cluster check --enable-disk命令来针对目标磁盘的io进行预检查。
以下是带ssd的物理机部署的集群和云主机部署集群的sysbench压测对比记录
最终导致了两次数据库的迁移,下面记录下两次迁移的执行过程。
迁移过程
1.首次迁移过程(MySQL主从到tidb)
1.1选择迁移方式
由于我们的迁移是从mysql主从到tidb,且数据量较小,选择了通过dm进行迁移。
1.2安装和部署dm
1.2.1安装dm超级简单,通过tiup一句命令即可完成,
tiup install dm dmctl
1.2.2部署dm则只需要先生成一个dm_topology.yaml
global:
user: "tidb"
ssh_port: 22
deploy_dir: "/data/dm-deploy"
data_dir: "/data/dm-data"
server_configs:
master:
log-level: info
worker:
log-level: info
master_servers:
- host: 10.11.141.160
name: master1
ssh_port: 22
port: 8261
config:
log-level: info
worker_servers:
- host: 10.11.141.160
ssh_port: 22
port: 8262
config:
log-level: info
monitoring_servers:
- host: 10.11.141.160
ssh_port: 22
port: 9090
grafana_servers:
- host: 10.11.141.160
port: 3000
alertmanager_servers:
- host: 10.11.141.160
ssh_port: 22
web_port: 9093
然后通过tiup安装即可
tiup dm deploy dm-smk v6.5.5 ./dm_topology.yaml --user tidb -p
1.2.3创建上游数据库source
生成mysql-141.yaml
source-id: "mysql-141"
from:
host: "10.11.141.141"
user: "root"
password: "+ZKZYcFtNc1lwtlRaR6UoEAnq7ffgs1EyIiQcCzOqhcUuYkfNKI+Lhu80yU="
port: 3306
注:数据库密码可以通过tiup dmctl --encrypt "您的密码"来生成,避免明文保存
执行命令创建source,tiup dmctl --master-addr=10.11.141.160:8261 operate-source create mysql-141.yaml
1.2.4创建同步任务
生成smkdm-task.yaml
name: smkdm
task-mode: all
target-database:
host: "10.12.141.117"
port: 3806
user: "root"
password: "X/ZGqrGswhoadLgZAMyGKEBz7mtamUz9TwgrczXGOZzTT6U="
mysql-instances:
- source-id: "mysql-141"
block-allow-list: "ba-rule1"
block-allow-list:
ba-rule1:
do-dbs: ["citizencard-biz","citizencarddb","citizencard-seata"]
执行命令创建同步任务,tiup dmctl --master-addr 10.11.141.160:8261 start-task smkdm-task.yaml
查询任务状态,tiup dmctl --master-addr 10.11.141.160:8261 query-status smkdm
1.2.5 确定同步已实时同步,可以通过sync_diff_inspector进行数据比对
生成sync.toml
# Diff Configuration.
######################### Global config #########################
# 检查数据的线程数量,上下游数据库的连接数会略大于该值
check-thread-count = 12
# 如果开启,若表存在不一致,则输出用于修复的 SQL 语句。
export-fix-sql = true
# 只对比表结构而不对比数据
check-struct-only = false
# 如果开启,会跳过校验上游或下游不存在的表。
skip-non-existing-table = true
######################### Datasource config #########################
[data-sources]
[data-sources.mysql1] # mysql1 是该数据库实例唯一标识的自定义 id,用于下面 task.source-instances/task.target-instance 中
host = "10.11.141.141"
port = 3306
user = "root"
password = "111222333" # 设置连接上游数据库的密码,可为明文或 Base64 编码。
#(可选)使用映射规则来匹配上游多个分表,其中 rule1 和 rule2 在下面 Routes 配置栏中定义
#route-rules = ["rule1", "rule2"]
#route-rules = ["rule2"]
[data-sources.tidb0]
host = "10.12.141.117"
port = 3806
user = "root"
password = "222333444" # 设置连接下游数据库的密码,可为明文或 Base64 编码。
#(可选)使用 TLS 连接 TiDB
# security.ca-path = ".../ca.crt"
# security.cert-path = ".../cert.crt"
# security.key-path = ".../key.crt"
#(可选)使用 TiDB 的 snapshot 功能,如果开启的话会使用历史数据进行对比
# snapshot = "386902609362944000"
# 当 snapshot 设置为 "auto" 时,使用 TiCDC 在上下游的同步时间点,具体参考 <https://github.com/pingcap/tidb-tools/issues/663>
# snapshot = "auto"
########################### Routes ###########################
# 如果需要对比大量的不同库名或者表名的表的数据,或者用于校验上游多个分表与下游总表的数据,可以通过 table-rule 来设置映射关系
# 可以只配置 schema 或者 table 的映射关系,也可以都配置
[routes]
[routes.rule1] # rule1 是该配置的唯一标识的自定义 id,用于上面 data-sources.route-rules 中
schema-pattern = "citizencard*" # 匹配数据源的库名,支持通配符 "*" 和 "?"
table-pattern = "*" # 匹配数据源的表名,支持通配符 "*" 和 "?"
target-schema = "citizencard*" # 目标库名
target-table = "*" # 目标表名
[routes.rule2]
schema-pattern = "citizencard*" # 匹配数据源的库名,支持通配符 "*" 和 "?"
table-pattern = "*" # 匹配数据源的表名,支持通配符 "*" 和 "?"
target-schema = "citizencard*" # 目标库名
target-table = "*" # 目标表名
######################### Task config #########################
# 配置需要对比的*目标数据库*中的表
[task]
# output-dir 会保存如下信息
# 1 sql:检查出错误后生成的修复 SQL 文件,并且一个 chunk 对应一个文件
# 2 log:sync-diff.log 保存日志信息
# 3 summary:summary.txt 保存总结
# 4 checkpoint:a dir 保存断点续传信息
output-dir = "./output"
# 上游数据库,内容是 data-sources 声明的唯一标识 id
source-instances = ["mysql1"]
# 下游数据库,内容是 data-sources 声明的唯一标识 id
target-instance = "tidb0"
# 需要比对的下游数据库的表,每个表需要包含数据库名和表名,两者由 `.` 隔开
# 使用 ? 来匹配任意一个字符;使用 * 来匹配任意;详细匹配规则参考 golang regexp pkg: https://github.com/google/re2/wiki/Syntax
target-check-tables = ["citizencard*.*"]
#(可选)对部分表的额外配置,其中 config1 在下面 Table config 配置栏中定义
target-configs = ["config1"]
######################### Table config #########################
# 对部分表进行特殊的配置,配置的表必须包含在 task.target-check-tables 中
[table-configs.config1] # config1 是该配置的唯一标识自定义 id,用于上面 task.target-configs 中
# 目标表名称,可以使用正则来匹配多个表,但不允许存在一个表同时被多个特殊配置匹配。
target-tables = [ "`citizencard-biz`.cc_request_result_log"]
#(可选)指定检查的数据的范围,需要符合 sql 中 where 条件的语法
range = "id<2"
#(可选)指定用于划分 chunk 的列,如果不配置该项,sync-diff-inspector 会选取一些合适的列(主键/唯一键/索引)
#index-fields = ["col1","col2"]
#(可选)忽略某些列的检查,例如 sync-diff-inspector 目前还不支持的一些类型(json,bit,blob 等),
# 或者是浮点类型数据在 TiDB 和 MySQL 中的表现可能存在差异,可以使用 ignore-columns 忽略检查这些列
ignore-columns = ["",""]
#(可选)指定划分该表的 chunk 的大小,若不指定可以删去或者将其配置为 0。
#chunk-size = 0
#(可选)指定该表的 collation,若不指定可以删去或者将其配置为空字符串。
#collation = ""
./sync_diff_inspector --config=./sync.toml 执行比对
注:sync_diff_inspector可通过如下连接下载
https://download.pingcap.org/tidb-community-toolkit-v6.5.8-linux-amd64.tar.gz
查看比对结果无异常后
1.2.6正式切换
切换数据库需要停止业务,选择一个晚上,提前报备,切换数据库
切换步骤
- 首先停止同步tiup dmctl --master-addr 10.11.141.160:8261 pause-task smkdm
- 修改生成应用对应的数据库连接
- 重启应用
- 验证业务正常,完成切换
第二次切换过程(tidb到tidb)
1.1选择迁移方式
由于我们的迁移是从tidb到tidb,也很简单,选择通过br+ticdc进行迁移。
1.2部署br并迁移全量数据
1.2.1准备外部存储,这里我们用minio来当外部存储
wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
# 配置访问 minio 的 access-key access-screct-id
export HOST_IP='172.16.6.122' # 替换为实际上游集群 ip
export MINIO_ROOT_USER='minio'
export MINIO_ROOT_PASSWORD='miniostorage'
# 创建数据目录, 其中 backup 为 bucket 的名称
mkdir -p data/backup
# 启动 minio, 暴露端口在 6060
./minio server ./data --address :6060 &
对应s3地址为:s3://backup?access-key=minio&secret-access-key=miniostorage&endpoint=http://10.11.142.246:6060&force-path-style=true
1.2.2上游关闭gc
SET GLOBAL tidb_gc_enable=FALSE;
1.2.3上游通过backup备份数据
BACKUP DATABASE * TO 's3://backup?access-key=minio&secret-access-key=miniostorage&endpoint=http://10.11.142.246:6060&force-path-style=true' RATE_LIMIT = 120 MB/SECOND;
记录备份完成时的checkpoint
Destination | Size | BackupTS | Queue Time | Execution Time
s3://backup 1940403955 447850504815116289 2024-02-20 15:28:18 2024-02-20 15:28:18
1.2.4下游通过restore恢复数据
RESTORE DATABASE * FROM 's3://backup?access-key=minio&secret-access-key=miniostorage&endpoint=http://10.11.142.246:6060&force-path-style=true';
| Destination | Size | BackupTS | Queue Time | Execution Time |
s3://backup 1940403955 447850504815116289 447850554199638017 2024-02-20 15:31:24 2024-02-20 15:31:24
1.2.5通过sync-diff-inspector校验数据
类似第一迁移,唯一的区别是需要指定上游的snapshot
snapshot = "447850504815116289" # 配置为实际的备份时间点
1.3部署ticdc同步增量数据
1.3.1部署ticdc超级简单,直接生成scale-out.yml
cdc_servers:
- host: 10.11.141.160
gc-ttl: 86400
data_dir: "/data/cdc-data"
通过tiup一句scale-out命令即可完成,注意这里还是在上游部署的ticdc
tiup cluster scale-out tidb-smk scale-out.yml -p
1.3.2创建同步任务
tiup cdc cli changefeed create --server=http://10.11.141.160:8300 --sink-uri="mysql://root:NzRiKjE1dzJwRF5aLVIrc0Uw@10.11.142.247:4000" --changefeed-id="upstream-to-downstream" --start-ts="447850504815116289"
1.3.3查看同步状态
tiup cdc cli changefeed list --server=http://10.11.141.160:8300
1.3.4开启上游gc
SET GLOBAL tidb_gc_enable=TRUE;
1.3.5正式切换
切换数据库需要停止业务,选择一个晚上,提前报备,切换数据库
切换步骤
- 首先停止业务
- 停止cdc同步
- 修改应用连接数据库配置并重启应用
- 验证业务正常,完成切换
备注:停止cdc同步过程
检查cdc同步时间点--确定晚于停止应用时间
tiup cdc cli changefeed list --server=http://10.11.141.160:8300
# 停止旧集群到新集群的 changefeed
tiup cdc cli changefeed pause -c "upstream-to-downstream" --server=http://10.11.141.160:8300
# 查看 changefeed 状态
tiup cdc cli changefeed list
总结
tidb的官方文档已经非常详细,基本按照文档进行迁移不会出啥问题。
另外还是建议大家在创建数据库之前就对机器和数据库的配置进行测试和确定,以免跟我一样反复的进行数据库的迁移和切换。