我正在尝试将50000条记录插入到五节点cassandra集群中。我正在使用 executeAsync 以提高性能(减少从应用程序端插入的时间)。我尝试使用多个批量大小的Batchstatement,但每次我得到以下异常。
Exception in thread "main" com.datastax.driver.core.exceptions.WriteTimeoutException: Cassandra timeout during write query at consistency ONE (1 replica were required but only 0 acknowledged the write)
at com.datastax.driver.core.exceptions.WriteTimeoutException.copy(WriteTimeoutException.java:54)
at com.datastax.driver.core.DefaultResultSetFuture.extractCauseFromExecutionException(DefaultResultSetFuture.java:259)
at com.datastax.driver.core.DefaultResultSetFuture.getUninterruptibly(DefaultResultSetFuture.java:175)
at
我插入了数据,即10000,20000到40000条记录没有任何问题。以下是我写的java代码。
for (batchNumber = 1; batchNumber <= batches; batchNumber++) {
BatchStatement batch = new BatchStatement();
for (record = 1; record <= batchSize; record++) {
batch.add(ps.bind(query));
}
futures.add(session.executeAsync(batch));
}
for (ResultSetFuture future : futures) {
resultSet = future.getUninterruptibly();
}
其中ps是预准备语句,批次是批次数,batchSize是批次中的记录数。
我无法理解问题的根本原因。我认为有些节点已关闭,当我检查时,所有节点都正常运行。
我应该如何调试异常?
答案 0 :(得分:4)
我看到了一些错误:
让我们重启。
BATCH
会使协调节点重载。批次越大(无论是kb还是语句数量),协调器的重载就越大。BATCH
的工作原理。选择一个节点协调所有语句,这样的节点将负责所有语句。通常,协调器是根据第一个语句选择的,如果您的语句命中多个节点,协调器也需要协调属于不同节点的事物。相反,如果您发起多个单独的异步查询,则每个节点只负责他们的语句。您将在所有群集节点上传播重载,而不是在一个节点上进行锤击。new BoundStatement(ps).bind(xxxx)
语句。无论如何,这很容易解决。future
添加到列表中,并最终因为OOM错误而被终止。此外,您还没有为群集提供实际提取所有数据的可能性,因为您可以比群集可以提取的方式更快地传输数据。您需要做的是限制列表中的期货数量。最多保留某些值(例如1000)。要执行此类任务,您需要使用.getUninterruptibly
在循环中移动最终循环。这样,您可以降低摄取速率并查看减少的超时异常计数。根据应用程序的不同,减少超时异常意味着重试次数减少,因此查询次数减少,开销减少,响应时间更短等...... .getUninterruptibly
列表中设置Future
循环是可以的,但是当您的群集是
超载,你 会超时。此时,您应该捕获异常,然后处理,无论是重试,还是重新抛出,无论如何。我建议你围绕幂等查询设计你的模型,这样我就可以重试失败的查询,直到它们成功而不用担心重试后果(这也可能发生在驱动程序级别!)。希望有所帮助。
答案 1 :(得分:0)
那不是BATCH
的用途。
当您向批处理添加多个语句时,Cassandra将尝试以原子方式应用它们。
要么所有这些都会成功,要么都不会,并且它们都必须在单个查询超时内完成。
此外,如果您发出的请求多于可以同时处理的请求,那么它们将进入队列,并且在队列中等待的时间会导致超时。
要在没有超时的情况下完成所有操作,请使用单独的语句并在任何时候限制飞行中的号码。
或者,使用COPY
命令从CSV加载数据。