Cassandra无DELETE操作却产生上万tombstone报错如何解决?
无DELETE操作产生大量tombstone的原因
你遇到的场景核心原因来自表配置的默认TTL规则,没有DELETE操作同样会产生大量行级tombstone:
- 你的表显式配置了
default_time_to_live = 6912000(即80天),所有写入该表的记录,存活时间超过80天后会被Cassandra自动标记为删除,生成行级tombstone,不需要业务侧显式调用DELETE接口。 - 次要原因:如果业务写入时为非主键字段传入null值,Cassandra会为对应字段生成字段级tombstone,这类tombstone量级一般较低,不会触发扫描超限的报错。
避免TombstoneOverwhelmingException的方案
可以按优先级选择以下优化方案:
- 更换更适配的压缩策略
当前你使用的SizeTieredCompactionStrategy(STCS)只有在同大小层级的SSTable合并时才会清理tombstone,清理效率极低。你的表按年月做分区键、自带TTL,属于典型的时间序列场景,建议更换为TimeWindowCompactionStrategy(TWCS),时间窗口建议设置为1个月,和分区键的时间粒度对齐,按时间窗口合并SSTable,当窗口内所有记录全部过期后可以直接删除整个SSTable,不需要扫描单条记录,tombstone清理效率提升非常明显。 - 调整TTL和GC Grace配置
- 如果业务不需要保留80天的历史数据,可以适当缩短
default_time_to_live,减少留存的过期数据量。 - 当前
gc_grace_seconds配置为10天,只要你能保证集群repair的频率小于10天,可以适当调短该参数,让tombstone可以更快被compaction清理,注意不要调整到小于集群的最大宕机恢复时间,防止过期数据复活。
- 如果业务不需要保留80天的历史数据,可以适当缩短
- 优化repair执行逻辑
执行repair时不要扫描全量token范围,拆分为更小的token分段执行,减少单次扫描过程中遇到的tombstone总量,避免触发阈值。同时尽量将repair任务放在业务低峰期执行,降低对业务查询的影响。 - 临时调整扫描阈值(不推荐长期使用)
如果需要临时解决报错,可以修改cassandra.yaml中的tombstone_failure_threshold参数,将默认的100000调整到更高的数值,避免查询直接被中止,该方案只是临时规避,不能从根本上解决tombstone过多的问题。
内容的提问来源于stack exchange,提问作者Anthony Elliott
相关产品推荐
相关产品推荐

