2016-06-09 29 views
2

当试图几千条记录一次插入到远程卡桑德拉分贝,我重复地遇到超时(5〜6千的元素连接速度慢)与NoHostAvailableException处理幻象DSL

错误:

All host(s) tried for query failed (tried: /...:9042 
(com.datastax.driver.core.exceptions.OperationTimedOutException: [/...] 
Timed out waiting for server response)) 
com.datastax.driver.core.exceptions.NoHostAvailableException: 
All host(s) tried for query failed (tried: /...:9042 
(com.datastax.driver.core.exceptions.OperationTimedOutException: [/...] 
Timed out waiting for server response)) 

模型:

class RecordModel extends CassandraTable[ConcreteRecordModel, Record] { 

    object id extends StringColumn(this) with PartitionKey[String] 

... 
abstract class ConcreteRecordModel extends RecordModel 
    with RootConnector with ResultSetFutureHelper { 

def store(rec: Record): Future[ResultSet] = 
    insert.value(_.id, rec.id).value(...).future() 

def store(recs: List[Record]): Future[List[ResultSet]] = Future.traverse(recs)(store) 

连接器:

val connector = ContactPoints(hosts).withClusterBuilder(
    _.withCredentials(
    config.getString("username"), 
    config.getString("password") 
).withPoolingOptions(
    new PoolingOptions().setCoreConnectionsPerHost(HostDistance.LOCAL, 4) 
     .setMaxConnectionsPerHost(HostDistance.LOCAL, 10) 
     .setCoreConnectionsPerHost(HostDistance.REMOTE, 2) 
     .setMaxConnectionsPerHost(HostDistance.REMOTE, 4) 
     .setMaxRequestsPerConnection(HostDistance.LOCAL, 32768) 
     .setMaxRequestsPerConnection(HostDistance.REMOTE, 2000) 
     .setPoolTimeoutMillis(10000) 
) 
).keySpace(keyspace) 

我已经尝试调整池选项,分开和一起。但是,即使加倍所有的REMOTE设置并没有改变超时明显

目前的解决方法,这是我想避免 - 分裂清单分成批次,等待每完成:

def store(recs: List[Record]): Future[List[ResultSet]] = { 
    val rs: Iterator[List[ResultSet]] = recs.grouped(1000) map { slice => 
    Await.result(Future.traverse(slice)(store), 100 seconds) 
    } 
    Future.successful(rs.to[List].flatten) 
} 

会是什么处理这个问题的好方法?

谢谢

编辑

的错误确实表明未能/超载集群,但我怀疑这里的网络发挥了重要作用。上面提供的数字来自远程机器。当同一个数据中心的机器提供相同的C *时,它们要高得多。另一个可疑的细节是,用quill喂养相同的C *实例不会遇到任何超时问题,远程或不远。

我真的不喜欢节流的是批量大小是随机的和静态的,而它们应该是适应性的。

回答

1

听起来就像是在触及群集的极限。如果你想避免超时,你将需要增加更多容量来处理负载。如果你只是想突发写入,你应该扼杀它们(就像你在做的那样),因为向太少的节点发送太多查询会抑制性能。如果您想等到可以写入,则还可以增加服务器端的超时(read_request_timeout_in_ms,write_request_timeout_in_ms,request_timeout_in_ms),但这不可取,因为您不会随时给Cassandra恢复并可能导致大量ParNew GC。

+0

IIUC你建议的方式去增加更多的机器?这可以完成,但我仍然想知道接受请求的数量很少。在上面添加了一些细节,也许你有一个想法。你可以分享一些合理的重试策略的细节吗?什么是集群恢复的合理时间。已经尝试过增加超时退出,但有时甚至在30秒后重试似乎要早。 – kostja

+0

使用羽毛笔时,您是否执行相同的查询?这些例外情况肯定发生在超时客户端,但是由于集群花费太长时间来响应结果。你在服务器的日志中看到很多GC吗?如果群集没有出现CPU/IO明显负载的情况,那么您也可以增加客户端的读取超时 http://docs.datastax.com/en/drivers/java/2.1/com/datastax/驱动器/核心/ SocketOptions.html#setReadTimeoutMillis,内部 - – Kurt