Cassandra ReadTimeoutException при получении всех записей в таблице даже после переопределения тайм-аута - PullRequest
0 голосов
/ 04 октября 2018

Итак, я пытаюсь получить все записи в таблице cassandra (~ 10K записей), используя драйвер Java datastax 3.1 со следующими настройками уровня запроса:

// |query| reads all records in a table (select * from table)
// Setting read timeout as 10 minutes
query.setReadTimeoutMillis(600000);
// Set page size as 1000
query.setFetchSize(1000);

Настройки сервера Cassandra по умолчанию (все таймауты по умолчанию).Это кластер из 3 узлов.

Драйвер смог успешно прочитать первые 1000 записей, но я начинал получать следующую ошибку каждый раз, когда драйвер пытался получить следующие 1000 записей.

com.datastax.driver.core.exceptions.ReadTimeoutException: Cassandra timeout during read query at consistency LOCAL_ONE (1 responses were required but only 0 replica responded)
    at com.datastax.driver.core.exceptions.ReadTimeoutException.copy(ReadTimeoutException.java:88)
    at com.datastax.driver.core.exceptions.ReadTimeoutException.copy(ReadTimeoutException.java:25)
    at com.datastax.driver.core.DriverThrowables.propagateCause(DriverThrowables.java:37)
    at com.datastax.driver.core.ArrayBackedResultSet$MultiPage.prepareNextRow(ArrayBackedResultSet.java:312)
    at com.datastax.driver.core.ArrayBackedResultSet$MultiPage.isExhausted(ArrayBackedResultSet.java:269)
    at com.datastax.driver.core.ArrayBackedResultSet$1.hasNext(ArrayBackedResultSet.java:143)
    ... <some more stacktrace of custom codebase trying to read all rows in a table>
Caused by: com.datastax.driver.core.exceptions.ReadTimeoutException: Cassandra timeout during read query at consistency LOCAL_ONE (1 responses were required but only 0 replica responded)
    at com.datastax.driver.core.exceptions.ReadTimeoutException.copy(ReadTimeoutException.java:115)
    at com.datastax.driver.core.Responses$Error.asException(Responses.java:124)
    at com.datastax.driver.core.RequestHandler$SpeculativeExecution.onSet(RequestHandler.java:500)
    at com.datastax.driver.core.Connection$Dispatcher.channelRead0(Connection.java:1012)
    at com.datastax.driver.core.Connection$Dispatcher.channelRead0(Connection.java:935)
    at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:342)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:328)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:321)
    at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:266)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:342)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:328)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:321)
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:342)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:328)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:321)
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:342)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:328)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:321)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1280)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:342)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:328)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:890)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:564)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:505)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:419)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:391)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
    at java.lang.Thread.run(Thread.java:748)
Caused by: com.datastax.driver.core.exceptions.ReadTimeoutException: Cassandra timeout during read query at consistency LOCAL_ONE (1 responses were required but only 0 replica responded)
    at com.datastax.driver.core.Responses$Error$1.decode(Responses.java:62)
    at com.datastax.driver.core.Responses$Error$1.decode(Responses.java:37)
    at com.datastax.driver.core.Message$ProtocolDecoder.decode(Message.java:277)
    at com.datastax.driver.core.Message$ProtocolDecoder.decode(Message.java:257)
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:88)
    ... 19 common frames omitted 

Итак, служба, которая считывала все записи в таблице, работала в цикле сбоя, каждый раз с одним и тем же исключением.

К моему удивлению, это исключение последовательно происходило ровно через 10 секунд после 1000-й записибыл прочитан.Кажется, что 10 секунд - это тайм-аут на стороне сервера cassandra по умолчанию, который должен был быть переопределен для моего запроса до 600 секунд (ясно, что этого не произошло).Может кто-нибудь объяснить мне, почему это могло произойти?

PS - После долгого времени, пытаясь найти основную причину, я перезапустил Кассандру.И вуаля! После этого все прошло гладко, все записи были прочитаны на страницах и обработаны без каких-либо проблем.

1 Ответ

0 голосов
/ 21 октября 2018

select * from table - это плохой шаблон - Cassandra не оптимизирована для него, поэтому ему нужно получать данные со всех узлов и передавать через узел-координатор.Наиболее эффективный способ получить доступ к данным в Cassandra - указать ключ раздела (возможно, с дополнительными условиями для столбцов кластеризации).

Если вам действительно нужно сканировать все данные в кластере, вам нужно реализовать это какнабор запросов диапазонов токенов, проходящих через все диапазоны в кластере (вы можете получить диапазоны токенов с помощью Metadata класса драйверов Java или Python).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...