Как гарантировать монотонно увеличивающееся время при выборе из scylla - PullRequest
4 голосов
/ 15 апреля 2020

У меня есть таблица с timeuuid в качестве ключа кластеризации.

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

I wi sh, чтобы выбрать данные в порядке этого ключа кластеризации со следующей гарантией - если я выберу что-то, то будет быть НИКАКИМИ вставками перед этими записями в будущем (так что я мог бы перебирать записи, проверяя, что произошло, без риска пропустить какие-либо события)

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

Если я сгенерирую timeuuid на клиенте и использовать параллельную вставку для scylla, технически возможно, что недавний timeuuid будет вставлен раньше, чем несколько более старых (скажем, из-за какой-то проблемы с сетью), и я мог бы пропустить эти записи в моих выборках. ?

Я попытался использовать функцию currentTimeUUID, и она, кажется, работает (монотонно увеличивается в пределах одного и того же ключа раздела), но создает много дубликатов (20-40 дубликатов на один и тот же ключ раздела), т.е. с большим количеством записей с одинаковым currentTimeUUID (мне бы очень хотелось, чтобы избежать дубликатов, это сложно съедает процесс выбора и потребляет ненужные ресурсы)

Мне также любопытно, существует ли угроза скачков назад при использовании функции currentTimeUUID?

1 Ответ

4 голосов
/ 16 апреля 2020

EDITED

Кажется, что в 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)
);

и сгенерировав для него значение на клиенте, в некотором смысле случайным образом. Возможно, есть какой-то аспект записи, который, как вы знаете, гарантированно уникален и может использоваться в качестве ключевого столбца кластеризации. Это будет работать лучше, чем случайное поле.

...