【发布时间】:2018-03-09 19:51:06
【问题描述】:
在系统上工作以支持并行的多个数据库查询。考虑到要从每个查询中查询大量数据,要求将每个数据库查询与其他查询分开。这意味着,一个数据库/表上的负载不应影响其他表查询。我使用 ExecutorService 在 Java 中开发了一个解决方案。每个数据库使用一个 ExecutorService(固定大小,1 个线程)。我维护一个数据库名称到 ExecutorService 的映射,并在接收查询请求时将调用定向到相应的执行程序服务。考虑到可以并行查询一百个数据库,不确定 ExecutorService 是否是正确的选择......!我做了一些估值,初步结果看起来还不错。我在使用此解决方案时遇到的一个挑战是,当我动态创建 ExecutorServices 时,我很难在应用程序停止时优雅地关闭它们。
解决此问题的其他方法是维护一个全局(即跨所有数据库)查询工作线程池,并将它们随机重用于传入请求。但是,这并不能保证所有数据库查询都具有同等的优先级。
DatasetFactory.java
public class DataSetExecutorFactory {
private static Map<String, DataSetExecutor> executorMap = Collections.synchronizedMap(new HashMap<String, DataSetExecutor>());
public static DataSetExecutor getDataSetExecutor(String dbName){
DataSetExecutor executor = null;
executor = executorMap.get(dbName);
if(executor == null){
executor = new DataSetExecutor(dbName);
executorMap.put(dbName, executor);
}
return executor;
}
}
}
DataSetExecutor.java
public class DataSetExecutor {
private ExecutorService executor = Executors.newFixedThreadPool(1);
public List<Map<String, Object>> execQuery(String collecName, Map<String, Object> queryParams){
//Construct Query job.
//QueryWorker extends 'Callable' and does the actual query to DB
QueryWorker queryWorker = new QueryWorker(Map queryParams);
Future<QueryResult> result = null;
try{
result = executor.submit(queryWorker);
}catch (Exception e){
//Catch Exception here
e.printStackTrace();
}
}
【问题讨论】:
-
你有什么问题?
-
我认为这是一个有效的解决方案,尽管如果您将所有内容推送到单线程执行器服务上,您的查询将不会在
parallel中运行。 -
为什么每个数据库都有一个执行器,而不是处理任何 queryWorker 的 1 个执行器(池中有 1 个以上的线程)?将数据源传递给 QueryWorker 以让它创建连接。
-
@PatrickMevzek 是否有替代或更好的方法来实现此用例?
-
@SamOrozco 是的,我可以在每个数据库的 Executor 服务中顺序执行查询。
标签: java concurrency