Cassandra“写超时”的本质是啥?

Posted

技术标签:

【中文标题】Cassandra“写超时”的本质是啥?【英文标题】:What's the nature of Cassandra "write timeout"?Cassandra“写超时”的本质是什么? 【发布时间】:2017-01-11 06:13:05 【问题描述】:

我正在 AWS EC2 上的 24 节点 Cassandra 3.5 集群(每台主机为 c4.2xlarge 类型:8 个 vcore 和 15G ram)上运行一个写入繁重的程序(10 个线程以 25K/秒的写入峰值)

每隔一段时间,我的 Java 客户端使用 DataStax 驱动程序 3.0.2 就会出现写入超时问题:

com.datastax.driver.core.exceptions.WriteTimeoutException: Cassandra timeout during write query at consistency TWO (2 replica were required but only 1 acknowledged the write)
    at com.datastax.driver.core.exceptions.WriteTimeoutException.copy(WriteTimeoutException.java:73)
    at com.datastax.driver.core.exceptions.WriteTimeoutException.copy(WriteTimeoutException.java:26)
    at com.datastax.driver.core.DriverThrowables.propagateCause(DriverThrowables.java:37)
    at com.datastax.driver.core.DefaultResultSetFuture.getUninterruptibly(DefaultResultSetFuture.java:245)
    at com.datastax.driver.core.AbstractSession.execute(AbstractSession.java:64)

错误很少发生,并且以非常不可预测的方式发生。到目前为止,我无法将故障与任何特定的事情联系起来(例如程序运行时间、磁盘上的数据大小、一天中的时间、系统负载指标,如 CPU、内存、网络指标)。操作。

我正在尝试找出问题的根本原因。在网上寻找选项,我对那里的所有线索有点不知所措,例如

更改“cassandra.yaml”中的“write_request_timeout_in_ms”(已更改为 5 秒) 使用适当的“RetryPolicy”来保持会话继续进行(已经在 ONE 会话级别一致性级别上使用 DowngradingConsistencyRetryPolicy) 更改缓存大小、堆大小等 - 从未尝试过那些 b/c 有充分的理由将其视为根本原因。

在我的研究过程中,真正令人困惑的一件事是,我从一个完全复制的集群中得到了这个错误,只有很少的 ClientRequest.timeout.write 事件:

我有一个完全复制的 24 节点集群,跨越 5 个 aws 区域。每个区域至少有 2 个数据副本 我的程序在会话级别运行一致性级别 ONE(使用 QueryOption 的集群构建器) 发生错误时,我们的 Graphite 图表记录的主机故障不超过三 (3) 个,即具有 Cassandra.ClientRequest.Write.Timeouts.Count 值 我已经将 write_timeout 设置为 5 秒。网络非常快(使用 iperf3 验证)且稳定

理论上,情况应该在 Cassandra 的故障安全范围内。但是为什么我的程序还是失败了?这些数字不是看起来的样子吗?

【问题讨论】:

我们有同样的问题,有时会发生写入超时,尤其是当我们失去 cassandra 数据中心之间的连接时(我们的数据中心之间的带宽很差),甚至本地数据中心内的请求也会因超时而失败。但是根据 cassandra 写入路径写入超时不是故障,因此我们为 cassandra 驱动程序实施了自定义重试策略以忽略写入超时,并且在最终一致性要求中工作正常 +1 谢谢米哈伊尔。就我而言,我忘了提到我的程序使用 BatchStatement。我刚刚看到这篇帖子datastax.com/dev/blog/cassandra-error-handling-done-right,它建议进一步检测失败的写入类型:是BATCH 还是BATCH_LOG。就我而言,我两者都有。我可以理解驱动程序在 BATCH_LOG 失败,但不明白为什么我仍然会遇到 BATCH 失败。除了我最初的问题(我应该有很多节点可以发送副本)之外,我还应用了 DowngradingConsistencyRetryPolicy,它应该已经忽略了这个错误。 必应,您的批处理中有多少个操作?可能是太大了,超时无法处理 Mikhail - 我将批量大小限制为 50。平均数据大小在 5-10K 之间(因为警告阈值设置为 5K,所以我必须从日志中查看实际值)。从那以后,我发现大多数超时都是 BATCH_LOG WriteType。所以你可能是对的 - 也许批量大小是问题。我很犹豫是否更改 b/c 超时很少发生,但使用批处理的性能增益是显着的。我确实尝试过异步写入,但遇到了类似于 CASSANDRA-10689 的驱动程序 OOM 问题。所以我选择在我的代码中添加一个恢复机制。 我有同样的问题,我的测量结果显示,这个异常出现得早,然后超过 2 秒(默认超时)。 【参考方案1】:

看到超时或错误并不总是一件坏事,特别是如果您以更高的一致性级别编写,写入可能仍然会通过。

我看到你提到CL=ONE 你仍然可以在这里得到超时,但写入(突变)仍然通过。我发现这个博客非常有用:https://www.datastax.com/dev/blog/cassandra-error-handling-done-right。在发生错误时检查您的服务器端(节点)日志,以查看您是否有诸如 ERROR / WARN / GC pauses(如上面提到的 cmets 之一)之类的事件,这些事件可能导致节点无响应,因此超时或其他类型的错误。

如果您的更新是幂等的(理想情况下),那么您可以构建一些重试机制。

【讨论】:

以上是关于Cassandra“写超时”的本质是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Cassandra 数据模型

Meet Professor Cassandra Fraser

Cassandra 更新无法正常工作

Cassandra 简介

JAVA操作cassandra数据库

Cassandra 分页在并发插入时的行为方式