我们对“Talend作业设计模式和最佳实践”的探讨即将圆满收官,如果您尚未读过第1、2、3部分,建议先行浏览。

不过依照先前的承诺,我们接下来要继续深入了解一组Talend作业设计模式的最佳实践。首先要提醒您注意一个简单却经常被忽略的事实:Talend是一种Java代码生成器,制定开发人员指南可以强化及简化通过作业设计模式生成Java代码的过程。这貌似显而易见,事实也的确如此。但设计优秀的作业能生成干净的java代码,借助这些概念在画布上绘制是卓有成效的绝佳方式,我称之为“成功驱动型项目”。

成功驱动型Talend项目

构建Talend作业的过程可能简单直接,也可能会相当复杂。成功实施的秘诀是培养良好的习惯以及纳入必要的纪律。

从本系列开篇讨论“基本法则”起到现在,我的目标一直是促进对这些最佳实践的公开讨论,以便通过Talend实现合理而实用的作业设计模式。大多数用例将受益于原子作业设计和父/子业务流程,并且当项目包含重要的可重用代码时,可为整体成功提速。您当然要选择适合自己的路径,不过至少希望您做到一以贯之。

数据库开发生命周期 (DDLC)

要坚持不懈,也许不仅仅关乎作业设计,同样关乎数据。我们正在处理数据,对吧?大多数情况下,数据位于数据库中。试问数据库是否需要最佳实践?这是个设问句。数据模型(模式)随着时间的推移而变化,因此数据库设计必然具有生命周期,这一点不言而喻。

数据库会不断演进,开发人员需要适应这一事实。此前我们已纳入SDLC流程,因此对于数据库开发生命周期的需求并不难理解,在我看来这一点浅显易懂。对于任何环境 (DEV/TEST/PROD),数据库都需要支持:

全新安装 - 基于模式的当前版本

应用升级 - 删除/创建/更改数据库对象,升级至下个版本

数据迁移 - 发生破坏性“升级”(比如表的拆分)

了解数据库生命周期及其对作业设计的影响变得尤其重要。数据库模型的版本管理十分关键。请遵循规定的设计流程,使用图形图表来说明设计,创建“数据字典”或“词汇表”,并跟踪历史变化轨迹。与此同时,在编制数据库模型时也请考虑以下流程,这是一套更高层次的纪律,而且非常奏效。

更多作业设计最佳实践

好,下面我们来了解更多作业设计模式和最佳实践,马上满足您的需要。这些内容将进一步深挖Talend的功能,可能涉及一些常见功能,也有一些并不常用,希望您能发现它们的价值。

另外8个最佳实践:

我们大都知道,一些基本tMap组件之所以在Talend作业中得以广泛运用,是由于其具备强大的转换功能。

tMap组件最常见的用途是将数据流模式从源输入映射到目标输出,简单吧?当然!我们知道还可以合并多个源和目标模式数据流,为我们提供根据需要加入和/或拆分这些数据流的诸多机会,其中可能包含转换表达式,用来控制传入数据分散到下游的内容和方式。tMap组件中的表达式可能出现在源架构或目标架构,还可以使用在tMap组件中定义的变量来进行应用。您可以在“Talend组件参考指南”中了解如何完成所有这些操作。请记住:强大的功能即意味着要担负重要的责任。

tMap组件还有一个不容忽视的用途,即纳入与源数据流联接的查找。对于可应用至tMap组件的查找次数或查找数据的具体内容并没有物理限制,但必须合理考虑实际情况。

来看这个基本示例:有两列生成器,一个是源,另一个是查找。运行时,首先生成查找数据,然后处理源数据。

因为查找数据的联接设置为“一次加载”,所有记录都会加载至内存,然后根据源数据结果集进行处理。此默认行为提供高性能连接,并且可以非常高效。

此外,可以想见当加载数百万个查找行或数十列时,可能产生相当大的内存需求。的确有此可能。如果需要进行多次查找,每次都有数百万行数据,该怎么办?需要多少内存?当查找涉及海量记录或数百列时,请谨慎考虑。

