6

在我的应用程序中,我让 mongo 通过其 ObjectId 方法生成订单 ID。

但在用户测试中,我们担心订单 ID 会让人“吓人”,即如果您需要通过电话与某人讨论您的订单,读出 24 个字母数字字符有点乏味。

同时,我真的不想存储两个不同的 id,一个是“人类可访问的”,一个是 mongo 内部使用的。

所以我的问题是 - 有没有办法选择一个长度为 6 甚至 8 的 mongo objectId 字符串的子字符串,我可以相当肯定它是唯一的?

例如,如果我有一个像这样的 mongo objectid

id = '4b28dcb61083ed3c809e0416'

也许我可以拿出

human_id = id.substr(0,7);

并确保我的订单总能获得唯一的 ID...

当然,优点是这些是命令,因此是人为创建的,因此每毫秒不会有数百万个。另一方面,如果两个订单具有相同的缩短 id,那将是一个问题......

---更清晰的解释---

我想问我问题的更好方法是:

例如,如果我决定只使用 mongo id 的最后 6 个字符,是否存在某种“概率”度量,这 6 个字符会在给定的一周内重复?

给定一定数量的mongo并行运行,一周内一定数量的用户等。

4

2 回答 2

9

如果您有多个 Web 服务器,具有多个进程,那么确实没有什么可以删除而失去唯一性。

如果您查看 的性质ObjectId

  • 一个 4 字节的值,表示自 Unix 纪元以来的秒数,
  • 一个 3 字节的机器标识符,
  • 一个 2 字节的进程 ID,以及
  • 一个 3 字节的计数器,从一个随机值开始。

您会发现那里没有多少可以安全移除的内容。由于前 4 个字节是时间,因此实现一种以干净和安全的方式删除部分时间戳的算法将是一项挑战。

机器标识符和进程标识符用于有多个服务器和/或进程充当数据库服务器的客户端的情况。如果你放弃了其中任何一个,你最终可能会再次出现重复。最后 3 个字节的随机值用于确保同一机器上同一进程内的两个标识符是唯一的,即使在频繁请求时也是如此。

如果您将其用作订单id,并且希望确保唯一性,我不会从 12 字节数字中删除任何内容,因为它经过精心设计,可提供强大且高效的分布式机制,用于在有许多连接的数据库时生成唯一数字客户。

如果您取 ObjectId ... 的最后 5 个字符,并且在给定的时间段内,发生冲突的概率是多少?

  • 进程号
  • 柜台

发生冲突的概率很高。进程 id 可能在整个期间保持不变,而另一个数字只是一个递增的数字,它将在 4095 个订单之后重复。但是,如果流程循环,那么您也有可能与旧订单发生冲突等。如果您正在谈论多个数据库客户端,那么机会也会增加。我只是不会尝试减少数字。不满意的客户试图下订单是不值得的。

当有多个数据库客户端生成ObjectIds. 当您开始查看各个部分时,尤其是在数据库客户端群的上下文中,您应该了解为什么这些部分存在,以及为什么删除它们会导致ObjectId生成崩溃。

我建议你实现一个算法来创建一个唯一的数字并将其存储在数据库中。这很简单。它确实会影响性能,但它是安全的。

我不久前写了这个答案,关于ObjectId在 URL 中使用 an 的挑战。它包括如何使用 MongoDB 创建唯一的自动递增数字的链接。

于 2014-02-01T13:44:16.913 回答
1

实际上,您选择什么和 Id(实际上是_id在 MongoDB 存储中)完全取决于您。如果您可以保留一些有用的数据_id,只要您保持其唯一性,那么就这样做。如果它必须对 url 编码有效,那么就这样做。

默认情况下,如果您指定,_id则该字段将填充您喜欢和讨厌的值。但是如果你明确地使用它,那么你会得到你想要的。

另外要记住的是,即使您指定了一个额外的唯一索引字段,假设order_idMongoDB 实际上必须检查该索引和查询计划上的其他索引,以查看哪个最适合使用。但如果_id是你的钥匙,计划就会放弃并为“主钥匙”而苦苦挣扎,这会快很多。

因此,只要您能确保它是独一无二的,就制作您自己的ID 。

于 2014-02-01T14:05:18.243 回答