25

根据 cassandra 的日志(见下文),由于存在太多,查询正在中止tombstones。发生这种情况是因为我每周清理(删除)行的计数器太低。这将“删除”数十万行(用tombstone. 标记它们)

如果在此表中,由于在清理过程中某个节点已关闭而重新出现已删除的行,这根本不是问题,因此我将gc grace time单个受影响表的时间设置为 10 小时(从默认的 10 天降低)所以墓碑行可以相对较快地永久删除。

无论如何,我必须设置tombstone_failure_threshold极高以避免以下异常。(一亿,从十万上升。)我的问题是,这有必要吗?我完全不知道哪种类型的查询会被中止;插入、选择、删除?

如果只是一些选择被中止,那没什么大不了的。但这是假设中止意味着“封顶”,因为查询过早停止并返回它在找到太多墓碑之前设法收集的任何实时数据。

好吧,问起来更简单;超过时会发生什么tombstone_failure_threshold

INFO [HintedHandoff:36] 2014-02-12 17:44:22,355 HintedHandOffManager.java (line 323) Started hinted handoff for host: fb04ad4c-xxxx-4516-8569-xxxxxxxxx with IP: /XX.XX.XXX.XX
ERROR [HintedHandoff:36] 2014-02-12 17:44:22,667 SliceQueryFilter.java (line 200) Scanned over 100000 tombstones; query aborted (see tombstone_fail_threshold)
ERROR [HintedHandoff:36] 2014-02-12 17:44:22,668 CassandraDaemon.java (line 187) Exception in thread Thread[HintedHandoff:36,1,main]
org.apache.cassandra.db.filter.TombstoneOverwhelmingException
    at org.apache.cassandra.db.filter.SliceQueryFilter.collectReducedColumns(SliceQueryFilter.java:201)
    at org.apache.cassandra.db.filter.QueryFilter.collateColumns(QueryFilter.java:122)
    at org.apache.cassandra.db.filter.QueryFilter.collateOnDiskAtom(QueryFilter.java:80)
    at org.apache.cassandra.db.filter.QueryFilter.collateOnDiskAtom(QueryFilter.java:72)
    at org.apache.cassandra.db.CollationController.collectAllData(CollationController.java:297)
    at org.apache.cassandra.db.CollationController.getTopLevelColumns(CollationController.java:53)
    at org.apache.cassandra.db.ColumnFamilyStore.getTopLevelColumns(ColumnFamilyStore.java:1516)
    at org.apache.cassandra.db.ColumnFamilyStore.getColumnFamily(ColumnFamilyStore.java:1335)
    at org.apache.cassandra.db.HintedHandOffManager.doDeliverHintsToEndpoint(HintedHandOffManager.java:351)
    at org.apache.cassandra.db.HintedHandOffManager.deliverHintsToEndpoint(HintedHandOffManager.java:309)
    at org.apache.cassandra.db.HintedHandOffManager.access$300(HintedHandOffManager.java:92)
    at org.apache.cassandra.db.HintedHandOffManager$4.run(HintedHandOffManager.java:530)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)

忘了说;运行 Cassandra 版本2.0.4

4

2 回答 2

30

当向 Cassandra 发出返回一系列行(或列)的查询时,它必须扫描表以收集结果集(这称为切片)。现在,已删除的数据以与常规数据相同的方式存储,除了它被标记为墓碑,直到被压缩。但是表格阅读器仍然必须扫描它。因此,如果您周围有大量墓碑,您将需要做大量的工作来满足您表面上有限的部分。

一个具体的例子:假设您有两行具有集群键 1 和 3,以及十万个具有集群键 2 的死行位于表的第 1 行和第 3 行之间。现在,当您发出SELECT键为 >= 1 和 < 3 的查询时,您将不得不扫描 100002 行,而不是预期的两行。

更糟糕的是,Cassandra 不仅扫描这些行,而且还必须在准备响应时将它们累积在内存中。如果事情超出范围,这可能会导致节点上的内存不足错误,并且如果多个节点正在为请求提供服务,它甚至可能导致多个故障导致整个集群瘫痪。为了防止这种情况发生,如果服务检测到危险数量的墓碑,它会中止查询。您可以随意启动它,但是如果您的 Cassandra 堆在这些峰值期间快用完,那么这是有风险的。

此异常是在最近的修复中引入的,首先在 2.0.2 中可用。 是描述更改试图解决的问题的错误条目。以前一切都很好,直到您的一个节点或可能的几个节点突然崩溃。

如果只是一些选择被中止,那没什么大不了的。但这是假设中止意味着“封顶”,因为查询过早停止并返回它在找到太多墓碑之前设法收集的任何实时数据。

该查询不返回有限的集合,它实际上完全丢弃了请求。如果您想缓解,也许值得以与宽限期相同的节奏进行批量行删除,这样您就不会每周都有大量的墓碑涌入。

于 2014-02-14T06:46:56.697 回答
4

这是完整解决方案的链接:

通过确保将 gc_grace_seconds 设置为在更频繁的时间运行以适合您的应用程序或对某些数据使用 TTL 来清理逻辑删除。例如,默认的 gc_grace_seconds 是 864000(10 天)。如果您的 TTL 数据设置为 6 天,那么您可能需要将 gc_grace_seconds 更改为 604800(7 天)以更快地删除墓碑。

https://support.datastax.com/hc/en-us/articles/204612559-ReadTimeoutException-seen-when-using-the-java-driver-caused-by-excessive-tombstones

cqlsh:results> alter table example with gc_grace_seconds = 10000;

问候,

阿里

于 2019-09-05T12:09:41.757 回答