【发布时间】:2020-06-07 04:43:43
【问题描述】:
我们有一个使用 Cassandra 作为数据存储的应用程序。为了方便访问,需要将相同的数据存储在具有不同分区键的多个表中。为了将数据存储到多个表中,使用了 BatchStatements。使用批处理语句的原因是确保数据写入全部或不写入。
通过此设置,最近我们开始看到由于用户群增加而导致的大量写入超时错误。我们遇到了许多博客和文章,其中提到 BatchStatements 被错误地用于存储多个分区。
参考文献:
- https://docs.datastax.com/en/dse/6.0/cql/cql/cql_using/useBatchGoodExample.html
- What is the batch limit in Cassandra?
- Cassandra Batch statement-Multiple tables
- https://grokbase.com/t/cassandra/user/153gsmdzs6/writing-to-multiple-tables
原因似乎是协调节点上的负载过大,进而导致延迟。可以选择将 cassandra.yaml 中的 write_request_timeout_in_ms 增加到比默认 5 s 更高的值。我们尝试了这个,但仍然请求失败。因此,我们更新了这个设置,现在使用 executeAsync。这样,WriteTimeout 异常就完全消失了。
但现在的问题是 - 我们如何处理原子性?下面是更新为使用 executeAsync 的代码。使用 executeAsync 是使用批处理语句的正确替代方法吗?有什么办法可以在异常块中处理回滚?
try {
for (ListenableFuture<ResultSet> futureItem : futureItems) {
futureItem.get();
}
} catch (Exception e) {
// need to handle rollback ?
}
【问题讨论】: