如何仅在属性未更改的情况下有条件地在cassandra中保存数据
How to save data in cassandra conditionally only if properties did not change
我们的文章数据模型有很多属性。这是我们的 table 模型:
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
字段,并且外部设备知道要同步哪些文章,因为它们在上次同步时有信息。
为此我们又添加了一个 table:
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';
所以我们可以很容易地 return 所有在特定时间点后更新的文章。这个 table 必须从每个 gtin 的重复项中清除,因为我们每天导入文章并且同步是从移动设备完成的,所以我们希望保持数据集小(理论上我们可以保存 table 中的所有内容并覆盖具有最新信息,但在同步之间创建了大型数据集,因此我们开始从中删除 table,要删除,我们需要先了解 last_updated
table)
我们现在面临的问题是:
- 为了检查文章字段是否更新,我们需要先读后写(我们使用
content_hash
字段部分解决了这个问题,它是所有字段的哈希值,因此我们读取并比较传入文章的哈希值与值在数据库中)
- 我们正在删除和插入第二个 table 因为我们需要唯一
gtins
那里(只需要最新的更改发送到设备,而不是重复的文章)这会产生大量的墓碑
- 我们可以通过许多不同的字段组合添加搜索功能
问题:
- cassandra 是这种数据的好选择,还是我们应该将其移动到其他存储(或者甚至将
elasticsearch
和 cassandra
组合在一起,我们可以在时间后索引更改,cassandra 可以根据 gtin
)? 仅保留主数据
- 能否针对我们的用例更好地建模数据,以避免在第二个 table 中先读后写或删除?
更新
只是为了澄清用例:其他设备正在与分页同步(发送 last_sync_date
和 skip
和 count
)所以我们需要 table 所有文章信息,按 [=12 排序=] 无重复且可按 last_updated
搜索
如果您使用的是 Cassandra 2.1.1 及更高版本,则可以在 UPDATE 语句的 IF 部分使用 "not equal" 比较(参见 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>;
对于第二个 table,您不需要复制第一个 table 的全部数据,因为您可以执行以下操作:
像这样创建你的 table:
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';
更新第一个 table 后,您可以再次读取 gtin
的 last_updated
值,如果它等于或大于 last_updated
您传入的值,然后您知道更新成功(通过您或其他进程),因此您现在可以继续并将检索到的 last_updated
值插入第二个 table。您不需要删除此更新的记录。我假设您可以在应用程序端创建不同的更新 gtin
列表,如果您定期进行轮询(使用范围查询),我假设这会提取合理数量的数据。例如,您可以在几个轮询周期后对这些新记录进行 TTL,以消除手动删除的必要性。然后,在您发现 gtins
受到影响后,您将执行第二个查询,从第一个 table 中提取所有数据。然后,您可以 运行 对更新日期进行第二次健全性检查,以避免发送任何应该在下一次更新时发送的内容(当然,如果有必要)。
HTH.
我们的文章数据模型有很多属性。这是我们的 table 模型:
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
字段,并且外部设备知道要同步哪些文章,因为它们在上次同步时有信息。
为此我们又添加了一个 table:
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';
所以我们可以很容易地 return 所有在特定时间点后更新的文章。这个 table 必须从每个 gtin 的重复项中清除,因为我们每天导入文章并且同步是从移动设备完成的,所以我们希望保持数据集小(理论上我们可以保存 table 中的所有内容并覆盖具有最新信息,但在同步之间创建了大型数据集,因此我们开始从中删除 table,要删除,我们需要先了解 last_updated
table)
我们现在面临的问题是:
- 为了检查文章字段是否更新,我们需要先读后写(我们使用
content_hash
字段部分解决了这个问题,它是所有字段的哈希值,因此我们读取并比较传入文章的哈希值与值在数据库中) - 我们正在删除和插入第二个 table 因为我们需要唯一
gtins
那里(只需要最新的更改发送到设备,而不是重复的文章)这会产生大量的墓碑 - 我们可以通过许多不同的字段组合添加搜索功能
问题:
- cassandra 是这种数据的好选择,还是我们应该将其移动到其他存储(或者甚至将
elasticsearch
和cassandra
组合在一起,我们可以在时间后索引更改,cassandra 可以根据gtin
)? 仅保留主数据
- 能否针对我们的用例更好地建模数据,以避免在第二个 table 中先读后写或删除?
更新
只是为了澄清用例:其他设备正在与分页同步(发送 last_sync_date
和 skip
和 count
)所以我们需要 table 所有文章信息,按 [=12 排序=] 无重复且可按 last_updated
如果您使用的是 Cassandra 2.1.1 及更高版本,则可以在 UPDATE 语句的 IF 部分使用 "not equal" 比较(参见 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>;
对于第二个 table,您不需要复制第一个 table 的全部数据,因为您可以执行以下操作:
像这样创建你的 table:
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';
更新第一个 table 后,您可以再次读取 gtin
的 last_updated
值,如果它等于或大于 last_updated
您传入的值,然后您知道更新成功(通过您或其他进程),因此您现在可以继续并将检索到的 last_updated
值插入第二个 table。您不需要删除此更新的记录。我假设您可以在应用程序端创建不同的更新 gtin
列表,如果您定期进行轮询(使用范围查询),我假设这会提取合理数量的数据。例如,您可以在几个轮询周期后对这些新记录进行 TTL,以消除手动删除的必要性。然后,在您发现 gtins
受到影响后,您将执行第二个查询,从第一个 table 中提取所有数据。然后,您可以 运行 对更新日期进行第二次健全性检查,以避免发送任何应该在下一次更新时发送的内容(当然,如果有必要)。
HTH.