【问题标题】:What exactly happens when tombstone limit is reached达到墓碑限制时究竟会发生什么
【发布时间】:2019-09-05 20:09:41
【问题描述】:

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


    【解决方案1】:

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

    一个具体的例子:假设您有两行具有集群键 1 和 3,以及位于表中的第 1 行和第 3 行之间的具有集群键 2 的十万死行。现在,当您发出SELECT 查询,其中键是>= 1 和

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

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

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

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

    【讨论】:

    • 根据我的问题中的错误日志,异常发生在提示切换期间。这似乎暗示该问题不仅发生在SELECT 查询期间,而且还发生在inter-node communication 期间。这个对吗?重要的原因是该表有一个compound key,并且常规选择只会通过这些键中的第一个进行查询,从而使所述查询期间的墓碑数量微不足道。
    • 是的,提示是一种用于在节点之间交换信息的协议,但它是一个可选功能,旨在提高节点中断期间的集群性能。您可以在datastax.com/dev/blog/modern-hinted-handoff 阅读更多内容。提示存储在系统表中,因此发送提示涉及执行切片,其中包含与墓碑相关的所有潜在问题。
    • 我对@9​​87654328@ 没有深入的了解,所以我不能说在提示表中获得过多的墓碑是否表明使用模式不好。我只能说你不是唯一一个看到这些的人;有关相关讨论,请参阅 cassandra-user-incubator-apache-org.3065146.n2.nabble.com/…。如果您可以将这些崩溃与特定操作或周期性任务相关联,那么它可能会引导您了解为什么首先会生成如此多的提示。
    • 谢谢,不过很奇怪;我使用ONE 的写入一致性,所以如果我理解正确,hintedhandoff 甚至不应该发挥作用......也许它来自对旧键空间的写入,但这只是一个没有受过教育的猜测。
    • @natli 到您的最后一条评论:即使写入 CL 为 ONE,以防拥有令牌的节点已关闭 - C* 将在它恢复时使用提示切换来更新它。
    【解决方案2】:

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

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

    问候,

    阿里

    【讨论】:

    • 这不是更早地创建墓碑吗?在发生压缩/修复事件之前,它们仍然不会被删除
    猜你喜欢
    • 2015-12-25
    • 2015-10-23
    • 2011-01-18
    • 2018-03-03
    • 2014-08-20
    • 1970-01-01
    • 2023-04-01
    • 2019-10-12
    • 1970-01-01
    相关资源
    最近更新 更多