首页 > 解决方案 > 从scylla中选择时如何保证timeuuid单调递增

问题描述

我有一个以 timeuuid 作为集群键的表。

CREATE TABLE event (
    domain TEXT,        
    createdAt TIMEUUID,
    kind TEXT,
    PRIMARY KEY (domain, createdAt)
);

我希望按此集群键的顺序选择数据,并提供以下保证 - 如果我选择了某些内容,将来这些记录之前将不会有任何插入(因此我可以遍历记录检查发生的新情况,而不会有跳过任何内容的风险事件)

SELECT kind FROM event WHERE domain = ? AND createdAt > lastCreatedAtWeAreAwareOf

如果我在客户端上生成 timeuuid 并使用并行插入到 scylla,那么从技术上讲,最近的 timeuuid 可能会在几个较旧的之前被首先插入(比如由于说一些网络问题),我可能会在我的选择中错过这些记录。

有什么可能的方法来解决这个问题?

我尝试使用currentTimeUUID函数,它似乎可以工作(在同一个分区键内单调增加)但会创建很多重复项(每个分区键有 20-40 个重复项),即我最终得到了很多完全相同的记录currentTimeUUID(我真的想要一种避免重复的方法,它会使选择过程复杂化并消耗不必要的资源)

我也很好奇使用currentTimeUUID函数时是否存在向后时钟跳跃的威胁?

标签: scyllatimeuuid

解决方案


已编辑

似乎 Scylla 中存在一个错误,即 currentTimeUUID 总是为使用相同的协调器同时完成的写入生成重复项。我在这里创建了一个问题。感谢您提出这个问题。

下面是以前的答案

如果我在客户端上生成 timeuuid 并使用并行插入到 scylla,那么从技术上讲,最近的 timeuuid 可能会在几个较旧的之前被首先插入(比如由于说一些网络问题),我可能会在我的选择中错过这些记录。

澄清一下,所有写入都将以正确的顺序存储。在某个时间点,您将能够以正确的顺序读取足够旧的写入。这意味着一种可能的解决方案是确保 select 不会查询最近的数据。因此,为“迟到”的写入留出一个窗口,让它们到达并排好队。例如,您可以使用这样的选择:

SELECT kind FROM event WHERE domain = ? AND createdAt > lastCreatedAtWeAreAwareOf AND createdAt < now() - 30s

不过,我不知道您是否可以施加这种延迟。这个策略不会给你一个完全的确定性,因为所有延迟超过 30 秒的写入都将被遗漏。

我尝试使用 currentTimeUUID 函数,它似乎可以工作(在同一个分区键内单调增加)但会创建很多重复项(每个分区键有 20-40 个重复项),即我最终得到了很多具有完全相同 currentTimeUUID 的记录(我真的很想要一种避免重复的方法,它会使选择过程复杂化并消耗不必要的资源)

您可以通过引入额外的集群键列来减少集群键重复的机会,例如:

CREATE TABLE event (
    domain TEXT,        
    createdAt TIMEUUID,
    randomBit UUID/int,
    kind TEXT,
    PRIMARY KEY (domain, createdAt, randomBit)
);

并以某种好的随机方式在客户端上为其生成价值。也许您知道记录的某些方面保证是唯一的并且可以用作集群键列。它会比随机场更好。


推荐阅读