根据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
当向Cassandra发出返回行(或列)范围的查询时,它必须扫描表以收集结果集(这称为切片)。现在,已删除的数据以与常规数据相同的方式存储,只是在删除之前将其标记为逻辑删除。但是,表读取器仍然必须对其进行扫描。因此,如果周围有大量的墓碑,那么您将需要做大量的工作来满足表面上有限的切片。
一个具体的示例:假设您有两行具有聚类键1和3,以及十万个具有聚簇键2的无效行,它们位于表的第1行和第3行之间。现在,当您发出SELECT
键为> = 1和<3的查询时,必须扫描100002行,而不是预期的两行。
更糟糕的是,Cassandra不仅要扫描这些行,还必须在准备响应时将它们存储在内存中。如果事情太遥远,这可能会导致节点上的内存不足错误,并且如果多个节点正在为请求提供服务,则甚至可能导致多个故障,从而使整个群集崩溃。为了防止这种情况发生,如果服务检测到危险数量的逻辑删除,则该服务将中止查询。您可以随意进行此操作,但是如果在这些峰值期间您的Cassandra堆快要用完了,那是有风险的。
在最近的修复程序中引入了此异常,该修复程序在2.0.2中首次可用。这是错误条目,描述了更改要解决的问题。以前,一切都会好起来的,直到您的一个节点或可能几个节点突然崩溃。
如果只是某些选择被中止,那没什么大不了的。但这是假设中止意味着“上限”,因为查询过早停止并返回在找到太多墓碑之前设法收集的所有实时数据。
该查询不返回有限的集合,而是实际上完全删除了该请求。如果您想减轻压力,也许值得以宽限期相同的节奏进行批量行删除,因此您不必每周都有大量的墓碑涌入。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句