概述
本文介绍 TiDB 基于 TiCDC 的灾备库创建、主库和备库的数据校验、备库的一致性读取、容灾切换演练、灾难下的容灾接管。
本文描述的技术场景适用 TiDB v6.5 及以上版本。
本文建议关注的要点:
- 官网 TiCDC 简介,本文不做赘述
- 通过 BR 备份恢复+TiCDC同步的灾备库搭建过程
- BR 恢复到备库后需重新收集统计信息
- TiCDC 启用 TiCDC 的 Syncpoint 功能 实现主库和备库的在线数据校验
- TiCDC 启用 TiCDC 的 Syncpoint 功能 实现快照一致性读取
- 容灾切换演练的步骤
- TiCDC 配置 redo log 实现灾难场景下备库的数据一致性
容灾库搭建
灾备库的搭建过程可以分为如下步骤:
- 创建灾备集群(本文省略)
- 扩容部署 TiCDC
- 通过 BR 进行备份并恢复到备库
- TiCDC 创建 changefeed 进行数据同步
主库扩容部署TiCDC
考虑到后续进行容灾切换,建议也在灾备库端扩容部署 TiCDC 实例。
建议TiCDC实例个数在2个及以上,以满足高可用能力。
配置 TiCDC 拓扑文件
vim scale-out-ticdc.yaml
cdc_servers:
- host: 172.16.201.137
ssh_port: 22
port: 8300
deploy_dir: "/data1/tidb-deploy/cdc-8300"
data_dir: "/data1/tidb-data/cdc-8300"
log_dir: "/data1/tidb-deploy/cdc-8300/log"
- host: 172.16.201.138
ssh_port: 22
port: 8300
deploy_dir: "/data1/tidb-deploy/cdc-8300"
data_dir: "/data1/tidb-data/cdc-8300"
log_dir: "/data1/tidb-deploy/cdc-8300/log"
- host: 172.16.201.139
ssh_port: 22
port: 8300
deploy_dir: "/data1/tidb-deploy/cdc-8300"
data_dir: "/data1/tidb-data/cdc-8300"
log_dir: "/data1/tidb-deploy/cdc-8300/log"
通过扩容部署TiCDC
tiup cluster scale-out tidb-cluster scale-out-ticdc.yaml -uroot -p
检查部署的 TiDB 集群情况
tiup cluster display tidb-cluster
备库创建 tidb_cdc 库 (Syncpoint使用)
#TiCDC 在创建 Changefeed 前,请确保 TiCDC 的配置项 enable-sync-point 已设置为 true,
#这样才会开启 Syncpoint 功能,在下游保存 ts-map。
#且需要在备库创建 tidb_cdc 库
create database tidb_cdc;
BR 备份并恢复到备库
调大主库 gc_life_time 如24小时(灾备库搭建完成后再调整回来),确保后续 TiCDC changefeed 的发起时间在 tikv_gc_safe_point 之内。
set global tidb_gc_life_time = '24h';
show variables like '%tidb_gc_life_time%';
主库进行 BR 备份
TiDB 集群快照数据是只包含某个物理时间点上集群满足事务一致性的数据。使用 br backup full
可以备份 TiDB 最新的或者指定时间点的快照数据。执行 br backup full --help
可获取该命令的使用帮助。
br backup full --pd "172.16.201.137:2379" \
--backupts '2024-03-01 13:30:00' \
--storage "s3://backup-data/20240301?access-key=${access-key}&secret-access-key=${secret-access-key}" \
--ratelimit 128 \
以上命令中:
--backupts
:快照对应的物理时间点(不指定则备份当前时间)。如果该快照的数据被 GC 了,那么br backup
命令会报错退出;如果你没有指定该参数,那么 BR 会选取备份开始的时间点所对应的快照。--ratelimit
:每个 TiKV 执行备份任务的速度上限(单位 MiB/s)。--log-file
:BR log 写入的目标文件。
备份期间有进度条在终端中显示。当进度条前进到 100% 时,说明备份已完成。
在完成备份后,BR 会将备份数据的 checksum 同集群 admin checksum table 的结果比较,以确保备份数据正确性。
注意:在备份目录s3://backup-data/20240301/ 下有个 checkpoint.meta 文件,文件中有记录 backup-ts ,该 tso 即为全备的快照时间点,TiCDC基于该 tso 进行增量同步。
BR 恢复到备库
BR 支持在一个空集群上执行快照备份恢复,将该集群恢复到快照备份时刻点的集群最新状态。
用例:将 s3 的名为 backup-data
bucket 下的 2024-03-01/
前缀目录中属于 2024-03-01 13:30:00
时刻点的快照数据恢复到目标机群。
br restore full \
--pd "172.16.202.237:2379" \
--storage "s3://backup-data/20240301?access-key=${access-key}&secret-access-key=${secret-access-key}" \
--ratelimit 128 \
--log-file restorefull.log
以上命令中,
--ratelimit
:每个 TiKV 执行恢复任务的速度上限(单位 MiB/s)--log-file
:BR log 写入的目标文件
恢复期间还有进度条会在终端中显示。当进度条前进到 100% 时,说明恢复已完成。
在完成恢复后,BR 为了确保数据安全性,还会校验恢复数据。
BR全量恢复后统计信息收集(可在灾备搭建完成后再操作)
BR 不恢复统计信息,所以在容灾库完成全量恢复后需要进行统计信息收集。
备库设置只读模式
备库建议设置只读模式避免产生脏数据。
对 ticdc 同步用户单独授予RESTRICTED_REPLICA_WRITER_ADMIN 权限。
备库设置只读模式
Set global tidb_restricted_read_only=on;
Set global tidb_super_read_only=on;
show global variables like '%tidb_super_read_only%';
show global variables like '%tidb_restricted_read_only%';
考虑到未来进行容灾切换,主、备库都创建 TiCDC 同步用户,ticdc 用户单独授权
create user 'ticdc'@'%' identified by 'passwd';
GRANT RESTRICTED_REPLICA_WRITER_ADMIN ON *.* TO 'ticdc'@'%';
创建TiCDC同步任务
编辑 changefeed 配置文件(建议开启 Syncpoint 和 redo log)
请确保 TiCDC 的配置项 enable-sync-point
已设置为 true
,且备库端已经创建了 tidb_cdc 库,这样才会开启 Syncpoint 功能,在下游保存 ts-map
。
并建议开启 redo log 配置,提供上游灾难情况下的最终一致性。
vim reptask_changefeed.toml
# 指定配置文件中涉及的库名、表名是否为大小写敏感
# 该配置会同时影响 filter 和 sink 相关配置,默认为 true
case-sensitive = true
# 是否输出 old value,从 v4.0.5 开始支持,从 v5.0 开始默认为 true
enable-old-value = true
force-replicate = true
# 是否开启 Syncpoint 功能,从 v6.3.0 开始支持,该功能默认关闭。
# 从 v6.4.0 开始,使用 Syncpoint 功能需要同步任务拥有下游集群的 SYSTEM_VARIABLES_ADMIN 或者 SUPER 权限。
# 注意:该参数只有当下游为 TiDB 时,且下游TIDB 创建空库 tidb_cdc 才会生效。
enable-sync-point = true
# Syncpoint 功能对齐上下游 snapshot 的时间间隔
# 配置格式为 h m s,例如 "1h30m30s"
# 默认值为 10m,最小值为 30s
# 注意:该参数只有当下游为 TiDB 时,才会生效。
sync-point-interval = "1m"
# Syncpoint 功能在下游表中保存的数据的时长,超过这个时间的数据会被清理
# 配置格式为 h m s,例如 "24h30m30s"
# 默认值为 24h
# 注意:该参数只有当下游为 TiDB 时,才会生效。
sync-point-retention = "24h"
[mounter]
# mounter 解码 KV 数据的线程数,默认值为 16
# worker-num = 16
[filter]
# 过滤器规则
# 过滤规则语法:https://docs.pingcap.com/zh/tidb/stable/table-filter#表库过滤语法
rules = ['*.*']
[mounter]
# mounter 线程数,用于解码 TiKV 输出的数据
worker-num = 16
[consistent]
# eventual consistency:使用 redo log,提供上游灾难情况下的最终一致性。
level = "eventual"
# 单个 redo log 文件大小,单位 MiB,默认值 64,建议该值不超过 128。
max-log-size = 64
# 刷新或上传 redo log 至 S3 的间隔,单位毫秒,默认 1000,建议范围 500-2000。
flush-interval = 2000
# 存储 redo log 的地址
storage = "s3://redo?access-key=minio&secret-access-key=miniostorage&endpoint=http://10.0.1.10:6060&force-path-style=true"
创建并启动任务
注意 --start-ts="" ,指定 changefeed 的开始 TSO。TiCDC 集群将从这个 TSO 开始拉取数据。默认为当前时间。
搭建灾备同步需要指定基于BR备份的tso,即BR备份时 checkpoint.meta 文件中的 backup-ts 。
tiup cdc cli changefeed create \
--server=http://172.16.201.137:8300 \
--sink-uri="mysql://ticdc:passwd@172.16.202.237:4000/" \
--changefeed-id="reptask" \
--config=~/cdc/reptask_changefeed.toml \
--start-ts="" # backup-ts
确认任务状态
经过以上步骤,备库搭建已经完成,可以通过 Grafana 的TiCDC 面板进行监控分析。
也可以通过 changefeed query 命令查询任务状态:
tiup cdc cli changefeed query -s --server=http://172.16.201.137:8300 --changefeed-id=reptask
主备在线数据校验和备库一致性快照读
开启了Syncpoint的情况下可以实现主备在线数据校验和备库一致性快照读。
Syncpoint的应用--在线主备数据校验
当你使用 TiCDC 搭建 TiDB 的主从集群时,可能会需要在不停止同步的情况下对上下游进行一致性的快照读或者对数据进行一致性验证。在普通的同步模式中,TiCDC 只提供数据的最终一致性的保证,而无法确保在同步的过程中数据的一致性。因此,对动态变更的数据进行一致性读非常困难,为了满足这一需求,TiCDC 提供了 Syncpoint 功能。
Syncpoint 通过利用 TiDB 提供的 snapshot 特性,让 TiCDC 在同步过程中维护了一个上下游具有一致性 snapshot 的 ts-map
。把校验动态数据的一致性问题转化为了校验静态 snapshot 数据的一致性问题,达到了接近数据一致性实时校验的效果。
主备模式下的数据校验作为一个可选的运维作业(TiCDC 的数据同步本身比较健壮,保证幂等性),可以进行周期性校验,如每天或者每周校验,如果数据容量特别大,可以选择部分核心业务表校验即可。
获取 ts-map
在备库 TiDB 中执行以下 SQL 语句,从结果中可以获取上游 TSO (primary_ts) 和下游 TSO (secondary_ts) 信息。
select * from tidb_cdc.syncpoint_v1;
+------------------+----------------+--------------------+--------------------+---------------------+
| ticdc_cluster_id | changefeed | primary_ts | secondary_ts | created_at |
+------------------+----------------+--------------------+--------------------+---------------------+
| default | test-2 | 435953225454059520 | 435953235516456963 | 2022-09-13 08:40:15 |
+------------------+----------------+--------------------+--------------------+---------------------+
以上 syncpoint_v1
表中各列所代表的信息如下:
ticdc_cluster_id
:插入该条记录的 TiCDC 集群的 ID。changefeed
:插入该条记录的 Changefeed 的 ID。由于不同的 TiCDC 集群可能会存在重名的 Changefeed,所以需要通过 TiCDC 集群 ID 和 Changefeed 的 ID 来确认一个 Changefeed 所插入的ts-map
。primary_ts
:上游数据库 snapshot 的时间戳。secondary_ts
:下游数据库 snapshot 的时间戳。created_at
:插入该条记录的时间。
sync-diff 进行数据校验
使用sync-diff 进行数据校验。
使用上一步骤获取的 ts-map 信息来配置上下游数据库的 snapshot 信息。
其中的 Datasource config
部分示例配置如下:
######################### Datasource config ########################
[data-sources.uptidb]
host = "172.16.201.137"
port = 4000
user = "root"
password = "passwd"
snapshot = "435953225454059520"
[data-sources.downtidb]
host = "172.16.202.237"
port = 4000
user = "root"
password = "passwd"
snapshot = "435953235516456963"
以上配置只展示了 Datasource config
部分,完整配置以及校验操作请参考 sync-diff-inspector 用户文档。
注意: 在使用 Syncpoint 功能进行数据校验时,需要调整 TiKV 的 GC 时间(如8小时),保证在校验时 snapshot 对应的历史数据不会被执行 GC,在校验后再还原 GC 设置。
Syncpoint的应用--备库的一致性快照读取
注意: 使用一致性快照读之前,请先 启用 TiCDC 的 Syncpoint 功能。如果多个同步任务使用同一个下游 TiDB 集群且都开启了 Syncpoint 功能,那么这些同步任务都将根据各自的同步进度来更新 tidb_external_ts 和 ts-map。此时,你需要使用读取 ts-map 表中记录的方式来设置同步任务级别的一致性快照读,同时应避免下游应用程序使用 tidb_enable_external_ts_read 的方式读数据,因为多个同步任务之间可能存在互相干扰导致无法获得一致性的结果。
当你需要从备库查询数据的时候,在业务应用中设置 SET GLOBAL|SESSION tidb_enable_external_ts_read = ON;
就可以在备用集群上获得事务状态完成的数据。
除此之外,你也可以通过查询 ts-map
的方式选取之前的时间点进行快照读。
容灾切换演练
容灾切换演练的步骤:
-
提前检查项
- 确认备库应用账号、权限跟主库一致
- 确认changefeed链路同步没有延迟
-
正式切换
- 停止主库业务
- 锁定业务用户、kill 连接、并将主库设置只读模式
- 确保备库中 tidb_cdc.syncpoint_v1 表的primary_ts 在主库设置只读模式之后
- 停止/删除主库 changefeed
- 备库到主库 changefeed 反向同步
- 备库取消只读模式
- 启动业务访问备库
-
验证业务
-
检查反向同步链路同步
停止主库业务
- 停止应用
- 锁定业务用户、kill 所有业务用户链接
alter user app_user ACCOUNT LOCK;
- 主库设置只读模式
set global tidb_restricted_read_only=on;
set global tidb_super_read_only=on;
show global variables like '%tidb_super_read_only%';
show global variables like '%tidb_restricted_read_only%';
select now();
确认数据同步完成
- 在备库中查询 tidb_cdc.syncpoint_v1 表的最新的 primary_ts 在主库设置只读模式之后:
select * from tidb_cdc.syncpoint_v1;
- 或者查询Changefeed 状态 checkpoint 在主库设置只读模式之后:
tiup cdc cli changefeed query -s --server=http://172.16.201.137:8300 --changefeed-id="dr-primary-to-secondary"
{"state": "normal",
"tso": 438224029039198209,
"checkpoint": "2022-12-22 14:53:25.307",
"error": null
}
state
代表当前 changefeed 的同步状态,各个状态必须和changefeed list
中的状态相同。tso
代表当前 changefeed 中已经成功写入下游的最大事务 TSO。checkpoint
代表当前 changefeed 中已经成功写入下游的最大事务 TSO 对应的时间。error
记录当前 changefeed 是否有错误发生。
主库停止/删除 changefeed 通道
停止主集群changefeed,以便进行之后建立反向同步链路
tiup cdc cli changefeed stop --server=://172.16.201.137:8300 --changefeed-id="reptask"
防止意外启动,建议删除 changefeed 通道
tiup cdc cli changefeed remove --server=://172.16.201.137:8300 --changefeed-id="reptask"
备库创建 changefeed 进行反向同步
- 编辑 changefeed 配置文件,可参考主库的配置文件
- 创建changefeed
tiup cdc cli changefeed create \
--server=http://172.16.202.237:8300 \
--sink-uri="mysql://ticdc:passwd@172.16.201.137:4000/" \
--changefeed-id="reptask" \
--config=~/cdc/reptask_changefeed.toml \
--start-ts="" # 这里不需要指定start-ts,即为当前时刻开始同步
- 查看changefeed
tiup cdc cli changefeed query -s --server=http://172.16.202.237:8300 --changefeed-id=reptask
备库取消只读模式
set global tidb_restricted_read_only=off;
set global tidb_super_read_only=off;
show global variables like '%tidb_super_read_only%';
show global variables like '%tidb_restricted_read_only%';
启动业务访问备库
修改应用配置指向备库并启动业务。
一般情况下,为了保持对应用的透明,都会通过LB访问数据库,此时只需要将LB的配置指向备库即可。
容灾切换后的检查
- 查看业务执行情况。
- 确认反向链路同步正常。
- 通过 Grfana 监控查看集群运行情况。
灾难情况下的容灾接管
当发生真正的灾难,比如主集群所在区域断电断网,主备集群的同步链路可能会突然中断,从而导致备用集群数据处于事务不一致的状态。
恢复备库到事务一致的状态
在灾备集群的任意 TiCDC 节点执行以下命令,以向灾备集群重放 redo log,使数据库达到最终一致性状态:
tiup cdc redo apply --storage "s3://redo?access-key=minio&secret-access-key=miniostorage&endpoint=http://10.0.1.10:6060&force-path-style=true" --tmp-dir /tmp/redo --sink-uri "mysql://ticdc:passwd@172.16.202.237:4000"
命令中参数描述如下:
--storage
:指定 redo log 所在的 S3 位置--tmp-dir
:为从 S3 下载 redo log 的缓存目录--sink-uri
:指定灾备集群的地址
备库取消只读模式
set global tidb_restricted_read_only=off;
set global tidb_super_read_only=off;
show global variables like '%tidb_super_read_only%';
show global variables like '%tidb_restricted_read_only%';
开放业务访问
修改业务应用的数据库访问配置,并重启业务应用,使得业务访问灾备集群。
检查业务状态是否正常。