Cassandra 的删除操作实际上是一个插入操作。新插入的一条数据被称为tombstone(墓碑),墓碑和普通记录最大的差别在于:它拥有一个过期时间(expiration date/time)。当过期时间到达的时候,tombstone数据在Cassandra执行Compaction操作的时候会被真正的从磁盘上删除。
1. 为什么使用tombstone机制
在分布式系统中,Cassandra 会存放同一份数据的多个副本在不同的节点上,这种方式提升了系统的可靠性,却大大提升了数据删除的复杂度。考虑不使用tombstone直接删除的方式,假设数据A存放在三个节点上,其中一个节点暂时崩溃了,当运行状态良好的节点收到删除请求时,直接删除了本地数据A。此时崩溃节点无法响应删除请求,因此A数据保留。当崩溃节点恢复时,Cassandra根据读一致性,会将A数据从崩溃节点恢复到所有已删除的节点上,因此删除操作失败。
使用tombstone机制,本质是插入一条tombstone数据,此数据包含了partition key, clustering key 和 deletion time(tombstone的数据格式参考:About Deletes and Tombstones in Cassandra)。Cassandra 拥有一个默认参数gc_grace_seconds(默认为10天)。此参数表示tombstone数据能够保留多长时间才会被真正删除。当Cassandra进行compaction操作并且一条数据的deletion time + gc_grace_seconds小于当前时间时,此条数据才会被真正删除。
使用gc_grace_seconds参数的原因:考虑不存在gc_grace_seconds的情况,如果一个节点奔溃了,此时其他节点创建了tombstone,如果在奔溃节点还未恢复的情况下,Cassandra进行了Compaction操作,那么tombstone数据就将被删除,此时崩溃节点的数据其实还在保存中,崩溃节点恢复后出于一致性,会复制此僵尸数据(zombie)到其他节点,这样删除操作失败。因此使用gc_grace_seconds参数,可以给予崩溃节点充分的恢复时间从而同步tombstone数据。但是如果在gc_grace_seconds时间内奔溃节点未恢复,那么删除操作依旧会执行失败。