有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何解决cassandra中的写入超时异常?

我正试图将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 

我插入了数据,即1000020000到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是准备好的语句,batch是批次数,batchSize是批次中的记录数

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

我应该如何调试异常


共 (1) 个答案

  1. # 1 楼答案

    我看到了一些错误:

    1. 你似乎在试图弄清楚你能一起批处理的最大查询数是多少
    2. 似乎您认为批处理多个语句会给您带来某种性能提升
    3. 您在循环中错误地重用了相同的预处理语句
    4. 您并没有以某些摄取率来限制应用程序
    5. 您没有执行任何异常处理,例如当某个批处理失败时重试

    让我们重新开始


    1. 批处理中语句的最大数量应小于10。越少越好。顺便说一下,批处理的总大小必须小于YAML配置文件中的任何值。通常,如果批处理大于5kb,则日志中将显示警告。如果批处理大于50kb,批处理将失败。您可以调整这些值,但应该记住BATCH会重载协调器节点。批处理越大(以kb或语句数表示),协调器上的过载就越大
    2. 将不相关的语句批处理在一起,不会带来任何好处。相反,你实际上会失去表现。这是因为BATCH的工作方式。选择一个节点来协调所有语句,该节点将负责所有语句。通常,协调器是根据第一条语句选择的,如果语句涉及多个节点,那么协调器也需要协调属于不同节点的内容。相反,如果启动多个独立的异步查询,每个节点将只负责它们的语句。您将在所有集群节点上传播重载,而不是在一个节点上敲打
    3. 你以错误的方式使用事先准备好的陈述。您应该添加一个new BoundStatement(ps).bind(xxxx)语句。无论如何,这是一个简单的解决办法
    4. 如果要运行大量查询,则需要一直运行它们。您将耗尽应用程序内存,因为它将继续向列表中添加future,并且最终将因为OOM错误而被杀死。此外,你没有给你的集群提供一种可能性,让它能够真正地接收你向它发射的所有数据,因为你发射数据的速度比你的集群接收数据的速度要快得多。你需要做的是限制列表中期货的数量。将其保持在某个最大值(如1000)。要执行这样的任务,你需要在循环中移动.getUninterruptibly。通过这种方式,可以降低摄入率,并减少超时异常计数。根据应用程序的不同,超时异常的减少意味着重试次数更少,因此查询更少,开销更少,响应时间更长等等
    5. Future的列表中有一个.getUninterruptibly的循环是可以的,但是当集群 超载时,你将超时。此时,您应该捕获异常并处理它,无论是重试,还是重新抛出,无论是什么。我建议您围绕幂等查询设计模型,这样我就可以重试失败的查询,直到它们成功,而不必担心重试结果(这也可能发生在驱动程序级别!)

    希望有帮助