【问题标题】:Cassandra data model with obsolete data removal possibility具有过时数据删除可能性的 Cassandra 数据模型
【发布时间】:2014-06-14 09:24:27
【问题描述】:

我是 cassandra 的新手,想问一下对于此类任务什么是正确的模型设计模式。 我想对未来可能移除的数据进行建模。

我每天有 100,000,000 条这种结构的记录:

  • transaction_id
  • transaction_time
  • transaction_type
  • 用户名
  • ...其他一些信息

我需要按用户名获取数据(我有大约 5,000,000 个用户)。 我还需要通过其 ID 查找交易详情。 大约 30 天后,所有数据都将变得无关紧要,因此需要找到一种方法来删除过时的行。

正如我所发现的,TTL-s 过期的列值,而不是行。 到目前为止,我遇到了这个模型,据我所知,它意味着非常宽的行:

CREATE TABLE user_transactions (
  transaction_date timestamp,    //date part of transactiom
  user_name text,
  transaction_id text,
  transaction_time timestamp,    //original transaction time
  transaction_type int,
  PRIMARY KEY ((transaction_date, user_name), transaction_id)
);

CREATE INDEX idx_user_transactions_uname ON USER_TRANSACTIONS(user_name);
CREATE INDEX idx_user_transactions_tid ON USER_TRANSACTIONS(transaction_id);

但此模型不允许按 transaction_date 删除。 这也构建了具有高基数的索引,这是 cassandra 文档强烈反对的

那么这个任务的正确模型是什么?

编辑:

到目前为止,我提出的丑陋解决方法是为每个日期分区创建一个表。请注意,我将此称为解决方法,而不是解决方案。我还在寻找合适的数据模型

CREATE TABLE user_transactions_YYYYMMDD (
  user_name text,
  transaction_id text,
  transaction_time timestamp, 
  transaction_type int,
  PRIMARY KEY (user_name)
);

YYYYMMDD 是交易的日期部分。我们可以使用 transaction_id 创建类似的表以进行事务查找。可以删除或截断过时的表。

【问题讨论】:

    标签: cassandra bigdata data-modeling cql3 cassandra-2.0


    【解决方案1】:

    也许您应该对数据模型进行非规范化。例如,通过 user_name 查询,您可以使用这样的 cf:

    CREATE TABLE user_transactions (
      transaction_date timestamp,    //date part of transactiom
      user_name text,
      transaction_id text,
      transaction_time timestamp,    //original transaction time
      transaction_type int,
      PRIMARY KEY (user_name, transaction_id)
    );
    

    所以你可以像这样直接使用分区键查询:

    SELECT * FROM user_transactions WHERE user_name = 'USER_NAME';

    对于 id,您可以使用这样的 cf:

    CREATE TABLE user_transactions (
      transaction_date timestamp,    //date part of transactiom
      user_name text,
      transaction_id text,
      transaction_time timestamp,    //original transaction time
      transaction_type int,
      PRIMARY KEY (transaction_id)
    );
    

    所以查询可能是这样的:

    SELECT * FROM user_transactions WHERE transaction_id = 'ID';
    

    通过这种方式,您不需要索引。

    关于 TTL,也许您可​​以通过编程确保同时更新行中的所有列(相同的 cql 语句)。

    【讨论】:

    • 是的,但这些模型不允许我使用指定交易日期的 DELETE 语句删除数据。这就是我试图将交易日期移动到分区键的原因。还有其他方法可以删除旧数据吗?
    • 忘了提到写在表中的数据是不可变的,我从来不需要修改它。
    • 在这种情况下,您可以在transaction_date上创建一个索引,根据该日期查询transaction_id的列表,并使用该列表按transaction_id删除。
    • 您的意思是运行 100,000,000 个单独的 DELETE-s?真的很怀疑 cassandra 是否可以处理这个问题。
    • cassandra 的目标之一是实现高吞吐量。如果 cassandra 可以处理这取决于您使用的集群,但不是因为 cassandra 本身。另一种解决方案是使用我在解决方案的最后一行中提到的 TTL,但是您必须同时更新所有列,因此同时删除所有列。另一件你必须考虑的事情是墓碑,也许你应该减少 cf 中的 gc_grace_seconds 参数以避免在删除过程后生成大量的墓碑。
    【解决方案2】:

    也许我的回答会有点用处。

    我会这样做的:

    CREATE TABLE user_transactions (
      date timestamp,
      user_name text,
      id text,
      type int,
      PRIMARY KEY (id)
    );
    
    CREATE INDEX idx_user_transactions_uname ON user_transactions (user_name);
    

    'transaction_time timestamp' 中不需要,因为这个时间将由 Cassandra 设置到每一列,并且可以通过 WRITETIME(column name) 函数获取。因为您同时写入所有列,所以您可以在任何列上调用此函数。

    INSERT INTO user_transactions ... USING TTL 86400;
    

    将同时使所有列过期。所以不用担心删除行。见这里:Expiring columns

    但据我所知,您不能删除整行 - 键列仍然存在,其他列将写入 NULL。 如果您想手动删除行,或者只是想通过 TTL 估计要删除的行,那么我推荐驱动程序 Astyanax:AllRowsReader All rows query

    确实,作为与 Cassandra 一起工作的驱动程序,我建议您使用 Astyanax。

    【讨论】:

    • Dmitry,这并不重要,但 transaction_time 并不总是与 write_date 匹配。
    • 您确定没有删除整行吗?因为我也确实认为这是真的(到处阅读),但是当我在例如 1 或 2 天后执行 select * 查询时,ttl 为 1 天的项目不再出现。这确实让我感到惊讶;)
    • 不,我不确定。这是我在文档、博客和论坛中读到的内容。您是否尝试过从 CLI 而不是 CQLSH 中查看底层数据的外观?因为 CQL 可能会掩盖和隐藏真正发生的事情(就像复合键和复合键一样)。
    • 确实,似乎 cassandra 驱动程序和 cqlsh 隐藏了它们,当我使用 cassandra-cli 执行“list keyspace”时,已删除的项目仍显示已删除行的 RowKey。将深入研究 cassandra-cli 的内容。
    • 是的。期待这个答案。
    猜你喜欢
    • 2016-07-12
    • 2016-10-18
    • 2015-03-07
    • 2015-03-23
    • 2017-05-14
    • 1970-01-01
    • 2021-12-17
    • 2020-11-17
    • 1970-01-01
    相关资源
    最近更新 更多