Skip to content

Latest commit

 

History

History
177 lines (118 loc) · 15.1 KB

Readme.md

File metadata and controls

177 lines (118 loc) · 15.1 KB

竞赛题目

DTS是阿里云自研的数据传输服务,专注解决RDBMS、NoSQL、OLAP等数据源间的数据传输问题,集数据迁移/订阅/同步于一体,帮助用户构建安全、可扩展、高可用的数据架构。DTS为阿里巴巴内部和阿里云用户提供了高效的数据传输通道,通过技术的革新,不断提升海量数据迁移性能和稳定性。英特尔® 傲腾™ 数据中心级持久内存重新定义了传统的架构在内存密集型工作模式,具有突破性的性能水平,同时具有持久化能力。 本题将DTS海量数据迁移技术构建于神龙非易失性内存增强型裸金属实例和Aliyun Linux操作系统之上,探索新介质和新软件系统上极致的持久化和性能。参赛者在充分认知AEP硬件特质特性的情况下设计最优的数据结构,实现海量数据的高效上云。 竞赛题目为海量数据高效上云,设计并实现程序将数据从本地传输到云上。数据存储在多个本地文件内作为输入,输出为处理好的数据,而参赛者需要实现输入到输出之间的程序。复赛从难度上高于初赛,同时输出数据到关系型数据库。

赛题说明

数据库中数据高效迁移是一个核心技术,它在阿里巴巴内部的异地多活建站、扩/缩容,以及阿里云用户的搬站、国产化场景中都有着非常重要的应用。其主要处理的问题包括存量数据高效迁移、增量数据依赖解决和高效写入。 本题以数据高效迁移这个场景切入,实现一个具备海量数据迁移能力的程序,支持存量和增量数据迁移,具备一定的鲁棒性,同时拥有良好的性能。

初赛赛题说明

初赛实现海量数据批量上云,主要解决存量数据迁移的问题。迁移程序从本地多个文件中读取待迁移数据,进行运算处理后,写入到目标文件。本地多个文件中包括多张表的数据,数据以行(row)为基本单位,分布在文件内。单行数据间可能会存在重复(及主键或唯一键相同的记录),需要保留出现时间最靠后的数据。单行数据可能需要进行清洗转换。数据规模控制在5亿量级内。

迁移程序的输入:赛题的输入包括元数据目录和数据目录。其中元数据目录存储表结构信息,而数据目录存储待处理的数据文件。元数据目录中的"schema.info"文件对待迁移数据的类型进行了描述。其描述方法如下示列所示,其中"<"和">"内为具体信息:

[DATABASE] <数据库名> [TABLE] <表名>
COLUMN NUMBER <列总数>
{"Name":"<列名>","Ordinal":<列位置,1开始>,"Unsigned":<是否是无符号>,"CharSet":<字符集>,"ColumnDef":"<列类型>","Length":<列长度>,"Precision":<列精度>,"Scale":<列范围>}
INDEX NUMBER <索引数>
{"IndexName":"<索引名称>","IndexCols":[<索引列>...],"Primary":<是否是主键索引>,"Unique":<是否是唯一索引>}
PRIMARY KEY NUMBER <主键索引数>
{"IndexName":"<索引名称>","IndexCols":[<索引列>...]}

这里的关键信息包括库、表、列名,列类型,主键,唯一键等。每种数据类型所能表示的数据和精度是不同的,具体可能参考MySQL的数据类型定义:https://dev.mysql.com/doc/refman/8.0/en/data-types.html 。 数据目录存储待处理的数据,形如"./source_file_dir/"。在这个目录下,存储着多个数据文件。每个数据文件以"tianchi_dts_source_data_"为前缀,后面为对应的文件序号。如"tianchi_dts_source_data_0"、"tianchi_dts_source_data_1"等。这些文件内存储着待迁移的数据。文件内的数据组织格式如下,"<"和">"内为具体信息:

<操作类型>\t<数据库名>\t<表名>\t<列1的值>\t<列N的值>\n
<操作类型>\t<数据库名>\t<表名>\t<列1的值>\t<列N的值>\n

可见,数据文件内以行进行组织。每行的第1列操作类型,可选值为"I/B/A/D"。其中"I"为数据插入,"B"为数据更新的前镜像(即更新操作发生前的状态),"A"为数据更新的后镜像(即为数据更新操作发生后的状态),"D"为删除数据。第2列库名,第3列为表名,第4列及其余各列为具体列数据。各列数据间使用"\t"分隔。对于指定库表,列值出现的顺序为其元数据文件中定义的列先后顺序。每行数据间使用"\n"分隔。

迁移程序的输出:将各输入文件读取和处理后,输出到一个给定目录下,将所属同一张表的数据输出到以表名命名的文件内,并且要求按照主键增序排列。输出文件内的数据格式与输入文件类似,只是去除了冗余信息:

