为什么使用 ParparedStatement、BoundStatement、Session.executeAsync 和 ResultSetFuture 的应用程序消耗这么高 CPU?
why a application using ParparedStatement, BoundStatement, Session.executeAsync and ResultSetFuture consuming such high CPU?
我需要在具有 3 个节点的 Cassandra(2.1.11) 集群中写入近 1000 万条记录,复制因子为 1,
我的步骤几乎与 datastax 的 Java 驱动程序如下:
String insert_query = "insert into " + keyspace + "." + tblName
+ " (a, b, c, d,"
+ "e, f, g, h, i, j,"
+ "k, l, m, n) VALUES "
+ "(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
List<ResultSetFuture> futures = new ArrayList<ResultSetFuture>();
PreparedStatement statement = session.prepare(insert_query);
BoundStatement bind = null;
int max = 5000000 or 6000000 or 7000000
for(int i = 0; i < max ; i++) {
bind = statement.bind(
id,
...
null,
null,
null
);
ResultSetFuture resultSetFuture = session.executeAsync(bind);
futures.add(resultSetFuture);
} //for
for(ResultSetFuture future : futures){
future.getUninterruptibly(15000, TimeUnit.MILLISECONDS);
}
然后,我的应用运行在16核机器下,我监控进程'CPU消耗:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
25502 pengcz 20 0 30.8g 27g 19m S 1263.7 25.8 104:28.82 java
而且我发现CPU使用率太高了(1263.7%
),而且我发现cpu使用率高了最后一次,写多了甚至写失败.
不知道是不是我的错误步骤导致了这种情况?任何建议将不胜感激!
实际上,您一次提交了 5、6 或 700 万个请求,然后等待所有请求同时完成。由于您正在构建一个包含请求数量的未来列表,因此您不仅会提交许多请求,还会使用大量内存来跟踪这些响应。我想象提交许多请求而不等待响应会产生大量 CPU 生成请求有效负载并将它们写入网络,此外还有越来越大的 GC 压力将这些未来保持在一个巨大的列表中。
你应该做的是一次只有这么多的飞行请求(也许500?),等待它们完成,然后提交下一组等等。肯定有比这更好、更优化的技术,而且这也不能很好地处理错误情况,但它应该会降低你的内存占用,并防止你用许多请求来打击 C*。这是一个可能看起来像的例子:
String insert_query = "insert into " + keyspace + "." + tblName
+ " (a, b, c, d,"
+ "e, f, g, h, i, j,"
+ "k, l, m, n) VALUES "
+ "(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
List<ResultSetFuture> futures = new ArrayList<ResultSetFuture>();
PreparedStatement statement = session.prepare(insert_query);
BoundStatement bind = null;
int max = 1000000;
for (int i = 0; i < max; i++) {
bind = statement.bind(i,
null,
null,
null
);
ResultSetFuture resultSetFuture = session.executeAsync(bind);
futures.add(resultSetFuture);
if (futures.size() % 500 == 0 || i == max - 1) {
for (ResultSetFuture future : futures) {
future.getUninterruptibly(15000, TimeUnit.MILLISECONDS);
}
futures.clear();
}
}
如需进一步指导,请查看 Asynchronous queries with the Java driver。
我需要在具有 3 个节点的 Cassandra(2.1.11) 集群中写入近 1000 万条记录,复制因子为 1, 我的步骤几乎与 datastax 的 Java 驱动程序如下:
String insert_query = "insert into " + keyspace + "." + tblName
+ " (a, b, c, d,"
+ "e, f, g, h, i, j,"
+ "k, l, m, n) VALUES "
+ "(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
List<ResultSetFuture> futures = new ArrayList<ResultSetFuture>();
PreparedStatement statement = session.prepare(insert_query);
BoundStatement bind = null;
int max = 5000000 or 6000000 or 7000000
for(int i = 0; i < max ; i++) {
bind = statement.bind(
id,
...
null,
null,
null
);
ResultSetFuture resultSetFuture = session.executeAsync(bind);
futures.add(resultSetFuture);
} //for
for(ResultSetFuture future : futures){
future.getUninterruptibly(15000, TimeUnit.MILLISECONDS);
}
然后,我的应用运行在16核机器下,我监控进程'CPU消耗:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
25502 pengcz 20 0 30.8g 27g 19m S 1263.7 25.8 104:28.82 java
而且我发现CPU使用率太高了(1263.7%
),而且我发现cpu使用率高了最后一次,写多了甚至写失败.
不知道是不是我的错误步骤导致了这种情况?任何建议将不胜感激!
实际上,您一次提交了 5、6 或 700 万个请求,然后等待所有请求同时完成。由于您正在构建一个包含请求数量的未来列表,因此您不仅会提交许多请求,还会使用大量内存来跟踪这些响应。我想象提交许多请求而不等待响应会产生大量 CPU 生成请求有效负载并将它们写入网络,此外还有越来越大的 GC 压力将这些未来保持在一个巨大的列表中。
你应该做的是一次只有这么多的飞行请求(也许500?),等待它们完成,然后提交下一组等等。肯定有比这更好、更优化的技术,而且这也不能很好地处理错误情况,但它应该会降低你的内存占用,并防止你用许多请求来打击 C*。这是一个可能看起来像的例子:
String insert_query = "insert into " + keyspace + "." + tblName
+ " (a, b, c, d,"
+ "e, f, g, h, i, j,"
+ "k, l, m, n) VALUES "
+ "(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
List<ResultSetFuture> futures = new ArrayList<ResultSetFuture>();
PreparedStatement statement = session.prepare(insert_query);
BoundStatement bind = null;
int max = 1000000;
for (int i = 0; i < max; i++) {
bind = statement.bind(i,
null,
null,
null
);
ResultSetFuture resultSetFuture = session.executeAsync(bind);
futures.add(resultSetFuture);
if (futures.size() % 500 == 0 || i == max - 1) {
for (ResultSetFuture future : futures) {
future.getUninterruptibly(15000, TimeUnit.MILLISECONDS);
}
futures.clear();
}
}
如需进一步指导,请查看 Asynchronous queries with the Java driver。