java - query - Tiempo de espera de escritura lanzado por el controlador datastax de cassandra
planet cassandra (4)
Es el tiempo de espera del coordinador (por lo que el servidor) espera los reconocimientos para la escritura.
Mientras hago una carga masiva de datos, incrementando los contadores basados en datos de registro, me encuentro con una excepción de tiempo de espera. Estoy usando el controlador java Datastax 2.0-rc2.
¿Se trata de un problema con el servidor que no puede mantenerse al día (es decir, un problema de configuración del lado del servidor), o es un problema con el cliente que se aburre esperando que el servidor responda? De cualquier manera, ¿hay un cambio de configuración fácil que pueda hacer que solucione esto?
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
Uno de los nodos informa esto aproximadamente en el momento en que ocurrió:
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)
Experimentamos problemas similares en un solo nodo en un clúster ESX con almacenamiento de SAN adjunto (lo que no se recomienda por datastax , pero no tenemos otras opciones en este momento).
Nota: la configuración a continuación puede ser un gran golpe para el máximo rendimiento que Cassandra puede lograr, pero elegimos un sistema estable en lugar de un alto rendimiento.
Mientras ejecutaba iostat -xmt 1
, encontramos altos tiempos de w_await al mismo tiempo que ocurrían las Explicaciones de WriteTimeout. Resultó que la memtable no se pudo escribir en el disco dentro de la configuración predeterminada write_request_timeout_in_ms: 2000
.
Redujimos significativamente el tamaño de la memoria memorable de 512Mb (por defecto al 25% del espacio de almacenamiento dinámico, que en nuestro caso era de 2Gb) a 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
También aumentamos ligeramente el tiempo de espera de escritura a 3 segundos:
write_request_timeout_in_ms: 3000
También asegúrese de escribir regularmente en el disco si tiene un alto tiempo de espera de 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
Estas configuraciones permitieron que el memtable permaneciera pequeño y se escribiera a menudo. Las excepciones se resolvieron y sobrevivimos a las pruebas de estrés que se ejecutaron en el sistema.
Si bien no entiendo la causa raíz de este problema, pude resolver el problema aumentando el valor de tiempo de espera en el archivo conf / cassandra.yaml.
write_request_timeout_in_ms: 20000
Vale la pena revisar dos veces la configuración de GC para Cassandra.
En mi caso, estaba usando un semáforo para estrangular las escrituras asíncronas y aún (a veces) obteniendo tiempos de espera.
Se supo que estaba usando una configuración de GC inadecuada, que había estado usando cassandra-unit por conveniencia, lo que tuvo la consecuencia no deseada de correr con la configuración de VM predeterminada. En consecuencia, eventualmente desencadenábamos un GC de parada en el mundo que provocaba un tiempo de espera de escritura. Aplicando la misma configuración de GC que mi imagen de cassandra docker en ejecución y todo está bien.
Esto podría ser una causa poco común, pero me habría ayudado, así que vale la pena grabarlo aquí.