当尝试一次将数千条记录插入远程Cassandra数据库时,我可重复地遇到超时(在慢速连接上有5到6千个元素)
错误:
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 *实例提供服务时不会遇到任何超时问题,无论是否是远程问题。
我真正不喜欢限制的是批量大小是随机的和静态的,而它们应该是适应性的。
答案 0 :(得分:1)
听起来你正在达到群集的极限。如果要避免超时,则需要添加更多容量才能处理负载。如果你想做突发写入,你应该限制它们(正如你所做的那样),因为向太少的节点发送太多查询会抑制性能。如果你想等到你可以写,但你也可以增加服务器端的超时(read_request_timeout_in_ms,write_request_timeout_in_ms,request_timeout_in_ms),但这是不可取的,因为你不会给Cassandra任何时间恢复并可能导致大量的ParNew GC。