【揭秘GP】全新 Greenplum 集群传输工具—GPCOPY 2.1.0 正式发布

导读:GPCOPY 是新一代的支持 Greenplum 集群之间快速高效传输数据的工具。作为 Greenplum 集群数据传输的官方首选配套工具,GPCOPY 除了具有高速稳定易用的特点外,还支持不同版本 Greenplum 集群之间的传输(当然支持同版本之间的传输)。GPCOPY 支持从 GP4.3.x 到 GP 5.x、GP5.x 到 GP6.x、甚至 GP4.3.x 到 GP6.x 的数据传输。它也同时支持同等规模集群和不等规模集群之间的传输。另外 GPCOPY 还支持数据的校验,支持事务,增加了数据传输的可靠性。GPCOPY 目前还没有开源,最新版本2.1.0在3月9日正式发布上线,做了很多方面的提升,可以在官网 https://network.pivotal.io/products/gpdb-data-copy/ 下载到。

一、新功能

1. 支持有外键的表、view 以及有继承关系的表

GPCOPY 是以表为单位从源数据库中把表的定义及表中数据复制到目标数据库中。

首先:GPCOPY 拷贝表是支持事务的,如果再拷贝过程中出错则回滚。例如如果目标数据库中不存在要拷贝的表,GPCOPY 首先会创建目标表,然后把源表的数据拷贝到目标表,如果在拷贝数据的过程中由于某种原因出错了,则整个表的拷贝会回滚,被创建的目标表不会出现在目标数据库中。

其次:GPCOPY 支持并行拷贝多个表。使用 -jobs 可以指定最多同时拷贝多少个表。-jobs 的最大值是由运行 GPCOPY 机器的性能、源数据库的性能、目标数据库的性能等多个因素共同决定的。并行拷贝表使 GPCOPY 拥有出色的性能,但是数据库中有些表并不是相互独立存在的,比如有外键的表、view、有继承关系的表都需要依赖其它的表,此时并行拷贝表就会出现问题。在 GPCOPY 2.1.0 版本之前,这个问题一直存在,例如有如下两个表:

<code>CREATE TABLE t(id INT PRIMARY KEY,name TEXT);
CREATE TABLE ft(item_id INT NOT NULL, foreign_id INT REFERENCES t(id));/<code>

为什么会出现这个错误?

让我们先来看一下 GPCOPY 在目标数据库创建表“ft”的步骤:

  1. 在源数据库使用 pg_dump -t table_name 导出创建表“ft”的SQL。
  2. 在目标数据库执行这些SQL语句创建表“ft”。
<code>CREATE TABLE ft (
    item_id integer NOT NULL,
    foreign_id integer
) DISTRIBUTED BY (item_id);
ALTER TABLE public.ft OWNER TO gpadmin;
--
# Name: ft_foreign_id_fkey; Type: FK CONSTRAINT; Schema: public; # Owner: gpadmin
--
ALTER TABLE ONLY ft
 ADD CONSTRAINT ft_foreign_id_fkey FOREIGN KEY (foreign_id) REFERENCES t(id);/<code>

上面是创建表“ft”的SQL,里面会引用“t”这个表。但是 GPCOPY 是在目标端并行地、并且在不同事务中创建表“t”和表“ft”,此时表“t”并不存在,因此会出错。

在 GPCOPY 2.1.0 中,我们通过分析表之间的依赖关系,对于有外键的表、view、以及有继承关系的表,先拷贝他们依赖的表。如果被依赖的表拷贝成功,再拷贝这些表;如果被依赖的表拷贝失败,则这些表不会被拷贝。如上例所示,GPCOPY 2.1.0 会先拷贝表“t”,表“t”拷贝成功后再拷贝表“ft”。对于没有依赖关系的表,我们依旧并行地进行拷贝。

GPCOPY 2.1.0 做到了既能并行拷贝表的 DDL 和数据,又能处理表之间的依赖的关系。

2. 新增选项 dest-mapping-file

运行 gpcopy –help 可以看到对该选项的说明:

