Gravity 的测试调研 Gravity -> TiDB

参考文档:https://github.com/moiot/gravity/blob/master/docs/2.0/03-inputs.md

整体架构

Gravity 是一款数据复制组件,提供全量、增量数据同步,以及向消息队列发布数据更新。 使用场景

  • 大数据总线:发送 MySQL Binlog,Mongo Oplog 的数据变更到 kafka 供下游消费
  • 单向数据同步:MySQL --> MySQL 的全量、增量同步
  • 双向数据同步:MySQL <–> MySQL 的双向增量同步,同步过程中可以防止循环复制
  • 分库分表到合库的同步:MySQL 分库分表 --> 合库的同步,可以指定源表和目标表的对应关系
  • 在线数据变换:同步过程中,可支持对进行数据变换

架构简介

单进程架构

单进程的 Gravity 采用基于插件的微内核架构,由各个插件围绕系统里的 core.Msg 结构实现输入到输出的整个流程。

各个插件有各自独立的配置选项。

如上图所示,系统总共由这几个插件组成:

  • Input 用来适配各种数据源,比如 MySQL 的 Binlog 并生成 core.Msg
  • Filter 用来对 Input 所生成的数据流做数据变换操作,比如过滤某些数据,重命名某些列,对列加密
  • Output 用来将数据写入目标,比如 Kafka, MySQL,Output 写入目标时,使用 Router 所定义的路由规则
  • Scheduler 用来对 Input 生成的数据流调度,并使用 Output 写入目标;Scheduler 定义了当前系统支持的一致性特性( 当前默认的 Scheduler 支持同一行数据的修改有序
  • Matcher 用来匹配 Input 生成的数据。Filter 和 Router 使用 Matcher 匹配数据

基本功能测试

MySQL环境准备

Gravity 对源端 MySQL 的要求如下:

  • 开启 gtid 模式的 binlog
  • 创建 drc 账户,并赋予 replication 相关权限,以及 drc 数据库的所有权限
  • MySQL 源端、目标端相应的表需要创建好

MySQL 配置项如下所示

[mysqld]

server_id=4

log_bin=mysql-bin

gtid-mode=ON

binlog_format=ROW

drc 账户权限如下所示

CREATE USER drc IDENTIFIED BY 'xxx' ;

GRANT SELECT , RELOAD, LOCK TABLES, REPLICATION SLAVE, REPLICATION CLIENT, INSERT , UPDATE , DELETE ON *.* TO 'drc' @ '%' ;

GRANT ALL PRIVILEGES ON drc.* TO 'drc' @ '%' ;

上下游表结构创建

--source

CREATE TABLE ``test.test_source_table(

``id int (11),

PRIMARY KEY (id)

) ENGINE=InnoDB DEFAULT CHARSET=utf8

--target

CREATE TABLE ``test.test_target_table(

``id int (11),

PRIMARY KEY (id)

) ENGINE=InnoDB DEFAULT CHARSET=utf8

GO 环境配置

参考文档:配置好 Go 语言环境

wget https: //dl .google.com /go/go1 .11.4.linux-amd64. tar .gz

tar -C /usr/local -xzf go1.11.4.linux-amd64. tar .gz

mkdir -p usr /local/go/src/github .com /moiot/ && cd usr /local/go/src/github .com /moiot/

git clone https: //github .com /moiot/gravity .git

cd gravity && make

MySQL to MySQL

创建配置文件 mysql2mysql.toml

mysql2mysql.toml

同步测试

##源端表及表数据

mysql> show databases;

+--------------------+

| Database |

+--------------------+

| information_schema |

| _gravity |

| mysql |

| performance_schema |

| sys |

| test |

| wk |

+--------------------+

7 rows in set (0.00 sec)

mysql> use test

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Database changed

mysql> show tables;

+---------------------+

| Tables_in_test |

+---------------------+

| test_source_table_1 |

| test_source_table_2 |

+---------------------+

2 rows in set (0.00 sec)

mysql> select * from test_source_table_1;

+-----+------+------+

| id | name | age |

+-----+------+------+

| 1 | NULL | NULL |

| 2 | NULL | NULL |

| 3 | NULL | NULL |

| 4 | NULL | NULL |

| 6 | NULL | NULL |

| 9 | NULL | NULL |

| 33 | NULL | NULL |

| 333 | wk | 12 |

| 334 | wk | 12 |

| 354 | wk | 12 |

+-----+------+------+

10 rows in set (0.00 sec)

mysql> select * from test_source_table_2;

+-----+------+------+

| id | name | age |

+-----+------+------+

| 3 | NULL | NULL |

| 4 | NULL | NULL |

| 5 | NULL | NULL |

| 6 | NULL | NULL |

| 66 | NULL | NULL |

| 77 | GG | 18 |

| 81 | GG | 18 |

| 89 | GG | 18 |

| 166 | bb | 11 |

| 183 | bb | 11 |

+-----+------+------+

10 rows in set (0.00 sec)

mysql>

目标端效果

mysql> show databases;

+--------------------+

| Database |

+--------------------+

| information_schema |

| mysql |

| performance_schema |

| sys |

| test |

+--------------------+

5 rows in set (0.00 sec)

mysql> use test ;

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Database changed

mysql> show tables;

+-------------------+

| Tables_in_test |

+-------------------+

| test_target_table |

+-------------------+

1 row in set (0.00 sec)

mysql> select * from test_target_table;

+-----+------+------+

| id | name | age |

+-----+------+------+

| 1 | NULL | NULL |

| 2 | NULL | NULL |

| 3 | NULL | NULL |

| 4 | NULL | NULL |

| 5 | NULL | NULL |

| 6 | NULL | NULL |

| 9 | NULL | NULL |

| 33 | NULL | NULL |

| 66 | NULL | NULL |

| 77 | GG | 18 |

| 81 | GG | 18 |

| 89 | GG | 18 |

| 166 | bb | 11 |

| 183 | bb | 11 |

| 333 | wk | 12 |

| 334 | wk | 12 |

+-----+------+------+

16 rows in set (0.00 sec)

mysql>

MySQL to TiDB

上游一库多表下游一库一表测试

配置文件

mysql2tidb2.toml

测试步骤

--上游表

mysql> show tables;

+ ---------------------+

| Tables_in_test |

+ ---------------------+

| test_source_table_1 |

| test_source_table_2 |

+ ---------------------+

2 rows in set (0.00 sec)

mysql> select * from test_source_table_1;

+ ------+---------+------+

| id | name | age |

+ ------+---------+------+

| 2019 | pingcap | 3 |

+ ------+---------+------+

1 row in set (0.00 sec)

mysql> select * from test_source_table_2;

+ -----+------+------+

| id | name | age |

+ -----+------+------+

| 77 | GG | 18 |

| 81 | GG | 18 |

| 89 | GG | 18 |

| 166 | bb | 11 |

| 183 | bb | 11 |

+ -----+------+------+

5 rows in set (0.01 sec)

--下游同步效果

mysql> select * from test_target_table;

+ ------+---------+------+

| id | name | age |

+ ------+---------+------+

| 77 | GG | 18 |

| 81 | GG | 18 |

| 89 | GG | 18 |

| 166 | bb | 11 |

| 183 | bb | 11 |

| 2019 | pingcap | 3 |

+ ------+---------+------+

6 rows in set (1.91 sec)

--上游delete

mysql> delete from test_source_table_2 where name = 'GG' or age= '11' ;

Query OK, 5 rows affected (0.00 sec)

mysql> select * from test_source_table_2;

Empty set (0.00 sec)

--下游效果

mysql> select * from test_target_table;

+ ------+---------+------+

| id | name | age |

+ ------+---------+------+

| 2019 | pingcap | 3 |

+ ------+---------+------+

1 row in set (0.10 sec)

--上游 insert 在 test_source_table_2 中插入 id=2019 的记录,模拟主键冲突

mysql> insert into test_source_table_2 values (2019, 'tidb' ,2);

Query OK, 1 row affected (0.00 sec)

mysql> select * from test_source_table_2;

+ ------+------+------+

| id | name | age |

+ ------+------+------+

| 2019 | tidb | 2 |

+ ------+------+------+

1 row in set (0.00 sec)

mysql> select * from test_source_table_1;

+ ------+---------+------+

| id | name | age |

+ ------+---------+------+

| 2019 | pingcap | 3 |

+ ------+---------+------+

1 row in set (0.00 sec)

--下游效果

mysql> select * from test_target_table;

+ ------+------+------+

| id | name | age |

+ ------+------+------+

| 2019 | tidb | 2 |

+ ------+------+------+

1 row in set (0.31 sec)

-- 上游 update

mysql> update test_source_table_1 set age = 999 where name = 'pingcap' ;

Query OK, 1 row affected (0.02 sec)

Rows matched: 1 Changed: 1 Warnings: 0

mysql> select * from test_source_table_1;

+ ------+---------+------+

| id | name | age |

+ ------+---------+------+

| 2019 | pingcap | 999 |

+ ------+---------+------+

1 row in set (0.00 sec)

--下游结果

mysql> select * from test_target_table;

+ ------+---------+------+

| id | name | age |

+ ------+---------+------+

| 2019 | pingcap | 999 |

+ ------+---------+------+

1 row in set (0.05 sec)

-- 此时发现上游按照数据同样被 replace 了

多库多表同步

gravity 可以同时启动多个,多个同步进程指向下游同一个库

默认 gravity 启动会使用 8080 端口,如果启动多个进程,需要改动默认端口

bin/gravity -config mysql2tidbtwo.toml -http-addr “:9090”

mysql> select * from test_source_table_1;

+ ----+------+------+

| id | name | age |

+ ----+------+------+

| 0 | RAFT | 10 |

+ ----+------+------+

1 row in set (0.00 sec)

mysql> select * from test_source_table_2;

+ ----+------+------+

| id | name | age |

+ ----+------+------+

| 1 | TIKV | 2 |

+ ----+------+------+

1 row in set (0.01 sec)

--源库效果

mysql> select * from test_target_table;

+ ------+---------+------+

| id | name | age |

+ ------+---------+------+

| 0 | RAFT | 10 |

| 1 | TIKV | 2 |

| 2019 | pingcap | 999 |

+ ------+---------+------+

3 rows in set (7.50 sec)

其它功能测试

filter 模块功能测试遇到 bug,摩拜正在修复

测试结果

  • 上下游同步成功 ,MySQL 到 TiDB 同步配置文件只需要修改对应 IP 和 port 就可以

  • 可以完成一库多表的合并

  • 同步之前需要在上下游创建好对应的 schema 以及表结构

  • DML 遇到主键冲突时会 replace

  • 多库合并仅限于同一数据库实例不同 schema ,跨实例合表有问题

  • MySQL 到 TiDB 同步配置文件只需要修改对应 IP 和 port 就可以

对比 TiDB-DM