没有分区键的 Cassandra 查询 table

Cassandra query table without partition key

作为迁移作业的一部分,我正在尝试从 table 中提取数据。

架构如下:

CREATE TABLE IF NOT EXISTS ${keyspace}.entries (
    username text,

    entry_type int,

    entry_id text,

    PRIMARY KEY ((username, entry_type), entry_id)
);

为了查询table我们需要分区键,主键的第一部分。 因此,如果我们知道 usernameentry_type,我们可以查询 table.

在这种情况下,username 可以是任何值,但 entry_type 是 0-9 范围内的整数。

在进行提取时,我们为每个用户名迭代 table 10 次,以确保我们尝试所有版本的 entry_type

我们无法再找到任何条目,因为我们已经耗尽了我们的用户名列表。但是我们的 nodetool tablestats 报告 table 中仍有数据,甚至有千兆字节。因此我们假设 table 不为空。

但我无法找到一种方法来检查 table 以找出 table 中保留的用户名。如果我可以检查它,我可以将留在 table 中的用户名添加到我们的提取作业中,最终我们可以耗尽 table。但我不能简单地查询 table 这样的:

SELECT * FROM ${keyspace}.entries LIMIT 1

因为 cassandra 需要分区键才能进行有意义的查询。

我怎样才能弄清楚我们的 table 中还剩下什么?

根据评论,迁移过程包括来自 Cassandra 的 DELETE 操作 table,但引擎在实际从磁盘中删除受影响的记录之前会有延迟;这个过程由墓碑和 table 的 gc_grace_seconds 属性在内部控制。这个延迟的原因在这个blog entry中有充分的解释,对于一个tl dr,如果默认值仍然存在,Cassandra从执行删除之前至少需要经过10天(864,000秒)实际删除数据。

对于您的情况,一种处理方法是:

  1. 确保您所有的节点都是 "Up" 和 "Healthy" (UN)
  2. 减少你的table的gc_grace_seconds属性,在例子中,它会设置为1分钟,而默认是

    ALTER TABLE .entries with GC_GRACE_SECONDS = 60;

  3. 手动压缩table:

    nodetool 压缩条目

  4. 该过程完成后,nodetool tablestats 应该是最新的

为了回答您的第一个问题,我想对 gc_grace_seconds 属性 进行更多阐述。

在 Cassandra 中,数据的删除方式与 RDBMS 中的不同。 Cassandra 专为高写入吞吐量而设计,并避免先读后写。所以在 Cassandra 中,删除实际上是更新,而更新实际上是插入。写入 “逻辑删除” 标记以指示数据现在(逻辑上)被删除(也称为软删除)。必须删除标记为逻辑删除的记录才能收回存储 space。这是由一个名为 Compaction 的过程完成的。但请记住,仅在称为 gc_grace_seconds 的特定秒数后,墓碑才有资格进行物理删除/垃圾收集。这是一个非常好的博客,可以详细阅读:https://thelastpickle.com/blog/2016/07/27/about-deletes-and-tombstones.html

现在您可能正在查看 gc_grace_seconds 之前的 table 大小,并且数据仍然存在。

关于您的第二个问题,您希望在不提供分区键的情况下从 table 中获取一些样本。您可以使用 Spark 分析您的 table 内容。 Spark Cassandra Connector 允许您创建 Java 使用 Spark 分析数据库数据的应用程序。您可以按照文章/文档编写一个快速方便的 spark 应用程序来分析 Cassandra 数据。

https://www.instaclustr.com/support/documentation/cassandra-add-ons/apache-spark/using-spark-to-sample-data-from-one-cassandra-cluster-and-write-to-another/

https://docs.datastax.com/en/dse/6.0/dse-dev/datastax_enterprise/spark/sparkJavaApi.html

我建议您在迁移时不要删除记录。而是首先完成迁移,然后 post 进行快速验证/验证以确保所有记录都成功迁移(这种使用可以轻松地使用 Spark 购买比较来自新旧 table 的数据帧)。 Post 成功验证截断旧的 table,因为截断不会创建墓碑,因此效率更高。请注意,大量的墓碑不利于集群健康。