使用 BR 进行备份与恢复

Backup & Restore(以下简称 BR)是 TiDB 分布式备份恢复的命令行工具,用于对 TiDB 集群进行数据备份和恢复。相比 mydumper/loader,BR 更适合大数据量的场景。本文档介绍了 BR 的使用限制、工作原理、命令行描述、备份恢复用例以及最佳实践。

使用限制

  • BR 只支持 TiDB v3.1 及以上版本。
  • 目前只支持在全新的集群上执行恢复操作。
  • BR 备份最好串行执行,否则不同备份任务之间会相互影响。

推荐部署配置

  • 推荐 BR 部署在 PD 节点上。
  • 推荐使用一块高性能 SSD 网盘,挂载到 BR 节点和所有 TiKV 节点上,网盘推荐万兆网卡,否则带宽有可能成为备份恢复时的性能瓶颈。

下载 Binary

详见下载链接

工作原理

BR 是分布式备份恢复的工具,它将备份或恢复操作命令下发到各个 TiKV 节点。TiKV 收到命令后执行相应的备份或恢复操作。在一次备份或恢复中,各个 TiKV 节点都会有一个对应的备份路径,TiKV 备份时产生的备份文件将会保存在该路径下,恢复时也会从该路径读取相应的备份文件。

备份原理

BR 执行备份操作时,会先从 PD 获取到以下信息:

  • 当前的 TS 作为备份快照的时间点
  • 当前集群的 TiKV 节点信息

然后 BR 根据这些信息,在内部启动一个 TiDB 实例,获取对应 TS 的数据库或表信息,同时过滤掉系统库 (information_schemaperformance_schemamysql)。

此时根据备份子命令,会有两种备份逻辑:

  • 全量备份:BR 遍历全部库表,并且根据每一张表构建需要备份的 KV Range
  • 单表备份:BR 根据该表构建需要备份的 KV Range

最后,BR 将需要备份的 KV Range 收集后,构造完整的备份请求分发给集群内的 TiKV 节点。

该请求的主要结构如下:

BackupRequest{
    ClusterId,      // 集群 ID
    StartKey,       // 备份起始点,startKey 会被备份
    EndKey,         // 备份结束点,endKey 不会被备份
    StartVersion,   // 上一次备份快照的版本,用于增量备份
    EndVersion,     // 备份快照时间点
    StorageBackend, // 备份文件存储地址
    RateLimit,      // 备份速度 (MB/s)
}

TiKV 节点收到备份请求后,会遍历节点上所有的 Region Leader,找到和请求中 KV Range 有重叠范围的 Region,将该范围下的部分或者全部数据进行备份,在备份路径下生成对应的 SST 文件。

TiKV 节点在备份完对应 Region Leader 的数据后将元信息返回给 BR。BR 将这些元信息收集并存储进 backupmeta 文件中,等待恢复时使用。

假如 StartVersion 不为 0,这次备份会被视作增量备份。BR 除了收集 KV 以外,还会收集 [StartVersion, EndVersion) 之间的 DDL,在进行恢复的时候,会先恢复这些 DDL。

如果执行命令时开启了 checksum,那么 BR 在最后会对备份的每一张表计算 checksum 用于校验。

备份文件类型

备份路径下会生成以下两种类型文件:

  • SST 文件:存储 TiKV 备份下来的数据信息
  • backupmeta 文件:存储本次备份的元信息,包括备份文件数、备份文件的 Key 区间、备份文件大小和备份文件 Hash (sha256) 值

SST 文件命名格式

