如何在迭代一个非常大的列表(> 100 000)时处理崩溃

时间:2011-09-08 17:25:04

标签: java-ee architecture iteration batch-processing recovery

我们的系统正在处理超过10万名订阅者。每周,另一个外部应用程序构建包含用户的财务信息的特殊文件,其中包含> 100 000行。 我们的应用程序应解析它并处理每条记录(在我们的例子中发送短信/毫秒/电子邮件)。当然,这些操作非常耗时,因此我们通过JMS异步执行这些操作。

但首先我们需要将所有记录放入队列。性能测试表明它需要大约30-40分钟甚至更长时间。 基本上我们将遍历整个10万个项目列表并逐个将消息放入JMS队列。让我们假设在第50,000次迭代系统崩溃。 如果我们不关心恢复逻辑,下半部分用户将不会收到任何消息。 如果我们只是重新启动该过程,前半部分用户将收到2条相同的短信。

所以我们需要在这里有一些逻辑能够以最小的性能影响正确地恢复迭代过程。 目前,我想到了以下解决方案:

  1. 在某些持久存储中保存迭代计数 - 可能更合适,与文件中的顺序相同

  2. 将进程状态序列化为某个持久存储 - 性能不佳?

  3. 保存整个列表并更新状态 - 性能不佳,无用的数据? 对于我的所有人,状态数据在每次迭代时都会更新到持久存储。
  4. 选择哪一个? 那里持久存储的最佳选择是什么(简单,快速,可靠)?

    有人知道在这种情况下通常应用的任何解决方案/模式吗?或者你已经遇到了同样的问题,可以建议你自己的方法? 任何帮助将不胜感激!提前谢谢!

3 个答案:

答案 0 :(得分:1)

我强烈建议您使用Spring batch来专门满足您的需求。它应该没有问题处理100,000多行,让你能够重新启动(从失败的角度),重试等。

答案 1 :(得分:0)

您的JMS提供商是否有交易?如果是这样,您可以在一个JMS事务中运行整个过程。在发送它的事务提交之前,代理不允许消费者处理任何消息。因此,如果导入过程随时崩溃,代理将自动回滚到目前为止发送的所有消息。

然后,您可以从头开始重新启动该过程。

BTW 30-40分钟向JMS队列发送100K消息(大约50 msgs / s)?我只是使用ActiveMQ 5.5.0网页界面进行了快速测试,发送100K消息大约需要1-2分钟......

答案 2 :(得分:0)

因为您正在对记录进行处理(一条记录不关心下一个或上一个记录是否已成功发送)我认为如果出现错误或担心重新启动,则无需停止刮;我的看法是处理你能做的所有记录,然后弄清楚如何修复/重新处理失败。

您唯一想要注意的是某种系统性错误:如果前50个记录因同样的原因而失败,那么尝试处理100K记录是没有意义的 - 例如网络故障。

如果您想要返回并重新运行故障,我倾向于复制要处理的数据快照并向其添加处理数据(发送成功@dd-mm-yy,hh :mm:ss,Failed,等等)。或者,只需将所有故障记录到标准日志记录系统中。