我在 Datastax 博客中阅读了有关使用 Cassandra 作为队列的陷阱的文章。很快,如果我们有这样的表
CREATE TABLE queues (
name text,
enqueued_at timeuuid,
payload blob,
PRIMARY KEY (name, enqueued_at)
);
并且我们删除已处理的行,随后的选择查询将在读取未处理的行之前扫描太多的墓碑。
SELECT enqueued_at, payload FROM queues WHERE name = 'queue-1'
作为一个潜在的解决方法,作者建议保存最后处理的行的 timeuuid 并在这样的查询中使用它来排除墓碑扫描
SELECT enqueued_at, payload
FROM queues
WHERE name = 'queue-1' AND enqueued_at > 9d1cb818-9d7a-11b6-96ba-60c5470cbf0e
但我无法理解一件事:依靠这种方法是否安全?当然,timeuuid 是按照集群键的时间顺序排序的,但是 Cassandra 是否给我们一些保证,在我们记忆的 timeuuid 之前不会添加任何记录,以防同时写入?例如,如果我们使用now()
函数插入新记录:
INSERT INTO queues VALUES ('queue-1', now(), /*some payload*/)
文档说,now()
在协调节点上生成新的 timeuuid。那么,是否有可能的情况:
- Coordinator1用timeuuid1生成record1并开始写
- Coordinator2 生成timeuuid2 > timeuuid1的 record2并开始写入
- record2的写入完成
- Coordinator3 从 partition 中读取新记录并 memoize timeuuid2
- 记录1的写入完成
- Coordinator3从timeuuid2开始读取新记录,跳过record1
?