达到墓碑限制时到底发生了什么

时间:2014-02-13 13:13:57

标签: cassandra tombstone

根据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

2 个答案:

答案 0 :(得分:23)

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

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

更糟糕的是,Cassandra不仅会扫描这些行,还必须在准备响应时将它们累积在内存中。如果事情太过分,这可能会导致节点上出现内存不足错误,并且如果多个节点正在为请求提供服务,则甚至可能导致多个故障导致整个群集崩溃。为了防止这种情况发生,如果服务检测到危险数量的逻辑删除,服务将中止查询。你可以自由地进行调整,但如果你的Cassandra堆在这些峰值期间即将耗尽,那么风险很大。

此异常是在最近的修复程序中引入的,首先在2.0.2中提供。 Here是描述更改试图解决的问题的错误条目。以前一切都会好起来的,直到你的一个节点,或者可能是几个节点突然崩溃。

  

如果只是某些选择被中止,那就不是那么大了。   但是,假设中止意味着'上限',因为查询停止了   过早地返回它之前收集的任何实时数据   发现了太多的墓碑。

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

答案 1 :(得分:1)

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

通过确保将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;

此致

阿里