2

对于 DyanamoDB 支持的 Web 应用程序,我需要生成唯一、稳定的 URL,这些 URL 可靠地引用 DynamoDB 表中的唯一行。

过去,对于 PostgreSQL 支持的应用程序,我使用自动递增整数作为主键并使用整数的hashid得到了很好的结果:

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 的 hashid 更长:

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

在这里做什么最好/最安全?我预计此表不会有繁重的写入负载,所以我是否需要分解并实现一个带有条件写入的自动递增整数方案?

更新:

我刚刚意识到,如果我右移 UUID1 的 32 位,它似乎是相当独特的:

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

但这会回来咬我吗?:D

更新 2:

要回答评论中的一些问题:

我的应用程序将是唯一一个写入此表的应用程序。

该应用程序是用 Python 编写的。

表的数据架构使用用户 ID 的哈希键和根据行中存储的内容而变化的排序键。假设我正在存储用户记录、用户的项目和项目中包含的文档。我可能最终会拥有一个全局二级索引来支持基于 URL hashid 的查询,除非 hashid 和记录的主键最终是等价的。

该表的常见查询将是:

  1. 另一个 GSI 支持的电子邮件用户(用于登录)
  2. 所有用户(通过哈希键)
  3. 一个用户的所有项目(使用 hash key 和 sort key beginswith()
  4. 一个特定的项目(由正在讨论的 GSI 支持)
  5. 特定项目中的所有文档(哈希键和排序键beginswith()
  6. 单个文件(由 GSI 支持,讨论中)
4

0 回答 0