Cassandra对更新和集群密钥的处理是如何交互的?
- Cassandra在写入记录后从未真正更新记录,它使用tombstone将旧版本标记为已删除,并记录旧版本和新版本,直到旧版本最终被内务处理删除:一种垃圾收集形式
- 集群密钥是使用一些魔术来实现的,它将数据记录在只有分区密钥的"真实"记录中
我突然意识到,这两个功能可能交互不好,导致产生过多的垃圾。
考虑这个模式:
CREATE TABLE t (
p int,
c int,
d string,
PRIMARY KEY ((p), c),
);
执行以下插入后:
INSERT INTO t (p, c, d) VALUE (1, 1, "text-1");
INSERT INTO t (p, c, d) VALUE (1, 2, "text-2");
是否存在保存(1, 1, "text-1")
数据的逻辑删除标记记录和同时保存(1, 1, "text-1")
和(1, 2, "text-2")
数据的新记录?也就是说,第二个插入是否被实现为分区密钥(p
)为1的"真实"记录的更新?
您的假设不正确。在您的模式中,p
是分区(或"行")键,c
是集群列。Cassandra是一个柱状存储,因此写入本质上是附加到分区的稀疏有序列的集合。可以通过创建复合行键和列名来实现额外的嵌套,在您的情况下,这可以转换为如下的存储模型:
Row Key: 1 =>
1:d => "text-1"
2:d => "text-2"
如果您要插入另一个分区密钥,如下所示:
INSERT INTO t (p, c, d) VALUE (2, 1, "text-1");
你的存储模型应该是这样的:
Row Key: 1 =>
1:d => "text-1"
2:d => "text-2"
Row Key: 2 =>
1:d => "text-1"
因此,您可以观察到这些列值(1:d
、2:d
等)是独立处理的。假设您删除其中一个值:
DELETE FROM t WHERE p = 1 AND c = 1;
你的结果是:
Row Key: 1 =>
1:d => "text-1" + [tombstone]
2:d => "text-2"
Row Key: 2 =>
1:d => "text-1"
其中tombstone将具有更大的时间戳,因此"覆盖"原始值,直到压缩将其清除。具体何时发生取决于许多因素(gc_grace_seconds
的值、压缩策略、工作负载等)。
据我所知,Cassandra不会在插入/更新(upstart)时删除记录,它只是将新信息记录为写入,而不会创建tombstone。当读取信息时,它将利用时间戳来确定哪些数据是最新的。在压缩过程中,旧记录将被删除,而tombstone将一直保留到宽限期到期(默认为10天),以帮助保持删除的一致性,从而使它们不会复活。