我正在尝试用Java开发一段代码,它能够处理来自SQL数据库的JDBC驱动程序提取的大量数据,然后再保存回DB。
我想过创建一个包含一个读者线程,一个编写器线程和可自定义数量的工作线程处理数据的管理器。读者线程将数据读取到DTO并将它们传递给标记为“准备处理”的队列。工作线程将处理DTO并将处理过的对象放到标记为“准备好持久性”的另一个队列中。编写器线程会将数据保留回DB。这种方法是否最佳?或许我应该允许更多读者获取数据? Java中是否存在用于执行此类我不知道的事情的现成库?
答案 0 :(得分:3)
您提出的方法是否最佳取决于处理数据的成本与从数据库获取数据以及将结果写回数据库的成本有多大。如果处理相对昂贵,这可能会很好;如果不是这样,您可能会引入相当大的复杂性而几乎没有任何好处(您仍然会获得管道并行性,这可能会对整体吞吐量产生影响,也可能不会产生重大影响。)
唯一可以确定的方法是分别对三个阶段进行基准测试,然后确定优化设计。
如果要采用多线程方法,那么使用两个队列的设计听起来很合理。您可能需要考虑的另一件事是限制每个队列的大小。
答案 1 :(得分:2)
我听到过去的回声,我想提供一种不同的方法,以防万一你要重复我的错误。它可能适用于您的情况,也可能不适用。
您写道,您需要从数据库中提取大量数据,然后再保留回数据库。
是否可以将您需要使用的任何外部数据临时插入数据库,并在数据库中执行所有处理?这将提供以下优势:
举个例子。很久以前我实现了一个(java)程序,其目的是将文件中的购买,支付和相关客户数据加载到中央数据库中。那时(我深感遗憾),我设计了负载来逐个处理事务,对于每个数据,执行几个数据库查找(sql),最后在适当的表中插入一些。当然,一旦体积增加,这种情况就不会扩大。
然后我又犯了一个错误。我认为这是问题所在的数据库(因为我听说 SELECT的速度很慢),所以我决定从数据库中提取所有数据并用Java进行所有处理。然后最终将所有数据保留到数据库中。我使用回调机制实现了各种各样的层,以便轻松扩展加载过程,但我无法让它表现良好。在后视镜中看,我应该做的是将(可笑的少量)100,000行临时插入一张桌子,并从那里处理它们。如果我发挥了我所掌握的所有技术的优势,那么花了将近半天的时间进行处理最多只需要几分钟。
答案 2 :(得分:1)
使用显式队列的另一种方法是使用ExecutorService并向其添加任务。这样,您就可以让Java管理器成为线程池。
答案 3 :(得分:1)
您正在描述类似于Spring Batch提供的功能。如果我是你,我会检查一下。我很幸运做了类似你用它描述的操作。提供并行和多线程处理,以及几个不同的数据库读/写器和其他一些东西。
答案 4 :(得分:1)
使用Spring Batch!这正是你所需要的