<code>Use the host to IP map file in case of destination cluster IP auto-resovling fails/<code>

意思是当 GPCOPY 遇到无法解析 HOSTNAME 的时候,可以把 HOSTNAME 对应的 IP 地址配置到一个文件中,通过 dest-maping-file 把该文件传给 GPCOPY。

GPCOPY 什么时候需要解析 HOSTNAME?需要解析谁的 HOSTNAME?

【揭秘GP】全新 Greenplum 集群传输工具—GPCOPY 2.1.0 正式发布

接下来用上图来解释这两个问题。

GPCOPY 在源数据库和目标数据库之间主要是通过 segment 到 segment 相互传输数据。源端和目标端的 segment 往往不在同一个 host 上,通过 gpcopy_helper 实现跨机器的数据传输。运行在源端 segment 上 gpcopy_helper 负责发送数据,运行在目标端 segment 上的 gpcopy_helper 负责接收数据。gpcopy_helper 发送数据的时候,需要知道接收数据的 gpcopy_helper 的地址,即目标 segment 的IP地址。

2.1.0 版本之前 GPCOPY 没有 dest-mapping-file 这个选项,那么它是怎么获取目标端 segment IP 地址的,以及存在什么问题呢?

首先查询目标数据库中 gp_segment_configuration 表,获取 segment 的 HOSTNAME 。源端不能直接使用该 HOSTNAME,需要其对应的IP地址。所以 GPCOPY 会在在目标集群的 master 上查询该 HOSTNAME 对应的IP地址(GPCOPY已知目标端 master 的地址,master 知道 segment HOSTNAME 对应的 IP)。但是有时目标端 master 只配置了 segment HOSTNAME 对应的私有IP地址,源数据库和目标数据库并不在一个集群中,导致源端的 gpcopy_helper 和目标端的 gpcopy_helper 无法通信。

为解决该问题,GPCOPY 2.1.0 增加了 dest-mapping-file 选项,当 GPCOPY 通过以上方法无法获取 segment 公有IP的时候,用户可以通过配置文件设置;或者当目标端的 segment 没有 public IP 的时候,可以设置一个用来做数据转发的IP地址。

GPCOPY 2.1.0 新增 dest-mapping-file 选项可以帮助用户解决源数据库和目标数据库之间的通信问题。

3. 减少端口占用

如前面提到, GPCOPY 可以同时运行多个 job,每个 job 负责拷贝一个表。GPCOPY 2.1.0 之前的版本,每个目标表都有独立的 gpcopy_helper 进程用来接收数据,每个 gpcopy_helper 进程分别占用不用的端口。因此会出现如果设置的 job 数量很多,则占用的端口会过多的情况。GPCOPY 2.1.0 实现了多个 gpcopy_helper 进程可以复用同一个端口来接收数据,从而减少了端口资源的占用。

4. 增加进度展示及统计信息

【揭秘GP】全新 Greenplum 集群传输工具—GPCOPY 2.1.0 正式发布

每个表拷贝完成时,GPCOPY 都会展示出当前的拷贝进度:总共多少表需要拷贝,已有多少表完成拷贝。

【揭秘GP】全新 Greenplum 集群传输工具—GPCOPY 2.1.0 正式发布

当所有表拷贝完成时,GPCOPY 会如上图一样显示本次拷贝总共花费的时间,总共传输的数据量及平均传输速度。

5. 优化命令行

2.1.0 版本,GPCOPY 命令支持单字符的 option。

二、架构

【揭秘GP】全新 Greenplum 集群传输工具—GPCOPY 2.1.0 正式发布

GPCOPY 的架构图如上图所示,大概包括三层:

  1. 最上层负责参数解析及获取要拷贝的表的元数据,为进行表拷贝做准备。
  2. 中间层即第二层负责分析表之间的依赖关系,生成拷贝依赖关系,并负责调度拷贝任务。
  3. 最底层也即第三层,负责一个表的拷贝。包括拷贝表的DDL、拷贝数据、数据验证及对表进行 ANALYZE。