SST 文件以 storeID_regionID_regionEpoch_keyHash_cf 的格式命名。格式名的解释如下:

  • storeID:TiKV 节点编号
  • regionID:Region 编号
  • regionEpoch:Region 版本号
  • keyHash:Range startKey 的 Hash (sha256) 值,确保唯一性
  • cf:RocksDB 的 ColumnFamily(默认为 defaultwrite

恢复原理

BR 执行恢复操作时,会按顺序执行以下任务:

  1. 解析备份路径下的 backupMeta 文件,根据解析出来的库表信息,在内部启动一个 TiDB 实例在新集群创建对应的库表。

  2. 把解析出来的 SST 文件,根据表进行聚合。

  3. 根据 SST 文件的 Key Range 进行预切分 Region,使得每个 Region 至少对应一个 SST 文件。

  4. 遍历要恢复的每一张表,以及这个表对应的 SST 文件。

  5. 找到该文件对应的 Region,发送下载文件的请求到对应的 TiKV 节点,并在下载成功后,发送加载请求。

TiKV 收到加载 SST 文件的请求后,利用 Raft 机制保证加载 SST 数据的强一致性。在加载成功后,下载下来的 SST 文件会被异步删除。

在执行完恢复操作后,BR 会对恢复后的数据进行 checksum 计算,用于和备份下来的数据进行对比。

br-arch

BR 命令行描述

一条 br 命令是由子命令、选项和参数组成的。子命令即不带 - 或者 -- 的字符。选项即以 - 或者 -- 开头的字符。参数即子命令或选项字符后紧跟的、并传递给命令和选项的字符。

以下是一条完整的 br 命令行:

br backup full --pd "${PDIP}:2379" -s "local:///tmp/backup"

命令行各部分的解释如下:

  • backupbr 的子命令
  • fullbackup 的子命令
  • -s--storage:备份保存的路径
  • "local:///tmp/backup"-s 的参数,保存的路径为本地磁盘的 /tmp/backup
  • --pd:PD 服务地址
  • "${PDIP}:2379"--pd 的参数

命令和子命令

BR 由多层命令组成。目前,BR 包含 backuprestoreversion 三个子命令:

  • br backup 用于备份 TiDB 集群
  • br restore 用于恢复 TiDB 集群
  • br version 用于查看 BR 工具版本信息

以上三个子命令可能还包含这些子命令:

  • full:可用于备份或恢复全部数据。
  • db:可用于备份或恢复集群中的指定数据库。
  • table:可用于备份或恢复集群指定数据库中的单张表。

常用选项

  • --pd:用于连接的选项,表示 PD 服务地址,例如 "${PDIP}:2379"
  • -h/--help:获取所有命令和子命令的使用帮助。例如 br backup --help
  • --ca:指定 PEM 格式的受信任 CA 的证书文件路径。
  • --cert:指定 PEM 格式的 SSL 证书文件路径。
  • --key:指定 PEM 格式的 SSL 证书密钥文件路径。
  • --status-addr:BR 向 Prometheus 提供统计数据的监听地址。

备份集群数据

使用 br backup 命令来备份集群数据。可选择添加 fulltable 子命令来指定备份的范围:全部集群数据或单张表的数据。

如果备份时间可能超过设定的 tikv_gc_life_time(默认 10m0s,即表示 10 分钟),则需要将该参数调大。

例如,将 tikv_gc_life_time 调整为 720h

mysql -h${TiDBIP} -P4000 -u${TIDB_USER} ${password_str} -Nse \
    "update mysql.tidb set variable_value='720h' where variable_name='tikv_gc_life_time'";

备份全部集群数据

要备份全部集群数据,可使用 br backup full 命令。该命令的使用帮助可以通过 br backup full -hbr backup full --help 来获取。

用例:将所有集群数据备份到各个 TiKV 节点的 /tmp/backup 路径,同时也会将备份的元信息文件 backupmeta 写到该路径下。

br backup full \
    --pd "${PDIP}:2379" \
    --storage "local:///tmp/backup" \
    --ratelimit 120 \
    --log-file backupfull.log

以上命令中,--ratelimit 选项限制了每个 TiKV 执行备份任务的速度上限(单位 MiB/s)。--log-file 选项指定把 BR 的 log 写到 backupfull.log 文件中。

备份期间有进度条在终端中显示。当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。进度条效果如下:

br backup full \
    --pd "${PDIP}:2379" \
    --storage "local:///tmp/backup" \
    --ratelimit 120 \
    --log-file backupfull.log
Full Backup <---------/................................................> 17.12%.

备份单个数据库的数据

要备份集群中指定单个数据库的数据,可使用 br backup db 命令。同样可通过 br backup db -hbr backup db --help 来获取子命令 db 的使用帮助。

用例:将数据库 test 备份到各个 TiKV 节点的 /tmp/backup 路径,同时也会将备份的元信息文件 backupmeta 写到该路径下。

br backup db \
    --pd "${PDIP}:2379" \
    --db test \
    --storage "local:///tmp/backup" \
    --ratelimit 120 \
    --log-file backuptable.log

db 子命令的选项为 --db,用来指定数据库名。其他选项的含义与备份全部集群数据相同。

备份期间有进度条在终端中显示。当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。

备份单张表的数据

要备份集群中指定单张表的数据,可使用 br backup table 命令。同样可通过 br backup table -hbr backup table --help 来获取子命令 table 的使用帮助。

用例:将表 test.usertable 备份到各个 TiKV 节点的 /tmp/backup 路径,同时也会将备份的元信息文件 backupmeta 写到该路径下。

br backup table \
    --pd "${PDIP}:2379" \
    --db test \
    --table usertable \
    --storage "local:///tmp/backup" \
    --ratelimit 120 \
    --log-file backuptable.log

table 子命令有 --db--table 两个选项,分别用来指定数据库名和表名。其他选项的含义与备份全部集群数据相同。

备份期间有进度条在终端中显示。当进度条前进到 100% 时,说明备份已完成。在完成备份后,BR 为了确保数据安全性,还会校验备份数据。

备份数据到 Amazon S3 后端存储

如果备份的存储并不是在本地,而是在 Amazon 的 S3 后端存储,那么需要在 storage 子命令中指定 S3 的存储路径,并且赋予 BR 节点和 TiKV 节点访问 Amazon S3 的权限。

这里可以参照 AWS 官方文档在指定的 Region 区域中创建一个 S3 桶 Bucket,如果有需要,还可以参照 AWS 官方文档 在 Bucket 中创建一个文件夹 Folder

将有权限访问该 S3 后端存储的账号的 SecretKeyAccessKey 作为环境变量传入 BR 节点,并且通过 BR 将权限传给 TiKV 节点。

export AWS_ACCESS_KEY_ID=${AccessKey}
export AWS_SECRET_ACCESS_KEY=${SecretKey}

在进行 BR 备份时,显示指定参数 --s3.region--send-credentials-to-tikv, --s3.region 表示 S3 存储所在的区域,--send-credentials-to-tikv 表示将 S3 的访问权限传递给 TiKV 节点。

br backup full \
    --pd "${PDIP}:2379" \
    --storage "s3://${Bucket}/${Folder}" \
    --s3.region "${region}" \
    --send-credentials-to-tikv true \
    --log-file backuptable.log

恢复集群数据

使用 br restore 命令来恢复备份数据。可选择添加 fulldbtable 子命令来指定恢复操作的范围:全部集群数据、某个数据库或某张数据表。

注意:

如果使用本地存储,在恢复前必须将所有备份的 SST 文件复制到各个 TiKV 节点上 --storage 指定的目录下。

即使每个 TiKV 节点最后只需要读取部分 SST 文件,这些节点也需要有所有 SST 文件的完全访问权限。原因如下:

  • 数据被复制到了多个 Peer 中。在读取 SST 文件时,这些文件必须要存在于所有 Peer 中。这与数据的备份不同,在备份时,只需从单个节点读取。
  • 在数据恢复的时候,每个 Peer 分布的位置是随机的,事先并不知道哪个节点将读取哪个文件。

使用共享存储可以避免这些情况。例如,在本地路径上安装 NFS,或使用 S3。利用这些网络存储,各个节点都可以自动读取每个 SST 文件,此时上述注意事项不再适用。

恢复全部备份数据

要将全部备份数据恢复到集群中来,可使用 br restore full 命令。该命令的使用帮助可以通过 br restore full -hbr restore full --help 来获取。

用例:将 /tmp/backup 路径中的全部备份数据恢复到集群中。

br restore full \
    --pd "${PDIP}:2379" \
    --storage "local:///tmp/backup" \
    --ratelimit 128 \
    --log-file restorefull.log

以上命令中,--ratelimit 选项限制了每个 TiKV 执行恢复任务的速度上限(单位 MiB/s)。--log-file 选项指定把 BR 的 log 写到 restorefull.log 文件中。

恢复期间还有进度条会在终端中显示,当进度条前进到 100% 时,说明恢复已完成。在完成恢复后,BR 为了确保数据安全性,还会校验恢复数据。进度条效果如下:

br restore full \
    --pd "${PDIP}:2379" \
    --storage "local:///tmp/backup" \
    --log-file restorefull.log
Full Restore <---------/...............................................> 17.12%.

恢复单个数据库的数据

要将备份数据中的某个数据库恢复到集群中,可以使用 br restore db 命令。该命令的使用帮助可以通过 br restore db -hbr restore db --help 来获取。

用例:将 /tmp/backup 路径中备份数据中的某个数据库恢复到集群中。

br restore db \
    --pd "${PDIP}:2379" \
    --db "test" \
    --storage "local:///tmp/backup" \
    --log-file restorefull.log

以上命令中 --db 选项指定了需要恢复的数据库名字。其余选项的含义与恢复全部备份数据相同。

恢复单张表的数据

要将备份数据中的某张数据表恢复到集群中,可以使用 br restore table 命令。该命令的使用帮助可通过 br restore table -hbr restore table --help 来获取。

用例:将 /tmp/backup 路径下的备份数据中的某个数据表恢复到集群中。

br restore table \
    --pd "${PDIP}:2379" \
    --db "test" \
    --table "usertable" \
    --storage "local:///tmp/backup" \
    --log-file restorefull.log

从 Amazon S3 后端存储恢复数据

如果需要恢复的数据并不是存储在本地,而是在 Amazon 的 S3 后端,那么需要在 storage 子命令中指定 S3 的存储路径,并且赋予 BR 节点和 TiKV 节点访问 Amazon S3 的权限。

将有权限访问该 S3 后端存储的账号的 SecretKeyAccessKey 作为环境变量传入 BR 节点,并且通过 BR 将权限传给 TiKV 节点。

export AWS_ACCESS_KEY_ID=${AccessKey}
export AWS_SECRET_ACCESS_KEY=${SecretKey}

在进行 BR 恢复时,显示指定参数 --s3.region--send-credentials-to-tikv, --s3.region 表示 S3 存储所在的区域,--send-credentials-to-tikv 表示将 S3 的访问权限传递给 TiKV 节点。--storage参数中的 BucketFolder 分别代表需要恢复的数据所在的 S3 存储桶和文件夹。

br restore full \
    --pd "${PDIP}:2379" \
    --storage "s3://${Bucket}/${Folder}" \
    --s3.region "${region}" \
    --send-credentials-to-tikv true \
    --log-file restorefull.log

以上命令中 --table 选项指定了需要恢复的表名。其余选项的含义与恢复某个数据库相同。

增量备份恢复

如果想要增量备份,只需要在备份的时候指定 --lastbackupts 即可。

注意增量备份有两个限制:

  • 增量备份需要与前一次全量备份在不同的路径下
  • 增量备份开始时间与 lastbackupts 之间不能有 GC
    LAST_BACKUP_TS=`./br validate decode --field="end-version" -s local:///home/tidb/backupdata`
    ./br backup full\
        --pd ${PDIP}:2379 \
        -s local:///home/tidb/backupdata/incr \
        --lastbackupts ${LAST_BACKUP_TS}

以上命令会备份 [LAST_BACKUP_TS, current PD timestamp) 之间的增量数据。你可以使用 validate 指令获取上一次备份的时间戳。

示例备份的增量数据包括 [LAST_BACKUP_TS, current PD timestamp) 之间的新写入数据,以及这段时间内的 DDL。在恢复的时候,我们会先把所有 DDL 恢复,而后才会恢复写入数据。

在增量恢复的时候,使用 BR 的方法和全量恢复并无差别。需要注意,恢复增量数据的时候,需要保证备份时指定的 last backup ts 之前备份的数据已经全部恢复到目标集群。

最佳实践

  • 推荐在 -s 指定的备份路径上挂载一个共享存储,例如 NFS。这样能方便收集和管理备份文件。
  • 在使用共享存储时,推荐使用高吞吐的存储硬件,因为存储的吞吐会限制备份或恢复的速度。
  • 推荐在业务低峰时执行备份操作,这样能最大程度地减少对业务的影响。

更多最佳实践内容,参见 BR 备份与恢复场景示例

备份和恢复示例

本示例展示如何对已有的集群数据进行备份和恢复操作。可以根据机器性能、配置、数据规模来预估一下备份和恢复的性能。

数据规模和机器配置

假设对 TiKV 集群中的 10 张表进行备份和恢复。每张表有 500 万行数据,数据总量为 35 GB。

MySQL [sbtest]> show tables;
+------------------+
| Tables_in_sbtest |
+------------------+
| sbtest1          |
| sbtest10         |
| sbtest2          |
| sbtest3          |
| sbtest4          |
| sbtest5          |
| sbtest6          |
| sbtest7          |
| sbtest8          |
| sbtest9          |
+------------------+

MySQL [sbtest]> select count(*) from sbtest1;
+----------+
| count(*) |
+----------+
|  5000000 |
+----------+
1 row in set (1.04 sec)

表结构如下:

CREATE TABLE `sbtest1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `k` int(11) NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `k_1` (`k`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=5138499

示例假设有 4 个 TiKV 节点,每个节点配置如下:

CPU 内存 磁盘 副本数
16 核 32 GB SSD 3

备份示例

  • 备份前需确认已将 GC 时间调长,确保备份期间不会因为数据丢失导致中断
  • 备份前需确认 TiDB 集群没有执行 DDL 操作

执行以下命令对集群中的全部数据进行备份:

bin/br backup full -s local:///tmp/backup --pd "${PDIP}:2379" --log-file backup.log
[INFO] [collector.go:165] ["Full backup summary: total backup ranges: 2, total success: 2, total failed: 0, total take(s): 0.00, total kv: 4, total size(Byte): 133, avg speed(Byte/s): 27293.78"] ["backup total regions"=2] ["backup checksum"=1.640969ms] ["backup fast checksum"=227.885µs]

恢复示例

恢复操作前,需确认待恢复的 TiKV 集群是全新的集群。

执行以下命令对全部数据进行恢复:

bin/br restore full -s local:///tmp/backup --pd "${PDIP}:2379" --log-file restore.log
[INFO] [collector.go:165] ["Full Restore summary: total restore tables: 1, total success: 1, total failed: 0, total take(s): 0.26, total kv: 20000, total size(MB): 10.98, avg speed(MB/s): 41.95"] ["restore files"=3] ["restore ranges"=2] ["split region"=0.562369381s] ["restore checksum"=36.072769ms]