返回介绍

集群间双向同步

发布于 2020-10-26 07:01:25 字数 2746 浏览 1074 评论 0 收藏 0

本文档介绍如何将一个 TiDB 集群的数据双向同步到另一个 TiDB 集群、双向同步的实现原理、如何开启双向同步、以及如何同步 DDL 操作。

使用场景

当用户需要在两个 TiDB 集群之间双向同步数据时,可使用 TiDB Binlog 进行操作。例如要将集群 A 的数据同步到集群 B,而且要将集群 B 的数据同步到集群 A。

注意:

集群间双向同步的前提条件是,写入两个集群的数据必须保证无冲突,即在两个集群中,不会同时修改同一张表的同一主键和具有唯一索引的行。

使用场景示例图如下:

使用场景示例图

实现原理

原理示例图

在 A 和 B 两个集群间开启双向同步,则写入集群 A 的数据会同步到集群 B 中,然后这部分数据又会继续同步到集群 A,这样就会出现无限循环同步的情况。如上图所示,在同步数据的过程中 Drainer 对 binlog 加上标记,通过过滤掉有标记的 binlog 来避免循环同步。详细的实现流程如下:

  1. 为两个集群分别启动 TiDB Binlog 同步程序。
  2. 待同步的事务经过 A 的 Drainer 时,Drainer 为事务加入 标识表

    _drainer_repl_mark 标识表的结构如下:

    CREATE TABLE `_drainer_repl_mark` (
      `id` bigint(20) NOT NULL,
      `channel_id` bigint(20) NOT NULL DEFAULT '0',
      `val` bigint(20) DEFAULT '0',
      `channel_info` varchar(64) DEFAULT NULL,
      PRIMARY KEY (`id`,`channel_id`)
    );

    Drainer 使用如下 SQL 语句更新 _drainer_repl_mark 可保证数据改动,从而保证产生 binlog:

    update drainer_repl_mark set val = val + 1 where id = ? && channel_id = ?;

    同步 DDL

    因为 Drainer 无法为 DDL 操作加入标识表,所以采用单向同步的方式来同步 DDL 操作。

    比如集群 A 到集群 B 开启了 DDL 同步,则集群 B 到集群 A 会关闭 DDL 同步。即 DDL 操作全部在 A 上执行。

    注意:

    DDL 操作无法在两个集群上同时执行。执行 DDL 时,若同时有 DML 操作或者 DML binlog 没同步完,会可能出现 DML 同步的上下游表结构不一致的情况。

    配置并开启双向同步

    若要在集群 A 和集群 B 间进行双向同步,假设统一在集群 A 上执行 DDL。在集群 A 到集群 B 的同步路径上,向 Drainer 添加以下配置:

    [syncer]
    loopback-control = true
    channel-id = 1 # 互相同步的两个集群配置相同的 ID。
    sync-ddl = true # 需要同步 DDL 操作
    
    [syncer.to]
    # 1 表示 SyncFullColumn,2 表示 SyncPartialColumn。
    # 若设为 SyncPartialColumn,Drainer 会允许下游表结构比当前要同步的数据多或者少列
    # 并且去掉 SQL mode 的 STRICT_TRANS_TABLES,来允许少列的情况,并插入零值到下游。
    sync-mode = 2
    
    # 忽略 checkpoint 表。
    [[syncer.ignore-table]]
    db-name = "tidb_binlog"
    tbl-name = "checkpoint"

    在集群 B 到集群 A 的同步路径上,向 Drainer 添加以下配置:

    [syncer]
    loopback-control = true
    channel-id = 1 # 互相同步的两个集群配置相同的 ID。
    sync-ddl = false  # 不需要同步 DDL 操作。
    
    [syncer.to]
    # 1 表示 SyncFullColumn,2 表示 SyncPartialColumn。
    # 若设为 SyncPartialColumn,Drainer 会允许下游表结构比当前要同步的数据多或者少列
    # 并且去掉 SQL mode 的 STRICT_TRANS_TABLES,来允许少列的情况,并插入零值到下游。
    sync-mode = 2
    
    # 忽略 checkpoint 表。
    [[syncer.ignore-table]]
    db-name = "tidb_binlog"
    tbl-name = "checkpoint"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文