mongodb objectid的一部分最有可能是独一无二的

时间:2014-02-01 13:10:46

标签: mongodb bson objectid

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

2 个答案:

答案 0 :(得分:6)

如果您有多个具有多个进程的Web服务器,那么您确实无法通过丢失唯一性来删除这些服务器。

如果你看一下ObjectId

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

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

如果有多个服务器和/或进程充当数据库服务器的客户端,则使用计算机标识符和进程标识符。如果你放弃其中任何一个,你可能会再次重复。随机值作为最后3个字节用于确保同一进程中同一进程中的两个标识符是唯一的,即使经常请求也是如此。

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

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

  • 进程ID
  • 计数器

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

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

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

前一段时间我写了this回答关于在网址中使用ObjectId的挑战。它包含了如何使用MongoDB创建唯一自动递增数字的链接。

答案 1 :(得分:1)

实际上您选择的内容和Id(MongoDB存储中的_id)完全取决于您。如果有一些有用的数据,只要您保持唯一,就可以保留_id,然后执行此操作。如果它必须是url编码有效的东西,那么就这样做。

默认情况下,如果您执行指定_id,那么该字段将填充您已经爱恨交织的值。但是如果你明确地使用它,那么你将得到你想要的东西。

要记住的另一件事是,即使你指定了一个addtional唯一索引字段,让我们说order_id然后MongoDB实际上必须检查查询计划中的那个和其他索引看哪一个最好用。但如果_id是您的关键,那么该计划将放弃并进入“主要关键点”,这将会更快。

因此,只要您确保它是唯一的,就可以自己设置 ID