Talend并行化和Java范围

时间:2016-01-13 21:28:21

标签: java mongodb talend

我正在创建一项工作,从关系数据为mongoDB创建复杂的多级文档。

我从Oracle中读到了“产品”记录。

我有一个tJavaRow,我使用mongoDB API使用产品详细信息创建产品文档(BasicDBObject)。我将此文档存储在全局地图中(称为'product_doc')..因为我需要嵌入稍后在子作业中的子文档。

我使用tFlowToIterate将product_id存储在globalMap中。

然后我有另一个Oracle输入,它使用全局映射中的product_id作为sql中的参数,因此获得产品关系的很多部分(称为'product_orders')。

我构建了一个'product_order'文档的java列表,并将List写入globalMap,我们称之为'product_orders'。

然后我将'product_documents'列表作为子文档插入到tJava组件中的'product'文档中。我将'product'写入mongoDB,然后转到Oracle的下一个产品行。

它比这更复杂,创建一个5级层次结构......但这是基本的想法 - 但它需要3个小时才能运行。

所以,我想将作业设置为并行运行,因此Oracle的每个产品行都会被发送到一个新的线程...... Round Robin风格。

但是,我对globalMap有很大的依赖性来存储对象以供以后在流程中使用....我知道线程会相互踩踏。我假设每个线程在子作业中保持相同的变量范围......

我认为我可以在globalMap“tCollector_1_THREAD_ID”中使用全局变量识别thread_id。

所以当我将文档/对象添加到globalMap中时,我考虑过这样做。

globalMap.put(“product_doc_”+ globalMap.get(“ tCollector_1_THREAD_ID“))

因此我在globalMap中放置的所有内容都是特定于线程的并且已标记...但我不知道如何填充tCollector_1_THREAD_ID,如果它在globalMap中,那么每个线程当然也可以践踏这个值吗?

它不起作用......我得到了大量的Null Errors。

所以我想我的问题是关于变量范围和在并行数据流中使用tJavaRow组件时使用globalMap,当你需要在每个线程中维护引用时。

----更新------

为清楚起见,如果您查看此页面,它表明您可以从变量tCollector_1_Thread_ID获取线程ID。 BUt它从globalMap获取该变量。

当然,globalMap是一个全局变量,那么多个线程如何不是一直都在改变这个全局变量并相互干扰呢?

https://help.talend.com//pages/viewpage.action?pageId=265114338

1 个答案:

答案 0 :(得分:0)

以下是我成功用于并行执行的一些方法:

如果可能,创建另一个并行运行的作业,这有助于理解任务: Using Iterate links

在此示例中,我使用“使用或注册共享Db连接”功能,因此我重新使用了我的连接。 tJavaFlex只包含一个简单的try {} catch块,因此我处理/隐藏错误。 GpOutput使用在线程外部创建的连接。

enter image description here

我更喜欢这种方法,我创建一个单独的作业并使用上下文参数将信息传递给作业。 enter image description here

在这里你可以看到如何使用globalMap。

我发现talend中的tPartition / Departitioner非常难以使用。我更喜欢使用更多受控方式来处理并行执行。例如Loop将工作负载拆分为20个并行线程。

  " WHERE mod(num,20) = " + context.i "