Создание уникального идентификатора для DynamoDB с меньшим количеством бит, чем UUID

Для веб-приложения, поддерживаемого DynamoDB, мне нужно сгенерировать уникальные стабильные URL-адреса, которые надежно ссылаются на уникальные строки в таблице DynamoDB.

В прошлом для приложения, поддерживаемого PostgreSQL, у меня были хорошие результаты от использования автоинкрементного целого числа в качестве первичного ключа и использования хэш целого числа:

In [1]: import hashids

In [2]: hasher = hashids.Hashids(min_length=5, alphabet='abcdefghijklmnopqrstuvwxyz0123456789')

In [3]: hasher.encode(12345)
Out[2]: 'e763y'

Затем я бы использовал это в URL-адресе:

http://example.com/random-mutable-title-e763y/

Однако в DynamoDB нет автоматически увеличивающихся первичных ключей, и вместо них рекомендуются UUID.

Однако UUID содержат 128 бит, а хеш-код UUID намного длиннее:

In [3]: import uuid

In [4]: hasher.encode(uuid.uuid4().int)
Out[4]: '5j257lmv00xwo5pvo132783jv0qkq'

Это слишком долго для URL-адреса или, по крайней мере, просто уродливо:

http://example.com/random-mutable-title-5j257lmv00xwo5pvo132783jv0qkq/

Я видел, что рекомендуется просто маскировать UUID:

In [5]: hasher.encode((uuid.uuid4().int & (1 << 64) - 1))
Out[5]: 'v0qnq92ml7oj382'

Но даже это кажется немного длинным:

http://example.com/random-mutable-title-v0qnq92ml7oj382/

Я мог бы отпилить больше битов:

In [6]: hasher.encode((uuid.uuid4().int & (1 << 32) - 1))
Out[6]: 'lj044pkn'

Но это кажется немного опасным:

In [7]: len(set(uuid.uuid4().int & (1 << 32) - 1 for _ in range(100000)))
Out[7]: 99999

Что здесь лучше/безопаснее всего делать? Я не ожидаю большой нагрузки на запись в эту таблицу, так что мне нужно разбить и реализовать схему целочисленного автоинкремента с условной записью?

Обновление:

Я только что понял, что если я сдвину вправо 32 бита UUID1, он будет довольно уникальным:

In [8]: len(set(uuid.uuid1().int >> 32 for _ in range(1000000)))
Out[8]: 1000000

Но вернется ли это, чтобы укусить меня? :D

Обновление 2:

Чтобы ответить на некоторые вопросы из комментариев:

Мое приложение будет единственным, записывающим в эту таблицу.

Приложение написано на Python.

Схема данных для таблицы использует хэш-ключ для идентификатора пользователя и ключ сортировки, который зависит от того, что хранится в строке. Допустим, я храню записи пользователей, проекты пользователей и документы, содержащиеся в проектах. Я, вероятно, в конечном итоге получу глобальный вторичный индекс для поддержки запросов на основе хэша URL, если только хэш и первичный ключ записи не будут эквивалентны.

Общие запросы к таблице будут такими:

  1. Пользователь по электронной почте (для входа в систему), поддерживаемый другим GSI
  2. Все пользователи (по хеш-ключу)
  3. Все проекты пользователя (с использованием хеш-ключа и ключа сортировки beginswith())
  4. Конкретный проект (при поддержке обсуждаемой GSI)
  5. Все документы в конкретном проекте (ключ хеширования и ключ сортировки beginswith())
  6. Индивидуальный документ (поддерживается обсуждаемым GSI)

person David Eyk    schedule 23.04.2018    source источник
comment
1) Является ли ваше веб-приложение единственным приложением, записывающим данные в таблицу? Какой язык вы используете? 2) Можете ли вы рассказать нам что-нибудь о вашей схеме данных? Вы уверены, что UUID является правильным первичным ключом? Я бы предположил, что UUID довольно редко является хорошим первичным ключом, поскольку в основном это означает, что вы получаете доступ к таблице только тогда, когда у вас уже есть ключ откуда-то еще.   -  person F_SO_K    schedule 24.04.2018
comment
Я не уверен, что UUID является правильным первичным ключом, поэтому я задаю этот вопрос. :) UUID обычно используются с DynamoDB, потому что клиент БД может безопасно генерировать уникальный идентификатор без согласования. Поэтому я, вероятно, по-прежнему буду использовать UUID для ключей хэша и сортировки и полагаться на GSI для поддержки поиска из слагов URL.   -  person David Eyk    schedule 24.04.2018