我们来看如何权衡内存与性能。有三种可用的查找模型:

一次加载 - 将所有符合的记录读入内存

每行重新加载 - 仅对每条源记录读取符合的行

每行重新加载(缓存)- 对每条源记录读取符合的行,并将其缓存

显然,如果查找数据已加载至内存以与源连接,那么查询速度会相当快。但如果内存约束阻止大量查找数据,或者您不想加载所有查找数据(因为用例可能并不需要),请使用“每行重新加载”查找模型。请注意,想要发挥其作用,您需要了解一些技巧。

首先在tMap组件内,可将查找模式更改为“每行读取”。注意下方区域会展开,以允许输入需要执行查找的“键”。添加这些键,以便有效定义tMap组件之外可用的全局变量。

对于查找组件,请在SQL语法的“WHERE”子句中使用 (datatype)globalMap.get(“key”) 函数,以在查找数据集上应用tMap中定义的已保存键值。这样就完成了对于从源进行处理的每条记录的查找检索。

无论采用哪种方式,都可实现高效查找。

全局变量

定义和使用我们所认为的“全局变量”涉及以下几个方面。开发人员一直都在Talend作业中创建和使用这些变量,我们称之为“上下文变量”。这些有时“内置”到本地作业中,有时在“项目存储库”中作为上下文组,因而可在多个作业中重复使用。

不管怎样,这些都是“全局变量”,其值在运行时确定,并可在赋予其定义的作业中用于任何位置。每当context.varname嵌入到组件、表达式或触发器中时,您就在使用一个这样的变量。别忘了将常用变量放在“参考项目”中,以便最大限度用于其他项目。

Talend还提供tSetGlobalVar和tGlobalVarLoad 组件,可在运行时定义、存储和使用“全局变量”。tSetGlobalVar 组件会在作业中存储键值对,类似于使用“上下文变量”提供更好的控制(如错误处理)。请参考我给出的示例,其中检索到单一 MAX(date) 值,随即将其应用于后续SQL查询以筛选另一个记录集检索。

要访问全局变量,请在SQL“WHERE”子句中使用 (datatype)globalMap.get(“key”) 函数。建议熟悉此功能,体会到其强大之处之后,您很可能会经常加以使用。

tGlobalVarLoad组件为无法使用tSetGlobalVar组件的大数据作业提供类似的功能。来看我的示例,其中将计算聚合值,随即在后续读取中用于限定要返回的记录。

继续这个话题,隐藏在普通视域中的是一组“系统全局变量”,可在作业中使用,其值由组件本身确定。我们之前在本系列第1部分的错误处理最佳实践中探讨过其中的CHILD_RETURN_CODE和ERROR_MESSAGE。这些系统全局变量通常在组件执行设置其值后立即可用。因组件而异,可以使用不同的系统变量。以下列出其中一部分:

ERROR_MESSAGE / DIE_MESSAGE / WARN_MESSAGE

CHILD_RETURN_CODE / DIE_CODE / WARN_CODE / CHILD_EXCEPTION_STACK

NB_LINE / NB_LINE_OK / NB_LINE_REJECT

NB_LINE_UPDATED / NB_LINE_INSERTED / NB_LINE_DELETED

global.projectName/global.jobName(这些为系统级别;使用情况显而易见)

加载上下文

“上下文组”支持高度可重用的作业设计,但有时我们对灵活性的需求更高。例如,假设您要在外部维护上下文变量的默认值。有时将它们存储在文件甚至数据库中会更有意义。具备在外部维护相应值的能力会非常有效,甚至可以支持一些安全考虑。tContextLoad组件在此大有用武之地。

关于进行作业设计以在运行时初始化上下文变量,上面的示例给出一种简单的方法。用于加载的外部文件包含以逗号分隔的键值命名对,并且读取时将覆盖作业中已定义上下文变量的当前值。这种情况下,将加载数据库连接详细信息,以确保提供所需的连接。请注意,您可以控制某些错误处理操作,实际上这提供了能以编程方式立即退出作业的其他位置:“错误结束”,这非常少见。当然,tContextLoad组件可以轻松地使用数据库查询,我知道有些客户这么做。

