我有一个表来存储无法处理的消息,并且我正在通过调度程序每 5 分钟重试一次处理消息。
成功处理消息后,表中的相应行将被删除,因此不应再次处理相同的消息。
从表查询中获取行是SELECT * FROM <table_name>
,因此,如果大量行被删除,我们将面临墓碑问题。表有时间戳作为分区键,message_name(TEXT) 作为集群键,TTL 为 7 天,gc_grace_second 为 2 天
根据我的要求,我需要删除记录,否则将处理重复记录。有什么办法可以避免墓碑问题吗?
我有一个表来存储无法处理的消息,并且我正在通过调度程序每 5 分钟重试一次处理消息。
成功处理消息后,表中的相应行将被删除,因此不应再次处理相同的消息。
从表查询中获取行是SELECT * FROM <table_name>
,因此,如果大量行被删除,我们将面临墓碑问题。表有时间戳作为分区键,message_name(TEXT) 作为集群键,TTL 为 7 天,gc_grace_second 为 2 天
根据我的要求,我需要删除记录,否则将处理重复记录。有什么办法可以避免墓碑问题吗?
所以我在这里看到两个问题。
SELECT * FROM <table_name>
,因为没有WHERE
子句。所以使用 Cassandra,一些数据模型和用例会生成墓碑。到那时,除了设计数据模型以免查询它们之外,没有太多工作要做。
所以我的想法是对表进行不同的分区。
CREATE TABLE messages (
day TEXT,
message_time TIMESTAMP,
message_text TEXT,
PRIMARY KEY ((day),message_time))
WITH CLUSTERING ORDER BY (message_time DESC);
使用此模型,您可以查询特定day
. 您还可以在day
和上运行范围查询message_time
。前任:
SELECT * FROM messages
WHERE day='20210827'
AND message_time > '2021-08-27 04:00';
这将构建一个包含所有消息的结果集,因为2021-08-27 04:00
. 在请求的时间范围之外(在这种情况下,在 04:00 之前)生成的任何墓碑都不会被查询。
请注意(基于删除模式)您仍然可以在给定时间范围内拥有墓碑。但是这里的想法是,该WHERE
子句限制了“爆炸半径”,因此查询较少数量的墓碑应该不是问题。
不幸的是,没有快速解决您的问题的方法。
您面临的挑战是您将 Cassandra 用作队列,这不是一个好主意,因为您正好遇到了墓碑地狱。我相信您现在已经看过这篇博客文章,其中谈到队列和类似队列的数据集是 Cassandra 的反模式。
如果您在存储桶中对数据进行不同的建模,每个存储桶映射到一个表,则可以避免生成大量墓碑。处理完存储桶中的所有项目后,TRUNCATE
表。这个想法来自 Ryan Svihla 在他的博客文章Understanding Deletes 中他通过“分区表”的想法。干杯!