替代GUID并考虑Scalablity和友好URL

Ida*_*ter 7 asp.net friendly-url guid

我决定使用GUID作为我的许多项目数据库表的主键.我认为这是一个很好的做法,特别是考虑到可扩展性,备份和恢复.问题是我不想使用常规GUID并搜索替代方法.我真的很想知道Pinterest我用什么作为主键.当您查看URL时,您会看到如下内容:

http://pinterest.com/pin/275001120966638272/
Run Code Online (Sandbox Code Playgroud)

我更喜欢数字表示,即使是存储为字符串.有没有办法实现这个目标?

此外,youtube还使用了一种不同的散列技术,我无法弄清楚:

http://www.youtube.com/watch?v=kOXFLI6fd5A
Run Code Online (Sandbox Code Playgroud)

这让我想起了缩短网址的方案.

我更喜欢最短的一个,但我知道它不能保证是唯一的.我首先考虑做这样的事情:

 DateTime dt1970 = new DateTime(1970, 1, 1);
 DateTime current = DateTime.Now;
 TimeSpan span = current - dt1970;
Run Code Online (Sandbox Code Playgroud)

结果示例:

1350433430523.66
Run Code Online (Sandbox Code Playgroud)

打印自1970年以来的总毫秒数,但如果我每秒有数十万次写入会发生什么.

我主要更喜欢非BIGINT自动增量解决方案,因为使用第三方工具扩展数据库以及不太有问题的备份/恢复功能会减少很少的麻烦,因为我可以在服务器之间传输数据,如果我想要的话.

另一种复杂的方法是根据我的应用定制解决方案.在数据库中,主键还将包含用户名(唯一且用户无法更改),因此我可以将名称的数值与毫秒数组合,这将为我提供唯一的数字字符串.由于用户不以如此高的速率插入数据,因此数字ID保证是唯一的.我也可以删除最后5个数字并仍然获得一个唯一的ID,因为我假设用户不会以每秒超过1的速度插入数据,但我可能不会这样做(你怎么看?这个想法?)

所以我请求你的帮助.我的数据假设增长非常大,每年2TB,每秒有10万个新行.我希望URL看起来尽可能"友好",并且不想使用"常规"GUID.

我正在使用ASP.NET 4.5和MySQL开发我的应用程序

谢谢.

Muh*_*eed 6

碰撞表

对于像 GUID 这样的 YouTube,您可以看到这个答案。他们基本上保留了他们正在生成的所有随机视频 ID 的数据库表。当他们请求一个新的时,他们检查表是否有任何冲突。如果他们发现碰撞,他们会尝试生成一个新的碰撞。

长主键

您可以使用long(eg 275001120966638272) 作为主键,但是如果您有多个服务器生成唯一标识符,则必须以某种方式对它们进行分区或引入全局锁,因此每个服务器不会生成相同的唯一标识符。

Twitter 雪花 ID

longID分区问题的一种解决方案是使用雪花 ID。这就是Twitter用来生成其 ID 的内容。所有生成的 ID 由以下部分组成:

  • 以毫秒为单位的纪元时间戳 - 41 位(使用自定义纪元为我们提供 69 年)
  • 已配置的机器 ID - 10 位(最多为我们提供 1024 台机器)
  • 序列号 - 12 位(每台机器的本地计数器,每 4096 次翻转一次)

保留一位额外的位以供将来使用。由于 ID 使用时间戳作为第一个组件,因此它们是时间可排序的(这对查询性能非常重要)。

Base64 编码的 GUID

您可以使用将 a 编码为 base64 字符串的ShortGuidGUID。缺点是输出有点难看(例如00amyWGct0y_ze4lIsj2Mw)并且它区分大小写,如果您使用小写它们可能对 URL不利。

Base32 编码的 GUID

还有GUID's 的base32 编码,您可以查看答案。它们比上面的 ShortGuid 稍长(例如lt7fz44kdqlu5pt7wnyzmu4ov4),但优点是它们可以全部小写。

多重因素

我一直在考虑的一种替代方法是引入多种因素,例如,如果 Pintrest 使用用户名和 ID 以获得额外的唯一性:

https://pinterest.com/some-user/1

这里的 ID1对用户来说是唯一的some-user,可以是他们发表的帖子数,即他们的下一篇帖子是2。您也可以将 YouTube 的方法与他们的视频 ID 一起使用,但特定于用户,这可能会导致一些短得可笑的 URL。


Fli*_*int 5

唯一键的第一个、最简单和实用的场景是写入顺序的递增编号序列,这表示在本地范围内提供唯一编号的数据库内的记录编号:这是 - 经常满足 -应用程序级别的要求

接下来,通常使用基于时间和计数器串联的数值方法来确保同一货车中的并发事务在写入之前具有唯一的 id。

当系统变得高度线程化和分布式时,比如在高度并发的情况下,在它们成为扩展的惩罚之前,需要放宽一些约束。

作为主键的通用唯一标识符

是的,这是一个很好的做法。

  • 键参考系统可以提供与底层数据库系统的独立性。
  • 这可以确保在诱发场景发生时为数据库提供更高级别的完整性:备份、还原、扩展、迁移,并可能证明某些真实性。

Alexander Marquardt(MongoDB的高级咨询工程师)撰写的这篇文章Generating Globally Unique Identifiers for Use with MongoDB详细介绍了这个问题,并提供了一些有关数据库和信息学的见解。

UUID 是 128 位长。它们引入了足够高的熵,以确保标签的实际唯一性。它们可以用 32 个十六进制字符串表示。足以写出几千亿个十亿的十进制数。

以下是在考虑总体原则和分析时可能会出现的一些问题:

  1. 数据库和唯一资源位置的主键应该作为两个不同的实体保存吗?

  2. 这种编号是否会破坏系统中的顺序性?

  3. 提供机器主机号(h),后跟用户号(u)(t)写入索引的时间是否能(i) 保证 PKhuti保持唯一?

现在考虑数据库系统:

  • 主键应保留为数字(无论是六进制)
  • 数据库系统依赖于它,这意味着性能方面的考虑。
  • 它们的大小应该是固定的,
  • 系统必须快速响应以判断它是否可能正在处理 PK。

哈希德

Youtube 的哈希技术是hashids

这是一个不错的选择:散列是shorts,长度可以控制,字母可以自定义,它是可逆的(并且像对主键的简短引用一样有趣),它可以使用salt。它旨在散列正数。

然而,它一个散列,因此存在发生冲突的可能性。它们可以被检测到:在存储它们之前违反了唯一约束,在这种情况下,应该再次运行。

考虑对这个答案的评论,以确定可以从缩短的 sha1+b64 配方中获得多少熵。 为了预测碰撞场景,需要估计数据库的未来维度,即潜在的记录数。推荐阅读:Z.Bloom,ID需要多长时间?

自纪元以来的毫秒数

引自上一篇文章,该文章以漂亮的综合风格提供了手头问题的大部分答案

但是,自 1970 年以来,您可能不需要每次都进行编码。如果您只想保持最近的记录彼此接近,您只需要足够的值来确保您没有比数据库一次缓存更多的具有相同前缀的值