【问题标题】:Efficient unique key generation for database entries数据库条目的高效唯一密钥生成
【发布时间】:2012-03-11 12:37:45
【问题描述】:

我目前正在开发注册系统原型。它非常简单,本质上只是一个写入 MongoDB 的 .NET 表单。

我坚持的是一种为每个用户生成唯一 ID/密钥的有效方法。这些 id 必须是人类友好的,因此类似于 7 个字符长的字母数字字符串,例如A1B2C3X。

到目前为止我看到的解决方案只是使用一个简单的函数来生成一个随机字符串,然后检查数据库以查看它是否是唯一的(如果不重复,直到找到一个唯一的)。随着数据库条目数量的增加,这当然会变得越来越昂贵。

我的想法是预先计算唯一 ID 集并将其存储在另一个数据库中。然后,当我需要在用户数据库中添加一个新条目时,我可以从我的 id 数据库中“弹出”一个 id(在恒定时间内),并且知道它在用户数据库中不存在,而无需搜索它。

我敢肯定,以前一定有人做过这样的事情。有没有更好的办法?我不知道为什么我要为此苦苦挣扎。非常感谢您的意见。

【问题讨论】:

  • MongoDB 驱动程序提供的 ObjectId 是否对您的用例不友好?
  • 我打算建议@EkinKoc 建议的内容(如果您对 40 个字符没问题,那就是要走的路)。但是,如果您恰好需要 7 个字符,那么与使用单独的数据库密钥库来弹出值相比,您概述的方法应该更便宜、更简单且更不容易出错。随机 7 个字符的字母数字字符串发生冲突的可能性几乎为零。这是您不应该优化的罕见边缘情况。 (无论如何,用户创建很少见,数据库唯一性检查对于相对罕见的过程来说足够快)。
  • @BenLee:碰撞概率随规模变化:)
  • @SergioTulentsev,是的,但这里有点争议。假设只有大写字母和数字,每个插槽仍有 36 种可能性。 36**7 = 78_364_164_096。 780 亿。一个系统将获得多少用户?即使是 facebook 也很少会遇到使用这种算法的冲突。
  • @LukeEllis:如果这个自定义 id 字段被索引,那么检查非常便宜。

标签: mongodb key unique database


【解决方案1】:

在应用程序中生成一个随机字符串并检查它是否唯一不是一个糟糕的解决方案。不要担心它效率低下,它不是——而且绝对不能与替代品相比。它肯定会比运行db.user.count() 或使用预先计算的 ID 保留一个单独的表更快。你只需要做对。

首先,多久会创建一次新用户?可能不会经常与其他事物相比,因此整个效率讨论实际上是没有实际意义的。其次,有 7 个字符 A-Z、0-9,范围为 36^7 或大约 780 亿。至少可以说,在您开始看到碰撞之前还需要一段时间。

如果你只是这样做,除非发生冲突(这极不可能),否则不会产生任何性能损失:

  • 生成唯一的用户 ID
  • 插入您的用户对象,使用用户 ID 作为 _id 的值
  • 检查重复键错误(如何执行此操作取决于语言和驱动程序,但可能涉及运行getLastError 命令)。
  • 如果出现重复键错误,请通过生成新用户 ID 重新开始

这样只有在发生碰撞时才会有额外的工作(我真的、真的想强调这非常不可能)。

还有另一种生成唯一用户 ID 的方法:获取当前的 UNIX 时间戳(精确到秒),附加主机名的哈希值,然后是进程 ID,最后是计数器的当前值。这实际上是 Mongo 的 ObjectId 的生成方式,并保证您可以在每个进程中每秒生成与计数器的最大值一样多的对象(在 Mongo 中为 3 个字节,因此为 1600 万)。如果您对详细信息感兴趣,请参阅 ObjectId 上的文档:http://www.mongodb.org/display/DOCS/Object+IDs

它具有您的用户 ID 会自然地按创建顺序排序的属性,但它有 12 个字节长,因此比您的 7 个字符长一点,很遗憾。您可以使用相同的方法并跳过主机名/pid,并将计数器(如果您愿意,也可以是随机数)缩短到两个字节,然后您将减少到 6 个字节,这可能会被压缩到大约 9字符 A-Z,0-9。

【讨论】:

  • 感谢您的详细回答。您的解决方案听起来是最简单的。现在使用 _id 插入然后检查重复密钥错误而不是手动检查冲突(在应用程序中)然后插入是有意义的。我认为这种微妙的差异让我担心解决方案的效率,正如您正确指出的那样,只要您正确地执行,它就没有道理。再次感谢。
猜你喜欢
  • 2010-09-08
  • 2023-04-04
  • 2021-08-05
  • 2013-07-18
  • 2012-04-09
  • 1970-01-01
  • 2015-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多