我正在设计一个程序,该程序需要从数据存储区获取结果并将这些结果发布到另一个系统。我正在获取的数据由 UUID 引用,并且有其他文档通过 UUID 链接到它。我将发布大量文档(>100K 文档),所以我想同时进行。我正在考虑以下设计:
从数据存储中获取文档列表。每个文件都有:
docId (UUID)
docData (json doc)
type1 (UUID)
type1Data (json)
type2 (UUUID)
type2Data (json)
list<UUID> type3Ids
list of type3 data (json)
我从第一次通话中获得的唯一数据是 docId。我正在考虑将这些文档放入队列中,并让一组工作人员(获取程序)将相关调用返回到数据存储区以检索数据。
retrieve the docData from datastore, fill in the type1, type2 and type3 UUIDS
do a batch get to retrieve all the type1, typ2 and type3 docs
Push the results into another queue for posting to other system
第二组工作人员(海报)将从第二个队列中读取每个文档并将结果发布到第二个系统。
我有一个问题,我应该创建 1 个 FixedThreadPool(size X) 还是两个 FixedThreadPool(size X/2)?如果第一个队列中有很多作业,导致第二个队列在第一个队列为空之前无法启动,是否存在饥饿的危险?
fetcher 将通过网络联合与数据库对话,他们似乎更受 IO 的约束而不是 CPU 的约束。发帖人也将进行网络调用,但他们位于与我的代码运行所在的同一 VPC 中的云中,因此他们的距离相当近。
最佳答案
阻塞队列
这是一个很正常的模式。
如果您有两个不同的工作要做,请使用两个不同的线程池并使其大小可配置,以便您可以根据需要调整它们的大小/在部署服务器上测试不同的值。
通常使用具有有限大小(例如,任意示例为 1000 个元素)的阻塞队列(Java 5 及更高版本中内置的 BlockingQueue
)。
阻塞队列是thread-safe ,所以第一个线程池中的所有内容都尽可能快地写入它,第二个线程池中的所有内容都尽可能快地读取。如果队列已满,写入只会阻塞,如果队列为空,读取只会阻塞 - 非常简单。
您可以调整线程数并重复运行以缩小每个池的最佳配置大小。
关于使用 FixedThreadPool(s) 和队列的 Java 设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53822908/