对于支持DyanamoDB的Web应用程序,我需要生成唯一且稳定的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'
然后我会在网址中使用它:
http://example.com/random-mutable-title-e763y/
但是,使用DynamoDB时,没有自动递增的主键和UUIDs are recommended instead。
但是,UUID包含128位,并且UUID的哈希值更长:
In [3]: import uuid
In [4]: hasher.encode(uuid.uuid4().int)
Out[4]: '5j257lmv00xwo5pvo132783jv0qkq'
网址过长,或至少是丑陋的:
http://example.com/random-mutable-title-5j257lmv00xwo5pvo132783jv0qkq/
我看到它建议只是mask the 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 hashid的查询,除非hashid和记录的主键最终是等效的。
该表的常见查询将是:
beginswith()
)beginswith()
)