如何删除Cassandra中的大量行(并避免潜在的墓碑问题)?

时间:2014-12-29 03:04:14

标签: cassandra tombstone

过度简化数据模型,我们有以下表格:

CREATE TABLE storage (
    id timeuuid,
    foo blob,
    bar blob,
    baz blob,
    data blob,
    PRIMARY KEY ((id))
);

CREATE TABLE storage_idx_by_foo (
    foo blob,
    id timeuuid,
    PRIMARY KEY ((foo), id)
);

CREATE TABLE storage_idx_by_bar (
    bar blob,
    id timeuuid,
    PRIMARY KEY ((bar), id)
);

CREATE TABLE storage_idx_by_baz (
    baz blob,
    id timeuuid,
    PRIMARY KEY ((baz), id)
);

第一个表可以包含数亿条记录,我们使用索引表根据一些可查询参数轻松定位数据。

当我们必须清除基于 foo bar baz 的数据时,问题就出现了。我们必须从 storage 表和所有索引表中删除该条目。所以,假设我们删除了例如 foo ,采取的措施是:

  1. 根据相应的索引表(在本例中为 storage_idx_by_foo )查找ID
  2. 获取 baz 并从存储表中删除记录
  3. 从其余两个索引表中删除记录(我们有 bar / baz id
  4. 步骤3是一个问题,因为墓碑 - 如果我们从剩下的两个索引表中删除数百万条记录(意思不是通过分区),Cassandra将创建数百万个墓碑,这将导致很多在压实发生之前读取数据时头痛。

    一些快速的头脑风暴表明我们可以:

    1. 清除过程后强行压缩
    2. 不从这两个表中删除并处理指向代码
    3. 中不存在的东西的索引条目
    4. ????
    5. 建议的方法是什么?我猜其他Cassandra用户也遇到过这个问题,但除了“你正在做Cassandra错误”之外我在网上找不到任何建议。我认为我们不能以不同的方式对我们的数据建模以避免这个问题(或者如果我们可以的话,我也会对这方面的反馈表示赞赏)。

      目前,我们倾向于选项2,尽管我不喜欢垃圾留在数据库中的想法。

1 个答案:

答案 0 :(得分:2)

“你可能正在做cassandra错误”!!

您有什么疑问?试图在不知道查询的情况下进行推广通常会导致Cassandra中的模型不佳。建模应该是查询驱动的。即使您不知道确切的查询,您也应该知道查询的(即您要编入索引的内容等)。

如果您知道要在foo,bar和baz上编制索引,请考虑是否可以添加一些可用作分区键的约束。对于您概述的模式,您将遇到的一个主要问题是,如果相同的foo值(或条形值或baz值)有大量条目。虽然从理论上讲,分区可能非常大,但是分区大于几十兆或大约一百个megs会因性能而。因此,在进行宽行时,请考虑如何限制宽行大小。如果每个foo或bar或baz有几百到几千个条目,这将不是问题。否则,你会遇到麻烦。在这种情况下,您可能想要添加一些用于分组。例如,看看您是否可以将查询限制为“在此日期获取foo x的数据”或“获取此国家/邮政编码/等的foo x数据”。这将防止巨大的行。

手动索引的另一个问题是索引更新不是原子的,索引可能与实际数据位于不同的节点上。如果您可以将查询限制为存储桶,则架构可能如下所示:

CREATE TABLE storage (
    some_bucket text,
    id timeuuid,
    foo blob,
    bar blob,
    baz blob,
    data blob,
    PRIMARY KEY (somebucket, id)
);

甚至您可以按原样保留存储空间并将索引设为:

CREATE TABLE storage (
    bucket text,
    foo blob,
    bar blob,
    baz blob,
    data blob,
    PRIMARY KEY (bucket)
);

在这两种情况下,您都会在foo,bar和baz上创建一个cassandra二级索引。这将允许您的查询。记住,当使用二级索引时,总是首先命中一个分区 - 否则它会变成一个群集范围的查询,可能会超时。在Cassandra 3.0中,一个名为全局索引的功能即将推出,旨在减少首先命中分区的需求,但在此之前,命中分区+二级索引,您的查询将快速

现在......关于墓碑的主题。 Cassandra删除将使用墓碑。没有办法解决这个问题。任何LSM数据库都需要压缩,而且无论负载如何,逻辑删除都是cassandra实现稳定写入吞吐量(几乎)的机制。但是你可以做一些事情。如果您可以限制何时发生大量删除,您可以使用nodetool来禁用自动压缩:

http://www.datastax.com/documentation/cassandra/2.1/cassandra/tools/toolsDisableAutoCompaction.html

然后,您可以执行清除,然后强制执行压缩:

http://www.datastax.com/documentation/cassandra/2.1/cassandra/tools/toolsCompact.html

再次启用自动压缩。

这显然不是“整洁”,但是如果您从表中删除了大量数据,而不是全部数据,则会有效。

希望有所帮助。