第一层比较好理解,不做过多解释。第三层是拷贝一个表必须的,第二层是并行拷贝多个表所必须的,接下来将自底向上进行详细介绍。

1. 拷贝一个表

  • 拷贝DDL

目前 GPCOPY 基于 pg_dump 实现拷贝表的 DDL。首先在源端使用 pg_dump -t 导出源表的 DDL,然后在目标数据库执行该 DDL 来创建表,并对创建表涉及的 schema、sequence、权限等做了处理。

  • 拷贝数据

把数据从源表拷贝到目标源有两种模式,一种是 master 之间拷贝,另外一种是 segment 之间拷贝。当数据量比较小的时候建议使用 master 拷贝数据,否则使用 segment 拷贝数据,模式选择可参考 -on-segment-threshold 选项使用说明。

无论是哪式拷贝模式,主要的步骤大致如下:

  1. 使用 copy 工具把数据从源表中导出
  2. 然后 gpcopy_helper 把数据从源 master/segment 传递到目标端 master/segment 上
  3. 最后再使用 copy 工具把数据导入到目标表中

当使用 segment 模式进行拷贝数据的时候,使用的是 copy on segment 命令将数据导入导出到 segment 上,但是该命令将数据导入到表的时候不支持重分布。因此当数据在目标需要重分布时候,使用临时外部表代替 copy 命令将数据导入表中。

  • 验证数据

该模块用于验证拷贝到目标表中的数据是否正确。有两种数据验证方法:md5xor 和 count。 md5xor是比较严格的数据验证方法,会把源表和目标表中的每行数据都计算在内,因此该方法比较耗时。而 count 方法则相反,只简单的对比源表和目标表中的数据条数,比较简单也不严格。用户可根据自己的需求选择验证数据或者不验证,或者选择不同的验证方法。

  • ANALYZE

Greenplum 中提供了 ANALYZE 命令用于更新数据库中表的统计信息。GPCOPY 中也提供在拷贝完一个数据表后自动调用 ANALYZE 命令的功能。

2. 并行拷贝多个表

在本文前面已经提到有外键的表、view、有继承关系的表,这些类型的表不是独立存在的,它们依赖于其它的表。这种依赖关系对于并行拷贝多个表造成了很大的困难。GPCOPY 主要通过以下几个模块解决该问题。

  • 生成表之间的拷贝依赖关系

对于数据库,表之间的依赖关系有很多种,比如:

  • 有外键的表是表中的某一列引用另外一个表的一列,通过 pg_constraint 可获取该依赖关系;
  • view 则是一个表依赖于另外一个表或者多个表,通过 pg_depend 和 pg_rewrite 可获取该依赖关系;
  • 有继承关系的表(包括partition 表)则通过pg_inherits来获取该依赖关系。

但对于GPCOPY来讲,只有一种依赖关系,即拷贝依赖关系:一个表依赖于另外一个表,被依赖的表需要先拷贝。

该模块通过查询源数据库的 catalog,分析表之间不同的依赖关系,最终生成表之间的拷贝依赖关系。

  • 调度器

调度器主要负责两个工作:第一、保证表的拷贝顺序符合表之间的依赖关系;第二、控制拷贝表的并发度。

怎么才能使拷贝顺序符合表之间的依赖关系?思路很简单,没有任何依赖的表或者其依赖的表全部拷贝完成,则调度拷贝该表,否则该表不会被调度。

  • 生成报告

该模块比较简单,收集并行执行的表拷贝的结果,生成拷贝进度信息及汇总信息。

三、未来规划

GPCOPY 的官方文档可以参考 https://gpdb.docs.pivotal.io/GPCOPY/2-1/index-GPCOPY.html。在接下来的版本,GPCOPY 还会支持增量传输,进一步提高性能。也希望广大用户多多反馈,多提宝贵意见。



本文作者

王晓冉

现任 Greenplum 研发工程师。研究生毕业于中国科学院软件所软件工程专业。目前主要负责 gpcopy 的研发工作。此前参与了 gpkakfa 的研发及 Postgres Merge 工作。


分享到:


相關文章: