在Redis上写入的三叉戟或Storm拓扑

时间:2014-02-24 09:54:41

标签: redis apache-storm trident

我遇到拓扑问题。我试着解释工作流程...... 我有一个源每2分钟发出大约500k元组,这些元组必须由一个喷口读取,并像一个对象一样繁琐地处理(我认为是三叉戟中的批处理)。 之后,一个bolt / function /还有什么?...必须附加一个时间戳并将元组保存到Redis中。

我尝试使用一个函数实现Trident拓扑,该函数使用Jedis对象(Redis库for Java)将所有元组保存到Redis中,但是当我部署时,我会在此对象上收到NotSerializable异常。

我的问题是。如何实现一个在Redis上写这批元组的函数?在网上阅读我找不到任何从函数写入Redis的示例或在Trident中使用State对象的任何示例(可能我必须使用它...)

我的简单拓扑:

TridentTopology topology = new TridentTopology();
topology.newStream("myStream", new mySpout()).each(new Fields("field1", "field2"), new myFunction("redis_ip", "6379"));

提前致谢

2 个答案:

答案 0 :(得分:7)

(由于与Redis相关的具体问题似乎在其他评论中得到解决,因此回复一般状态)

当我们记住Storm从分布式(或“分区”)数据源(通过Storm“spouts”)读取时,Storm中的DB更新概念变得更加清晰,并行处理多个节点上的数据流,可选择执行计算这些数据流(称为“聚合”)并将结果保存到分布式数据存储(称为“状态”)。聚合是一个非常宽泛的术语,仅仅意味着“计算内容”:例如,计算流上的最小值在Storm中看作是先前已知最小值的聚合,其中当前在集群的某个节点中处理了新值。

考虑到聚合和分区的概念,我们可以看一下Storm中的两个主要原语,它们允许在一个状态中保存一些东西:partitionPersist和persistentAggregate,第一个在每个群集节点的级别运行而没有与其他分区协调,感觉有点像通过DAO与DB通信,而第二个涉及“重新分区”元组(即通过集群重新分配它们,通常沿着某些组逻辑),进行一些计算(读取/保存到DB之前的“聚合”)感觉有点像与HashMap而不是DB交谈(在这种情况下Storm会将DB称为“MapState”,如果只有一个键,则称为“Snapshot”)地图)。

要记住的另一件事是Storm的恰好一次语义不能通过一次处理每个元组来实现:这太脆弱了,因为每个可能有几个读/写操作在我们的拓扑中定义的元组,我们希望出于可伸缩性原因而避免两阶段提交,并且在大规模时,网络分区变得更有可能。相反,Storm通常会继续重播元组,直到他确定它们已经完全成功处理至少一次。这与状态更新的重要关系是Storm给我们原始(OpaqueMap)允许幂等状态更新,以便这些重放不会破坏先前存储的数据。例如,如果我们总结数字[1,2,3,4,5],那么保存在DB中的结果将始终为15,即使它们在“sum”操作中被重放和处理多次,因为有些暂时失败。 OpaqueMap对用于在DB中保存数据的格式有轻微影响。请注意,只有当我们告诉Storm这样做时,才会出现那些重放和不透明逻辑,但我们通常会这样做。

如果您有兴趣阅读更多内容,我在这里发布了2篇博客文章。

http://svendvanderveken.wordpress.com/2013/07/30/scalable-real-time-state-update-with-storm/

http://svendvanderveken.wordpress.com/2014/02/05/error-handling-in-storm-trident-topologies/

最后一件事:正如上面重播的内容所示,Storm本质上是一种非常异步的机制:我们通常有一些数据生成器在排队系统中发布事件(例如,Kafka或0MQ)和Storm读取那里。因此,在问题中建议的风暴内分配时间戳可能会或可能不会产生预期效果:此时间戳将反映“最近成功处理时间”,而不是数据提取时间,当然它不会相同在重播元组的情况下。

答案 1 :(得分:1)

你有没有试过redis的三叉戟状态? github上有一个代码已经完成了: https://github.com/kstyrc/trident-redis

如果这回答了你的问题,请告诉我。