TiCDC 双向复制
TiCDC 支持在两个 TiDB 集群之间进行双向复制 (Bidirectional replication, BDR)。基于该功能,你可以使用 TiCDC 来构建 TiDB 集群的多写多活解决方案。
本文档以在两个 TiDB 集群之间进行双向复制为例,介绍双向复制的使用方法。
部署双向复制
TiCDC 复制功能只会将指定时间点之后的增量变更复制到下游集群。开始双向复制之前,需要采取以下步骤:
(可选)根据实际需要,使用数据导出工具 Dumpling 和导入工具 TiDB Lightning 将两个集群的数据导入到对方集群。
在这两个 TiDB 集群之间部署两套 TiCDC 集群,集群的拓扑如下图所示,图中箭头所指的方向即为该 TiCDC 集群同步数据的流向。
指定上下游集群的数据同步的开始时间点。
确认上下游集群的时间点。如果进行双集群容灾,那么建议确保两个集群在某个对应的时刻的数据是一致的,例如 TiDB A 在
ts=1
时刻与 TiDB B 在ts=2
的时刻数据是一致的。在创建同步任务时,分别把对应集群的同步任务的
--start-ts
参数指定为对应的tso
,即上游为 TiDB A 的同步任务需设置参数--start-ts=1
,上游为 TiDB B 的同步任务需设置参数--start-ts=2
。
在创建同步任务的
--config
参数所指定的配置文件中,添加如下配置:# 是否启用 bdr 模式 bdr-mode = true
这样,以上搭建好的集群即可对数据进行双向复制。
DDL 类别
从 v7.6.0 开始,为了在双向复制中尽可能地支持 DDL 同步,根据 DDL 对业务的影响,TiDB 将 TiCDC 原本支持同步的 DDL 划分为两种 DDL:可复制的 DDL 和不可复制的 DDL。
可复制的 DDL
可复制的 DDL 是指在双向复制中,可以直接执行并同步到其他 TiDB 集群的 DDL。
可复制的 DDL 包括:
CREATE DATABASE
CREATE TABLE
ADD COLUMN
:添加的列必须可以为null
,或者是同时带有not null
和default value
ADD NON-UNIQUE INDEX
DROP INDEX
MODIFY COLUMN
:仅能修改列的default value
和comment
ALTER COLUMN DEFAULT VALUE
MODIFY TABLE COMMENT
RENAME INDEX
ADD TABLE PARTITION
DROP PRIMARY KEY
ALTER TABLE INDEX VISIBILITY
ALTER TABLE TTL
ALTER TABLE REMOVE TTL
CREATE VIEW
DROP VIEW
不可复制的 DDL
不可复制的 DDL 是指对业务影响较大、可能会造成集群间数据不一致性的 DDL,这类 DDL 不能在双向复制中直接通过 TiCDC 同步到其他 TiDB 集群的 DDL。不可复制的 DDL 必须通过特定的操作来执行。
不可复制的 DDL 包括:
DROP DATABASE
DROP TABLE
ADD COLUMN
:添加的列为not null
且不带有default value
DROP COLUMN
ADD UNIQUE INDEX
TRUNCATE TABLE
MODIFY COLUMN
:修改列除default value
和comment
以外的属性RENAME TABLE
DROP PARTITION
TRUNCATE PARTITION
ALTER TABLE CHARACTER SET
ALTER DATABASE CHARACTER SET
RECOVER TABLE
ADD PRIMARY KEY
REBASE AUTO ID
EXCHANGE PARTITION
REORGANIZE PARTITION
DDL 同步
为了能够解决上述可复制的 DDL 和不可复制的 DDL 两类 DDL 的同步问题,TiDB 引入了两种 BDR role:
PRIMARY
:你可以执行可复制的 DDL,但不能执行不可复制的 DDL。TiCDC 会把 PRIMARY 集群执行的可复制的 DDL 同步到下游。SECONDARY
:你不能执行上述所有的 DDL。但是,TiCDC 能够把 PRIMARY 集群执行的 DDL 同步到 SECONDARY 集群。
在不设置 BDR role 时,你可以执行任意 DDL。但是处于 BDR 模式中的 changefeed 不会同步该集群上的任何 DDL。
总的来说,在 BDR 模式下,TiCDC 仅会将 PRIMARY 集群上可复制的 DDL 同步到下游。
可复制的 DDL 的同步场景
选择一个 TiDB 集群,执行
ADMIN SET BDR ROLE PRIMARY
将其设置为主集群。如下所示:ADMIN SET BDR ROLE PRIMARY; Query OK, 0 rows affected Time: 0.003s ADMIN SHOW BDR ROLE; +----------+ | BDR_ROLE | +----------+ | primary | +----------+在其他 TiDB 集群上,执行
ADMIN SET BDR ROLE SECONDARY
将其设置为从集群。在主集群上执行可复制的 DDL,执行成功的 DDL 会被 TiCDC 同步到从集群中。
不可复制的 DDL 的同步场景
- 对所有 TiDB 集群执行
ADMIN UNSET BDR ROLE
,撤销集群的 BDR role。 - 暂停所有集群中需要执行 DDL 的对应的表的写入操作。
- 等待所有集群中对应表的所有写入已经同步到其他集群后,手动在每一个 TiDB 集群上单独执行所有的 DDL。
- 等待 DDL 完成之后,重新恢复写入。
- 按照可复制的 DDL 的同步场景的操作步骤,切换回可复制的 DDL 的同步场景。
停止双向复制
在业务数据停止写入之后,你可以在两个集群中都插入一行特殊的值,通过检查这两行特殊的值来确保数据达到了一致的状态。
检查完毕之后,停止同步任务,并对所有集群执行 ADMIN UNSET BDR ROLE
。
使用限制
BDR role 只能在以下两种场景中正常使用:
1 个
PRIMARY
集群和 n 个SECONDARY
集群(可复制的 DDL 的同步场景)n 个不设置 BDR role 的集群(用于在每个集群手动执行不可复制的 DDL 的同步场景)
一般情况下,禁止在同步的表中使用
AUTO_INCREMENT
或AUTO_RANDOM
键,以免产生数据冲突的问题。如果需要使用AUTO_INCREMENT
或AUTO_RANDOM
键,可以通过在不同的集群设置auto_increment_increment
和auto_increment_offset
来使得不同的集群都能够分配到不同的主键。假设有三个 TiDB 集群(A、B、C)处于双向同步中,那么你可以采取如下设置:- 在 A 中设置
auto_increment_increment=3
,auto_increment_offset=2000
- 在 B 中设置
auto_increment_increment=3
,auto_increment_offset=2001
- 在 C 中设置
auto_increment_increment=3
,auto_increment_offset=2002
这样 A、B、C 隐式分配到的
AUTO_INCREMENT
ID 和AUTO_RANDOM
ID 就不会互相冲突。如果需要增加 BDR 模式的集群,需要临时暂停相关业务的写入,重新在所有集群上设置合适的auto_increment_increment
和auto_increment_offset
,然后再开启相关业务。- 在 A 中设置
双向复制的集群不具备检测写冲突的功能,写冲突将会导致未定义问题。你需要在业务层面保证不出现写冲突。
TiCDC 双向复制功能支持超过 2 个集群的双向同步,但是不支持多个集群级联模式的同步,即 TiDB A -> TiDB B -> TiDB C -> TiDB A 的环形复制方式。在这种部署方式下,如果其中一个链路出现问题则会影响整个数据同步链路。因此,如果需要部署多个集群之间的双向复制,每个集群都需要与其他集群两两相连,即
TiDB A <-> TiDB B
,TiDB B <-> TiDB C
,TiDB C <-> TiDB A
。