Storm Trident:如何使用IPartitionedTridentSpout?

时间:2014-02-07 15:01:52

标签: java apache-storm

在我们的系统中,我们有多个数据生成器在共享文件系统中创建文件内容,并在文件名中指示DataSourceId。需要有一个公平的调度机制来读取所有源生成的文件,解析,展平和放大。丰富(使用参考数据)文件中的数据记录,批量化丰富的记录并写入数据库。

我使用IPartitionedTridentSpout。拓扑看起来像这样:

TransactionalTridentEsrSpout spout
    = new TransactionalTridentEsrSpout(NUM_OF_PARTITIONS);

TridentTopology topology = new TridentTopology();
topology.newStream("FileHandlerSpout", spout)
         .each(new Fields("filename", "esr"), new Utils.PrintFilter())
         .parallelismHint(NUM_OF_PARTITIONS)
         .shuffle()
         .each(new Fields("filename", "record"), new RecordFlattenerAndEnricher(), new elds("record-enriched"))
         .each(new Fields("filename", "record-enriched"), new Utils.PrintFilter())
         .project(new Fields(record-enriched")) // pass only required 
         .parallelismHint(PARALLELISM_HINT_FOR_ESR_FLATTENER_ENRICHER)
         .shuffle()
         .aggregate(new Fields("record-enriched"), new BlockWriterToDb(), new Fields("something"))
         .each(new Fields("something"), new Utils.PrintFilter())
         .parallelismHint(PARALLELISM_HINT_FOR_GP_WRITER);

由于数据文件非常大(通常是100万条记录),我会阅读小批量的10K记录。对于transactionId生成的每个Coordinator,我的Emitter会在其分区中发出当前/下一个文件的下一个10K记录。最后的BlockWriter会将丰富的记录聚合到缓冲区中,并在“完整”方法调用中将缓冲区写入DB。

拓扑工作正常,但我有以下问题:

parallelismHint的{​​{1}}影响ParttionedTridentSpout的数量,设置为分区数。接下来的两个图层EmittersparallelismHintFlattenerAndEnricher)需要设置为更高的值,因为我们还有很多工作要做。由于此处不需要BlockWriterToDb,因此我在此处的所有阶段之间使用groupBy。当特定的下游螺栓死亡时,Trident应该使用适当的旧元数据调用shuffle(),要求它重新发射。但是,由于发生了混乱,作为一个Emitter的一部分发射的特定记录将落在多个下游螺栓中。那么,Trident如何调用适当的发射器进行重新发射,以便重新发射完全相同的记录。即使Trident调用适当的发射器,Emitter也会重新发出整个10K批次,其中一些记录只是失败了。这整个序列是如何由Storm处理的,我们如何在这里设计应用程序逻辑来处理完全一次语义的容错。

1 个答案:

答案 0 :(得分:0)

使用Trident时,整个批次成功,或整个批次失败。 当批次失败时,喷口应该(自动)重放整个批次,并且您将无法在发出时选择其记录。

要获得完全一次的语义,您的下游逻辑/数据库更新应该忽略重放的项目(跟踪成功更新的项目的批次ID),或者是幂等的。