<列1的值>\t<列N的值>\n

处理程序除了实现输入数据的读取、分类、按照PK/UK列去重合并、定序输出外,还要实现简单的数据清洗逻辑。这里包括如下4类清洗操作:

  • 非法整数数值。如定义为int的列值出现了非法字符,我们统一将其处理为"0"值;比如表item表,i_price字段类型为decimal(5,2),出现了SQ字符串,则认为非法列值;
  • 超长浮点数精度。如定义为decimal(3, 2)的列值中出现了小数点后3位,我们对其进行4舍5入;比如order_line表,ol_amount字段出现值5.346,则需要清洗为5.35;
  • 非法时间数据。如定义为datetime的列值中出现了非法的日期,我们将其统一成"2020-04-01 00:00:00.0";非法时间数据一般包括大小写字母,比如:2021-04-1a 15:41:55.0;
  • 超长字符长度。如定义为varchar(16)的列值出现了17个字符,此时我们按照此列的最大长度对列值截断(注意不考虑"\0"因素)。比如warehouse表w_state字段类型为char(2),出现了"aaaaaaa"长度值,则需要截断处理"aa";

注意:

  • 热身赛给出了表结构信息schema.info,待处理信息文件tianchi_dts_source_data_,正确结果:tianchi_dts_expect_data_,选手可在本地调试通过提交。

  • 选手提交程序,sink_file_dir文件夹默认不存在,需要自行创建,输出文件格式为tianchi_dts_sink_data_<table_name>,不带任何后缀。

  • 输出输出文件路径和格式:1)schema.info文件:/<input_dir>/schema_info_dir/schema.info;2)输入数据:/<input_dir>/source_file_dir/tianchi_dts_source_data_*;3)输出数据:/<output_dir>/sink_file_dir/tianchi_dts_sink_data_*,其中input_dir,output_dir是传递给start.sh的父目录;4)expect_file_dir文件夹是判定结果文件夹,用于选手调试使用。

  • 该工程提供了热身赛测试程序(expample文件夹)和运行结果判定程序(judge文件夹),该程序无法完成初赛结果判定,需要用户自行优化。

  • 具体表结构见:https://github.com/Percona-Lab/tpcc-mysql/blob/master/create_table.sql

复赛赛题说明

复赛实现海量数据实时上云,主要解决增量数据迁移的问题。迁移程序从本地多个文件中读取待迁移增量数据,进行运算处理后,写入到目标数据库。

迁移程序的输入:复赛的输入本地文件中的数据格式与初赛一致,单行数据协带操作类型标识(I/B/A/D)。数据集由多个文件构成,文件内存储单行数据。单行数据间存在时序性,按照数据文件编号、以及出现在同文件内的先后顺序指定。数据规模控制在5亿量级内。输入数据格式、输出数据格式、以及数据清洗逻辑参见上文描述。数据依赖关系说明如下:

I\tTEST_DB\tTEST_TB\t1\n
B\tTEST_DB\tTEST_TB\t1\n
A\tTEST_DB\tTEST_TB\t2\n

参见上面3条数据,它们是针对TEST_DB下的TEST_TB进行的操作,其逻辑行为是:先插入一条数据,其值为1;随后将其值更新为2。更新操作对应两行数据,对应我们示例中的2、3行。第2行的操作符为B,表示其在更新操作发生前的数据状态;第3行的操作符为A,表示其在更新操作发生后的数据状态。这3条数据即存在依赖关系,在处理时必须依照其顺序进行。

迁移程序的输出:复赛的输出是到目标MySQL数据库中,其表结构会预先建好。

处理程序除了实现输入数据的读取、分类、按照PK/UK列去重合并、定序输出外,还要实现简单的数据清洗逻辑。这里包括如下4类清洗操作:

  • 非法整数数值。如定义为int的列值出现了非法字符,我们统一将其处理为"0"值;
  • 超长浮点数精度。如定义为decimal(3, 2)的列值中出现了小数点后3位,我们对其进行4舍5入;
  • 非法时间数据。如定义为datetime的列值中出现了非法的日期,我们将其统一成"2020-04-01 00:00:00.0";
  • 超长字符长度。如定义为varchar(16)的列值出现了17个字符,此时我们按照此列的最大长度对列值截断(注意不考虑"\0"因素)。

评测逻辑

本次比赛的提交评测,在主办方提供的评测平台上进行。 选手将代码压缩成zip包提交到天池上,评测程序会下载选手的提交并解压到比赛机器上,然后调用选手代码文件中固定的入口程序(start.sh)运行选手的代码。 在调用入口程序时,会把必要的信息作为入参输入。请注意:调用程序时的初始目录可能不是选手代码目录,传进来的目录参数为绝对路径,其格式如下所示,包括存储着待迁移数据的文件目录、迁移目标文件目录(初赛)、迁移目标数据库(复赛):