利用相应的tContextDump组件,将当前上下文变量值写出到文件或数据库中,这在编制高适应性作业设计时非常有用。

使用动态模式

经常有人问我如何构建处理动态模式的作业。这么问未免意义含混,因为有多种用例涉及处理动态模式。最常见的情形是将多个表中的数据移动到另一组相应的表,可能分属不同数据库系统(例如从Oracle到MS SQL server)。创建作业来移动这些数据看似简单,但我们几乎立即可以判定:针对每个表构建作业并不切合实际。要是有数百个表怎么办?构建可以处理所有表的单一作业,难道这样不可以吗?很遗憾,Talend在这一方面确实存在局限。不过也莫沮丧,我们可以分成两个作业来实现这一点:一个用于转储数据,另一个用于加载数据。这样能接受吧?

来看我的作业示例:建立三个连接,前两个分别检索“表”和“列”的列表,第三个检索实际数据。只需通过迭代每个表,保存其中的列,我就可以使用tSetDynamicSchema组件对位置平面文件进行数据读写(转储进程)。类似作业同理,不同的是第三个连接将读取位置文件并写入目标数据存储(加载进程)。

在该场景中,开发人员必须对其主机数据库的内部工作稍有了解。大多数系统(如Oracle、MS SQL server和MySQL)都有系统表,通常称为“信息模式”,其中包含表及其列等有关数据库的对象元数据。下面的查询将从我的TAC v6.1 MySQL数据库中提取完整的表/列的列表。(我的首选SQL语法格式是否合您意?)

此数据库通常受保护,请务必使用具有相应“选择”权限的连接凭据。

请注意我使用tJavaFlex组件来迭代找到的表名称。我保存每个“表名称”并设置“控置中断”标志,然后迭代找到的每个表并检索其排序列的列表。在对列长度中的任何空值进行调整后,保存的“动态模式”即已完成。当表名称更改时,条件“IF”将检查“控制中断”标志并开始当前表的转储过程。搞定!

动态SQL组件

动态代码非常有用,Talend提供了几种实现的方法。在之前的作业设计中,我使用直接方法从数据库中检索表和列的列表。Talend实际上提供主机系统特定组件来执行相同操作。这些t{DB}TableList和t{DB}ColumnList组件(其中 {DB} 由主机组件名称替换)提供对“信息模式”元数据的直接访问,无需实际了解任何相关信息。也可使用这些组件代替之前描述的冷工作转储/加载进程,不过具体有何意义?

并非所有SQL查询都需要检索或存储数据。有时需要其他数据库操作。针对这些要求登记 t{DB}Row和t{DB}SP组件。前者可用于执行几乎任何不返回结果集的SQL查询,如“DROP TABLE”,后者则用于执行“存储过程”。

最后一项要点是t{DB}LastInsertId组件,可从数据库输出组件检索最近插入的“ID”,有时这非常有用。

另一个常见问题是,Talend是否支持CDC:“变更数据捕获”?答案是肯定的。当然,可通过“发布/订阅”机制直接与所涉及的主机数据库系统进行关联。需要注意的是,并非所有数据库系统都支持CDC。以下是Talend作业中明确的CDC支持“当前”列表:

有三种CDC模式可供选择,包括:

触发器(默认) - 使用可以跟踪插入、更新和删除的数据库主机触发器

重做/归档日志 - 仅与Oracle 11g及更早版本一起使用

XStream - 仅与Oracle 12和OCI一起使用

这三种模式中,您最有可能使用的是“触发”模式,鉴于此,我们来了解其架构:

《Talend用户指南》第11章全面探讨了有关Studio内以及与主机数据库系统协调的 CDC 进程、配置和使用。虽然在概念上非常简单,但是需要进行大量设置。应预先充分了解您的需求、CDC模式和作业设计参数,并在开发人员指南中做好记录。

