如何在cassandra中解决写超时异常?

时间:2016-11-16 11:39:17

标签: java exception cassandra prepared-statement resultset

我正在尝试将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是批次中的记录数。

我无法理解问题的根本原因。我认为有些节点已关闭,当我检查时,所有节点都正常运行。

我应该如何调试异常?

2 个答案:

答案 0 :(得分:4)

我看到了一些错误:

  1. 您似乎正在尝试弄清楚批量最大次查询的数量。
  2. 您似乎认为批处理多个语句会为您带来某种性能提升。
  3. 您错误地在循环中重复使用相同的预处理语句。
  4. 某些提取率并非限制您的应用程序。
  5. 您没有执行任何异常处理,例如,当某个批处理失败时重试。
  6. 让我们重启。

    1. 批次中的最大语句数应小于10.越小越好。顺便说一下,批处理的总大小必须低于YAML配置文件中的任何值。通常,如果您的批次大于5kb,则日志中会出现警告。如果您的批次大于50kb,批次将失败。您可以调整这些值,但应记住BATCH会使协调节点重载。批次越大(无论是kb还是语句数量),协调器的重载就越大。
    2. 通过将不相关的陈述一起批处理,您无法获得任何收益。相反,您实际上失去性能。这是由于BATCH的工作原理。选择一个节点协调所有语句,这样的节点将负责所有语句。通常,协调器是根据第一个语句选择的,如果您的语句命中多个节点,协调器也需要协调属于不同节点的事物。相反,如果您发起多个单独的异步查询,则每个节点只负责他们的语句。您将在所有群集节点上传播重载,而不是在一个节点上进行锤击。
    3. 您正在以错误的方式使用预准备语句。您应该添加new BoundStatement(ps).bind(xxxx)语句。无论如何,这很容易解决。
    4. 如果要运行大量查询,则会一直运行它们。您将耗尽应用程序内存,因为它会继续将future添加到列表中,并最终因为OOM错误而被终止。此外,您还没有为群集提供实际提取所有数据的可能性,因为您可以比群集可以提取的方式更快地传输数据。您需要做的是限制列表中的期货数量。最多保留某些值(例如1000)。要执行此类任务,您需要使用.getUninterruptibly 循环中移动最终循环。这样,您可以降低摄取速率并查看减少的超时异常计数。根据应用程序的不同,减少超时异常意味着重试次数减少,因此查询次数减少,开销减少,响应时间更短等......
    5. .getUninterruptibly列表中设置Future循环是可以的,但是当您的群集是 超载,你 会超时。此时,您应该捕获异常,然后处理,无论是重试,还是重新抛出,无论如何。我建议你围绕幂等查询设计你的模型,这样我就可以重试失败的查询,直到它们成功而不用担心重试后果(这也可能发生在驱动程序级别!)。
    6. 希望有所帮助。

答案 1 :(得分:0)

那不是BATCH的用途。 当您向批处理添加多个语句时,Cassandra将尝试以原子方式应用它们。 要么所有这些都会成功,要么都不会,并且它们都必须在单个查询超时内完成。

此外,如果您发出的请求多于可以同时处理的请求,那么它们将进入队列,并且在队列中等待的时间会导致超时。

要在没有超时的情况下完成所有操作,请使用单独的语句并在任何时候限制飞行中的号码。 或者,使用COPY命令从CSV加载数据。