2

我正在尝试用 Java 开发一段代码,它将能够处理 JDBC 驱动程序从 SQL 数据库中获取的大量数据,然后持久化回 DB。

我想创建一个包含一个读取器线程、一个写入器线程和可定制数量的工作线程处理数据的管理器。读取器线程会将数据读取到 DTO 并将它们传递到标有“准备处理”的队列。工作线程将处理 DTO 并将处理过的对象放入另一个标记为“准备好持久化”的队列中。编写器线程会将数据持久化回数据库。这种方法是最优的吗?或者我应该允许更多的读者来获取数据?Java中是否有任何现成的库可以做我不知道的这种事情?

4

5 回答 5

3

您提出的方法是否最优,关键取决于处理数据的成本与从数据库获取数据并将结果写回数据库的成本。如果处理相对昂贵,这可能会很好;如果不是,您可能会引入相当多的复杂性而没有什么好处(您仍然会获得管道并行性,这可能对整体吞吐量很重要,也可能不重要。)

唯一可以确定的方法是分别对三个阶段进行基准测试,然后确定最佳设计。

如果多线程方法是可行的方法,那么您的带有两个队列的设计听起来很合理。您可能要考虑的另一件事是对每个队列的大小进行限制。

于 2010-12-08T22:31:28.777 回答
2

我听到了我过去的回声,我想提供一种不同的方法,以防你重复我的错误。它可能适用于您的情况,也可能不适用于您的情况。

您写道,您需要从数据库中提取大量数据,然后持久化回数据库。

是否可以将您需要使用的任何外部数据临时插入到数据库中,并在数据库内执行所有处理?这将提供以下优点:

  1. 它消除了提取大量数据的需要
  2. 它消除了持久化大量数据的需要
  3. 它支持基于集合的处理(优于程序)
  4. 如果您的数据库支持它,您可以使用并行执行
  5. 它为您提供了一个框架(表和 SQL)来报告您在此过程中遇到的任何错误。

举个例子。很久以前,我实现了一个 (java) 程序,其目的是将购买、付款和相关的客户数据从文件加载到中央数据库中。那时(我深感遗憾),我设计了负载来处理事务,并为每条数据执行几次数据库查找(sql),最后将多次插入到适当的表中。自然,一旦数量增加,这不会扩展。

然后我又犯了一个错误。我认为问题出在数据库上(因为我听说SELECT 很慢),所以我决定从数据库中提取所有数据并用 Java 进行所有处理。然后最后将所有数据持久化回数据库。我用回调机制实现了各种层来轻松扩展加载过程,但我就是无法让它表现良好。

看着后视镜,我应该做的是在一个表中临时插入(可笑的少量)100,000 行,然后从那里处理它们。如果我充分发挥我掌握的所有技术的力量,需要将近半天的时间来处理最多只需要几分钟。

于 2010-12-09T08:51:50.703 回答
1

您正在描述编写类似于 Spring Batch 提供的功能的东西。如果我是你,我会检查一下。我很幸运地进行了类似于您所描述的使用它的操作。提供了并行和多线程处理,以及几个不同的数据库读取器/写入器和一大堆其他东西。

于 2010-12-09T05:40:55.907 回答
1

使用显式队列的替代方法是拥有一个 ExecutorService 并向其添加任务。这样,您就可以让 Java 管理线程池。

于 2010-12-08T23:06:21.637 回答
1

使用 Spring Batch!这正是你所需要的

于 2011-06-17T07:41:41.447 回答