建立CDC 环境后,其将提供强大的机制,使下游目标(通常是数据仓库)保持最新状态。使用Talend作业中的t{DB}CDC 组件对于自上次提取后已更改的数据进行提取。配置和实施CDC需要时间和精力,但其功能的确非常有用。

自定义组件

Talend现有调色板提供超过1,000个组件,不过您仍有众多理由自行构建。Talend开发人员常在自定义组件中封装特定功能。部分开发者已构建组件并将其产品化,另一些开发者则将组件发布于最近现代化的Talend Exchange上供免费访问。对于Talend调色板不提供的组件,在该处进行搜索可能会找到合您所需的内容。需使用“Talend Forge”帐户(不过您可能已经创建)。

首先请确保正确设置存储自定义组件的目录。从“首选项”菜单中执行此操作,并选择一个通用位置,供所有开发人员使用。单击“应用”,然后单击“确定”。

在菜单栏上找到“交换”链接,以便选择和安装组件。第一次执行此操作时,请选中“始终在后台运行”并单击“在后台运行”按钮,因为加载大量可用对象需要一些时间。从此列表中可以“查看/下载”感兴趣的对象。完成组件下载后,单击“下载的扩展”进行实际安装,以便在Studio中使用。完成后,组件将显示为“已安装”,并可从调色板使用。

组件及其相关文件安装完成后,可能不容易找到,可以查看这两个位置:

{talend}/studio/plugins/org.talend.designer.components.exchange{v}

{talend}/studio/plugins/org.talend.designer.components.localprovider{v}

如果想要自行创建自定义组件,请在Studio中切换到“组件设计器”透视图。大多数自定义组件使用“JavaJet”,这是用于针对“Eclipse IDE”封装Java代码的文件扩展名。有关“如何创建自定义组件”的教程内容精当,适合初学者。虽然该教程有点过时(2013年左右发布),但其中包含您需要掌握的基础知识。此外也可参考第三方教程(部分在以上教程中列出),比如我推荐“Talend示例:自定义组件”。您还可借助Google搜索有关创建“自定义组件”的更多信息。

作业脚本 API

通常我们使用“设计器”来编制Talend作业,然后生成底层Java代码。您有没有想过可否自动生成Talend作业?的确有一种方法。打开您的任意一项作业,画布底部有三个选项卡:DESIGNER、CODE和JOBSCRIPT。这里值得细究,您可能用过CODE选项卡来检查生成的Java代码,有没有单击过JOBSCRIPT选项卡?如果有,知道自己看到的是什么吗?我打赌多数人并不知道。该选项卡显示的是代表作业设计的脚本。下次不妨仔细看看。看到与作业设计有关的熟悉的内容了吧?没错…

那么,您说说看?好吧,我来揭晓答案。假设您在某个位置创建和维护有关作业设计的元数据,并通过创建的进程引擎来运行,生成格式正确的作业脚本,或者调整关键元素以创建作业的多个排列。这时情况会很有意思。

查看CODE>ROUTINES部分下的“Project Repository”,找到“Job Scripts”文件夹。新建一个JobScript(我命名为“test_JobScript”)。打开任何作业并复制JobScript选项卡内容,将其粘贴到JobScript文件中并保存。右键单击JobScript,然后选择“生成作业”。现在看看“Job Designs”文件夹,您会发现一项新作业。想象一下现在能做什么吧,太棒了!

好,以上就是全部内容。并不是说创建和维护Talend作业设计就没有其他最佳实践了,相信还有更多,不过可以在更广泛的社区对话中接着讨论。我们介绍的这一系列最佳实践(共32项)兼具广度和深度,将对使用Talend的成功驱动型项目有所助益。

关注更多精彩

Talend (Nasdaq: TLND) 是云集成解决方案领域的领导企业,致力于让更多正确数据更快地在业务中发挥作用。Talend Cloud为公共、私有和混合云以及本地环境中简单和复杂的数据集成任务提供单一平台,并使IT和业务团队之间的协作更加紧密。结合自助服务解决方案和涵盖从SaaS应用程序到云数据仓库的数百个预置连接器,Talend让客户可以经济高效地满足不断增长的数据量、用户及用例数量需求。