如果结果集较大,则使用 Cassandra 和 DataStax Java 驱动程序时出现 NoHostAvailableException

Posted

技术标签:

【中文标题】如果结果集较大,则使用 Cassandra 和 DataStax Java 驱动程序时出现 NoHostAvailableException【英文标题】:NoHostAvailableException With Cassandra & DataStax Java Driver If Large ResultSet 【发布时间】:2013-10-31 23:10:53 【问题描述】:

设置:

2 节点 Cassandra 1.2.6 集群 副本=2 非常大的 CQL3 表,没有二级索引 Rowkey 是一个 UUID.randomUUID().toString() 读取一致性设置为 ONE 使用 DataStax java 驱动程序 1.0

请求:

尝试通过“SELECT some-col from schema.table LIMIT nnn;”进行表扫描

失败:

一旦超出某个 nnn LIMIT,我就会开始从驱动程序中获取 NoHostAvailableExceptions。

它是这样写的:

com.datastax.driver.core.exceptions.NoHostAvailableException: All host(s) tried for query failed (tried: /10.181.13.239 ([/10.181.13.239] Unexpected exception triggered))
            at com.datastax.driver.core.exceptions.NoHostAvailableException.copy(NoHostAvailableException.java:64)
            at com.datastax.driver.core.ResultSetFuture.extractCauseFromExecutionException(ResultSetFuture.java:214)
            at com.datastax.driver.core.ResultSetFuture.getUninterruptibly(ResultSetFuture.java:169)
            at com.jpmc.es.rtm.storage.impl.EventExtract.main(EventExtract.java:36)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:601)
            at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: com.datastax.driver.core.exceptions.NoHostAvailableException: All host(s) tried for query failed (tried: /10.181.13.239 ([/10.181.13.239] Unexpected exception triggered))
            at com.datastax.driver.core.RequestHandler.sendRequest(RequestHandler.java:98)
            at com.datastax.driver.core.RequestHandler$1.run(RequestHandler.java:165)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)

鉴于:对于具有数百万行的大表来说,这可能不是最有启发性的事情,但这是我学习不该做什么的方法,所以我非常感谢能自愿出现这种错误的人被调试。

例如,当这种情况发生时,没有迹象表明集群中的节点曾经遇到过请求问题(任何一个节点上的日志中都没有任何内容表明任何超时或故障)。此外,我在驱动程序上启用了跟踪,只要查询成功,它就会为您提供一些很好的自动跟踪(ala Oracle)信息。但是在这种情况下,驱动程序会抛出 NoHostAvailableException 并且没有可用的 ExecutionInfo,因此在这种情况下跟踪没有提供任何好处。

我还发现有趣的是,这似乎没有被记录为超时(我的 JMX 控制台告诉我没有发生超时)。所以,我不明白故障实际发生在哪里。我的想法是驱动程序有问题,但我不知道如何调试它(我真的很想)。

我已经阅读了几篇来自人们的帖子,其中指出 query'g for resultSets > 10000 rows 可能不是一个好主意,我愿意接受这一点,但我想了解导致异常的原因以及异常发生在哪里正在发生异常。

FWIW,我也尝试在 cassandra.yaml 中调整超时属性,但这没有任何区别。

我欢迎任何建议、轶事、侮辱或金钱捐助,以帮助我在白痴开发者之家注册。

问候!!

【问题讨论】:

【参考方案1】:

我的猜测(也许其他人可以确认)是您通过导致超时的查询对集群施加了过高的负载。所以,是的,调试有点困难,因为根本原因并不明显:我设置的限制太大还是集群实际上已关闭?

您希望避免对单个查询中请求的数据量设置过大限制,通常通过设置合理的限制并对结果进行分页,例如,

SELECT * FROM messages WHERE user_id = 101 LIMIT 1000;
SELECT * FROM messages WHERE user_id = 101 AND msg_id > [Last message ID received] LIMIT 1000;

添加的自动分页功能(see this document,其中复制了此答案中的代码示例)是对 datastax java-driver 的重大改进,因为它无需手动分页并允许您执行以下操作:

Statement stmt = new SimpleStatement("SELECT * FROM images");
stmt.setFetchSize(100);
ResultSet rs = session.execute(stmt);

// Iterate over the ResultSet here

虽然这不一定能解决您的问题,但可以最大限度地减少“太大”查询的可能性。

【讨论】:

非常感谢您的回复,Lorcan!我来自俄亥俄州都柏林 :) 经过大量的 Google 搜索,我确信您是正确的。对于这种情况,我需要比我更好地计划使用。我会研究 2.0,但我同意你的看法,这是对技术的不切实际的期望。 完全没有,很乐意提供帮助。我们都柏林人需要互相照顾;-)

以上是关于如果结果集较大,则使用 Cassandra 和 DataStax Java 驱动程序时出现 NoHostAvailableException的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Achilles 更新 cassandra 中的 TTL,如果不存在则抛出异常

状态:整理我的面板数据集-如果先前的ID满足补充准则,则过滤符合准则的观察结果

将值与可能较大的数据集进行比较

如果存储过程在 SQL Server 2005 上的选择之前进行更新,则没有结果集

cassandra分页

Impala在处理结果集较大的查询的优势