./start.sh --input_dir <初赛待处理数据目录> --output_dir <初赛输出数据目录> --output_db_url <复赛输出数据库地址> --output_db_user <复赛输出数据库账号> --output_db_passwd <复赛输出数据库账号密码>

启动选手迁移程序后,最终统计迁移程序启动到退出所用的时间,按照使用时间的从低到高排名。 评测分为两个阶段,正确性评测和(初/复赛)性能评测:

1)程序正确性评测,验证迁移程序的正确性(复赛会增加持久化能力的验证)。正确性验证部分的耗时不计入运行时间的统计。

2)初赛性能评测,待迁移数据使用标准TPCC(具体表结构见:https://github.com/Percona-Lab/tpcc-mysql/blob/master/create_table.sql)生成,数据操作类型均为"I",即为插入类型。数据集中存在重复数据,存在需要进行清洗的数据。在选手迁移程序正常退出(exit code为0)后,这里我们认定入口程序(start.sh)运行结束即为迁移完毕,评测程序会对选手迁移程序耗时统计,并在正确性校验通过后,将其程序耗时作为打榜时间。

3)复赛性能评测,待迁移数据在标准TPCC的基础上,增加实时的I/U/D操作,这一部分数据通过修改TPCC而获取到。数据集中存在重复数据,存在需要进行清洗的数据。在选手程序过行过程中,评测程序会对选手程序进行至少3次的kill操作。在选手迁移程序正常退出(exit code为0)后,评测程序结束对选手迁移程序耗时统计,并在正确性校验通过后,将其程序耗时作为打榜时间。

赛题规则

1.语言限定

无限制

2.程序目标

实现海量数据迁移上云。

3.参赛方法说明

1)在天池平台完成报名流程;

2)按照示例代码工程的约束完成迁移程序的编写;

3)在天池提交成绩的入口,提交自己的代码;

4)等待评测结果

4.排名规则

在正确性验证通过的情况下,对性能评测阶段整体计时,根据总用时从低到高进行排名(用时越短排名越靠前)。

5.作弊说明

如果发现有作弊行为,比如通过hack评测程序,绕过了必须的评测逻辑等行为,则程序无效,且取消参赛资格。

选手程序评测环境说明

选手迁移程序运行在一个容器环境内,此容器在alpine:3.13的基础版本上定制而成,在容器内部包含C/C++/Java/Bash/Python/Go等运行环境。此容器的Docker Image会尽快开放给选手下载。

选手迁移程序评测环境中存在两块PMEM内存供使用,以fsdax方式开放给选手。挂载目录为/input和/output目录,其中/input目录为只读,/output目录为可读写。待迁移数据会存储在/input目录下,整理好的数据或是临时数据可存储于/output目录下,而/output同时也是初赛中的输出数据目录。

初、复赛选手可使用的CPU资源为16C,DRAM为8G,存储资源一块已挂载到/output目录的,大小为512GB。

由于容器本身的架构限制,使用virtio-pmem方式使用PMEM设备。而这一方式会和真实PMEM设备有所不同:即对于pmem_map_file、pmem_is_pmem等函数,会显示其为fake pmem地址空间,但在读写性能上,却和真实PMEM设备一致。同时,相对于真实PMEM需要使用pmem_persist保证持久化,在容器内需要使用pmem_msync进行持久化。

测试数据

初赛测试数据

测试环境

为了便于选手调试程序,我们开放了和比赛选手运行环境一致的Docker Image供选手测试,使用如下命令运行镜像:

docker pull rv2001/tianchi-contest:public1.0

docker run -it rv2001/tianchi-contest:public1.0 /bin/bash

参考资料

Intel 傲腾持久化内存介绍

傲腾持久化内存(AEP)工作模式

PMEM IO官网

如何模拟PMEM

PMEM编程指北

PMDK示例程序

评测环境使用PMEM

JAVA使用PMEMKV

DTS数据迁移技术原理

FAQ

  • 本工程中的example代码靠谱么?

不靠谱,example中的代码只起到示例作用,可能连正确性验证都过不了,example只是一个example。甚至还有bug。

  • 能在本地进行持久化验证测试吗?

本地测试与评测机不一致通常是由于本地无法保证及时将数据刷回磁盘,如果需要在本地进行测试,需要自己在结束前手动调用pmem_msync。

  • 如何输出Log

评测程序会将标准输入、输出中的数据放置到Log文件中,并在程序结束后上传Log文件到OSS。选手可以在评估结果信息中获取到本程序Log文件的访问地址。

  • 评测失败是否反馈具体原因?例如OOM,Core等。

初赛不反馈程序意外退出的原因,仅反馈评测失败。除此以外,如果程序超出时间限制被杀死,会在log底部注明: Time Limit Error。

  • libpmem需要自己包含在工程吗,还是测试环境已经有

已有。

  • 复赛一定要依赖libpmem或PMDK吗?

是的。