【问题标题】:mongodb part of objectid most likely to be uniqueobjectid的mongodb部分最有可能是唯一的
【发布时间】:2014-02-01 13:10:46
【问题描述】:

在我的应用程序中,我让 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并行运行,一周内一定数量的用户,等等。

【问题讨论】:

    标签: mongodb bson objectid


    【解决方案1】:

    如果您有多个 Web 服务器,具有多个进程,那么您确实无法删除某些内容而失去唯一性。

    如果你看看ObjectId的性质:

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

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

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

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

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

    • 进程 ID
    • 计数器

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

    当有多个数据库客户端生成ObjectIds 时,即使是时间戳和随机种子值也不够用。当您开始查看各个部分时,尤其是在数据库客户端群的上下文中,您应该明白为什么这些部分存在,以及为什么删除它们会导致ObjectId 一代的崩溃。

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

    我不久前写了this 的答案,关于在网址中使用ObjectId 的挑战。它包含一个链接,指向如何使用 MongoDB 创建唯一的自动递增数字。

    【讨论】:

    • 感谢您的回复!我试图澄清我上面的问题 - 这个想法不是要替换 ObjectId,它只是为了看看如何衡量和最大限度地减少向用户显示文档真实 ObjectId 的一小部分的风险......
    • 这并没有真正改变问题的性质,但我添加了更多内容。
    • 好吧,上次更新真的很有用——正是我想知道的。至于可以在多个 mongos 之间保持唯一性的唯一编号生成器...如果您有任何参考资料,我将不胜感激!
    • @Petrov - 不确定这是否是您的意思:docs.mongodb.org/manual/tutorial/…
    【解决方案2】:

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

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

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

    所以,只要你能确保它是独一无二的,就制作你自己的 Id

    【讨论】:

    • 我不确定我是否理解您关于索引order_id 的观点?如果它被编入索引并设置为unique(在这种情况下您想要这样做),会有哪些额外的性能问题?如果它是唯一值,则您不会将其他字段指定为查询的一部分(与指定 _id 时一样)。
    • 考虑查询优化器的工作方式。如果您有其他 unique 字段和索引,则需要遍历它们以找到最合适的。每个文档始终具有_id 主键。搜索它会减少一大堆服务器端代码。此外,您正在编写另一个唯一索引。
    • 一堆?你确定吗?这是在哪里记录的?如果您要查询单个唯一值,则只能使用一个字段,就像 _id 一样。
    猜你喜欢
    • 2021-03-31
    • 1970-01-01
    • 1970-01-01
    • 2014-05-12
    • 2016-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多