【问题标题】:How to save data in cassandra conditionally only if properties did not change仅当属性未更改时,如何有条件地将数据保存在 cassandra 中
【发布时间】:2015-05-21 14:55:40
【问题描述】:

我们有很多属性的文章数据模型。这是我们的表格模型:

CREATE TABLE articles (
    organization_id bigint,
    gtin text,
    barcodes text,
    code text,
    brand text,
    season text,
    name text,
    option text,
    style text,
    color text,
    sizes text,
    supplier text,
    category text,
    prices text,
    last_updated timeuuid,
    content_hash uuid,
    markdown boolean,
    PRIMARY KEY (organization_id, gtin)
) WITH COMMENT='Articles';

gtin 唯一标识文章,我们将组织的所有文章保存在一行中。只有在某些情况发生变化时,我们才会更新每篇文章。这很重要,因为如果文章发生更改,我们会更新 last_updated 字段,并且外部设备知道要同步哪些文章,因为它们在上次同步时有信息。

为此我们又添加了一张表格:

CREATE TABLE articles_by_last_updated (
    organization_id bigint,
    gtin text,
    barcodes text,
    code text,
    brand text,
    season text,
    name text,
    option text,
    style text,
    color text,
    sizes text,
    supplier text,
    category text,
    prices text,
    last_updated timeuuid,
    content_hash uuid,
    markdown boolean,
    PRIMARY KEY (organization_id, last_updated)
) WITH CLUSTERING ORDER BY (last_updated ASC) AND COMMENT='Articles by last updated field';

因此我们可以轻松地返回在某个时间点之后更新的所有文章。必须从每个 gtin 的重复项中清除该表,因为我们每天导入文章并从移动设备完成同步,因此我们希望保持数据集较小(理论上我们可以将所有内容保存在该表中,并用最新信息覆盖,但这会创建大型数据集在同步之间,因此我们开始从该表中删除,并且要删除我们需要从第一个表中知道 last_updated

我们现在面临的问题是:

  1. 为了检查文章字段是否更新,我们需要先读再写(我们部分解决了这个问题,content_hash 字段是所有字段的哈希值,因此我们读取传入文章的哈希值并将其与数据库中的值进行比较)
  2. 我们正在第二个表中删除和插入,因为我们需要唯一的 gtins 那里(只需要发送到设备的最新更改,而不是重复的文章),这会产生大量的墓碑
  3. 我们可以通过许多不同的字段组合来添加搜索功能

问题:

  1. cassandra 是这种数据的好选择,还是我们应该将其移动到其他存储(或者甚至将 elasticsearchcassandra 组合在一起,我们可以索引一段时间后的更改,而 cassandra 只能保存每个 @ 的主数据987654330@)?
  2. 能否更好地为我们的用例建模数据,以避免在第二个表中先读取再写入或删除?

更新 只是为了澄清用例:其他设备正在与分页同步(发送last_sync_dateskipcount)所以我们需要包含所有文章信息的表格,按last_updated排序,没有重复,可以按last_updated搜索

【问题讨论】:

标签: cassandra data-modeling cassandra-2.1 nosql


【解决方案1】:

如果您使用 Cassandra 2.1.1 及更高版本,则可以在 UPDATE 语句的 IF 部分使用“不等于”比较(请参阅CASSANDRA-6839 JIRA 问题),以确保仅在有任何内容时更新数据改变了。你的陈述看起来像这样:

UPDATE articles 
SET 
  barcodes = <barcodes>, 
  ... = <...>, 
  last_updated = <last_updated> 
WHERE 
  organization_id = <organization_id> 
  AND gtin = <gtin> 
IF content_hash != <content_hash>;

对于您的第二个表,您不需要复制第一个表中的整个数据,因为您可以执行以下操作:

像这样创建你的表:

CREATE TABLE articles_by_last_updated (
    organization_id bigint,
    last_updated timeuuid,
    gtin text,
    PRIMARY KEY (organization_id, last_updated)
) WITH CLUSTERING ORDER BY (last_updated ASC) AND COMMENT='Articles by last updated field';

一旦您更新了第一个表,您可以再次读取该 gtinlast_updated 值,如果它等于或大于您传入的 last_updated 值,那么您知道更新是成功(通过您或其他进程),因此您现在可以继续将检索到的 last_updated 值插入到第二个表中。您无需删除此更新的记录。我假设您可以在应用程序端创建不同的更新gtin 列表,如果您定期进行轮询(使用范围查询),我假设这会提取合理数量的数据。例如,您可以在几个轮询周期后对这些新记录进行 TTL 处理,以消除手动删除的必要性。然后,在您发现gtins 受到影响后,您执行第二个查询,从第一个表中提取所有数据。然后,您可以对更新的日期进行第二次完整性检查,以避免发送任何应该在下一次更新时发送的内容(当然,如果有必要的话)。

HTH。

【讨论】:

  • 谢谢@Roman,第一部分很有帮助,我试过了,但在你张贴换票之前。至于第二部分,其他设备正在与分页同步(发送last_sync_dateskipcount)所以我需要包含所有文章信息的表格,按last_updated 排序,没有重复,可按last_updated 搜索
  • 那么在分页期间保持一致性可能更为重要。想象一下,如果您获取了 100 行,那么在获取下一个 100 行之前,您从先前检索到的结果中删除了 10 行,因为文章已经更新。然后,您的下一次提取将提取之前的第 111 行到第 210 行,基本上不会发送第 101-110 行的更新。
猜你喜欢
  • 2013-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-09
  • 2022-07-07
  • 1970-01-01
相关资源
最近更新 更多