【问题标题】:Write timeout thrown by cassandra datastax drivercassandra datastax 驱动程序引发的写入超时
【发布时间】:2014-03-16 03:44:46
【问题描述】:

在执行大量数据加载、根据日志数据递增计数器时,我遇到了超时异常。我正在使用 Datastax 2.0-rc2 java 驱动程序。

这是服务器无法跟上的问题(即服务器端配置问题),还是客户端厌倦了等待服务器响应的问题?无论哪种方式,我都可以通过简单的配置更改来解决这个问题吗?

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.ResultSetFuture.extractCauseFromExecutionException(ResultSetFuture.java:271)
    at com.datastax.driver.core.ResultSetFuture.getUninterruptibly(ResultSetFuture.java:187)
    at com.datastax.driver.core.Session.execute(Session.java:126)
    at jason.Stats.analyseLogMessages(Stats.java:91)
    at jason.Stats.main(Stats.java:48)
Caused by: 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.Responses$Error.asException(Responses.java:92)
    at com.datastax.driver.core.ResultSetFuture$ResponseCallback.onSet(ResultSetFuture.java:122)
    at com.datastax.driver.core.RequestHandler.setFinalResult(RequestHandler.java:224)
    at com.datastax.driver.core.RequestHandler.onSet(RequestHandler.java:373)
    at com.datastax.driver.core.Connection$Dispatcher.messageReceived(Connection.java:510)
    at org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:70)
    at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564)
    at org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPipeline.java:791)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:296)
    at org.jboss.netty.handler.codec.oneone.OneToOneDecoder.handleUpstream(OneToOneDecoder.java:70)
    at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564)
    at org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPipeline.java:791)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:296)
    at org.jboss.netty.handler.codec.frame.FrameDecoder.unfoldAndFireMessageReceived(FrameDecoder.java:462)
    at org.jboss.netty.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:443)
    at org.jboss.netty.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:303)
    at org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:70)
    at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564)
    at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:559)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
    at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:88)
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:109)
    at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:312)
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:90)
    at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
    at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
    at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
Caused by: 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.Responses$Error$1.decode(Responses.java:53)
    at com.datastax.driver.core.Responses$Error$1.decode(Responses.java:33)
    at com.datastax.driver.core.Message$ProtocolDecoder.decode(Message.java:165)
    at org.jboss.netty.handler.codec.oneone.OneToOneDecoder.handleUpstream(OneToOneDecoder.java:66)
    ... 21 more

其中一个节点在它发生的大致时间报告了这一点:

ERROR [Native-Transport-Requests:12539] 2014-02-16 23:37:22,191 ErrorMessage.java (line 222) Unexpected exception during request
java.io.IOException: Connection reset by peer
    at sun.nio.ch.FileDispatcherImpl.read0(Native Method)
    at sun.nio.ch.SocketDispatcher.read(Unknown Source)
    at sun.nio.ch.IOUtil.readIntoNativeBuffer(Unknown Source)
    at sun.nio.ch.IOUtil.read(Unknown Source)
    at sun.nio.ch.SocketChannelImpl.read(Unknown Source)
    at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:64)
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:109)
    at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:312)
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:90)
    at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

【问题讨论】:

    标签: java cassandra datastax


    【解决方案1】:

    虽然我不明白这个问题的根本原因,但我能够通过增加 conf/cassandra.yaml 文件中的超时值来解决问题。

    write_request_timeout_in_ms: 20000
    

    【讨论】:

    • 我曾经遇到过同样的问题。我使用BatchStatement 在 Cassnadra 中写入数据。我的批量大小是 10000。减少这个批量大小后,我没有遇到异常。因此,也许您正试图在单个请求中将大量数据加载到 Cassandra。
    • 这实际上是一个非常糟糕的选择。您是否可能发现为什么会发生这种情况,因为我现在面临同样的错误。
    • @Superbrain_bug 感谢您分享您对此解决方法的判断。我相信有些人可能会觉得你的判断很有趣。如果您找到解决此问题的替代方案,我相信每个人都想知道。
    • 其中一个原因可能是 cassandra 正在运行一些内存密集型内部进程,例如压缩、修复等,而您没有足够的内存在 2 秒内进行写入 - 这种情况经常发生在我身上在开发过程中。它可以正常运行 10-15 分钟,然后出现此错误,因此我必须重新启动它。很烦人。
    【解决方案2】:

    我们在连接了 SAN 存储的 ESX 集群中的单个节点上遇到了类似的问题(not recommended by datastax,但目前我们没有其他选择)。

    注意: 下面的设置可能会对 Cassandra 所能达到的最大性能造成很大的打击,但我们选择了一个稳定的系统而不是高性能。

    在运行 iostat -xmt 1 时,我们发现在发生 WriteTimeoutExceptions 的同时 w_await 时间很高。结果证明无法在默认的write_request_timeout_in_ms: 2000 设置中将内存表写入磁盘。

    我们将 memtable 大小从 512Mb(默认为堆空间的 25%,在我们的示例中为 2Gb)显着减小到 32Mb:

    # Total permitted memory to use for memtables. Cassandra will stop
    # accepting writes when the limit is exceeded until a flush completes,
    # and will trigger a flush based on memtable_cleanup_threshold
    # If omitted, Cassandra will set both to 1/4 the size of the heap.
    # memtable_heap_space_in_mb: 2048
    memtable_offheap_space_in_mb: 32
    

    我们还将写入超时时间略微降低到 3 秒:

    write_request_timeout_in_ms: 3000
    

    如果您的 IO 等待时间较长,请确保定期写入磁盘:

    #commitlog_sync: batch
    #commitlog_sync_batch_window_in_ms: 2
    #
    # the other option is "periodic" where writes may be acked immediately
    # and the CommitLog is simply synced every commitlog_sync_period_in_ms
    # milliseconds.
    commitlog_sync: periodic
    commitlog_sync_period_in_ms: 10000
    

    这些设置允许 memtable 保持较小并经常写入。异常已解决,我们在系统上运行的压力测试中幸存下来。

    【讨论】:

      【解决方案3】:

      这是协调器(所以服务器)超时等待写入的确认。

      【讨论】:

      • 嗨,克里斯,我怎样才能进一步调试以找出 ACK 没有出现的原因?我面临着类似的问题,正在努力寻找根本原因......谢谢。
      【解决方案4】:

      值得仔细检查 Cassandra 的 GC 设置。

      在我的例子中,我使用信号量来限制异步写入,但仍然(有时)会超时。

      我发现我使用了不合适的 GC 设置,为了方便起见,我一直在使用 cassandra-unit,这会产生使用默认 VM 设置运行的意外后果。因此,我们最终会触发 hit-the-world GC,从而导致写入超时。应用与我正在运行的 cassandra docker 映像相同的 GC 设置,一切都很好。

      这可能是一个不常见的原因,但它会帮助我,所以它似乎值得在这里记录。

      【讨论】:

        猜你喜欢
        • 2016-09-21
        • 2016-02-27
        • 2017-01-20
        • 2013-07-14
        • 1970-01-01
        • 2018-02-15
        • 2013-12-23
        • 2015-10-25
        • 2020-02-01
        相关资源
        最近更新 更多