MongoDB 的 ObjectIds 是如何生成的?

Posted

技术标签:

【中文标题】MongoDB 的 ObjectIds 是如何生成的?【英文标题】:How are MongoDB's ObjectIds generated? 【发布时间】:2011-08-14 15:19:22 【问题描述】:

它们是有点随机的吗?

我的意思是....人们能把它们分开吗?

【问题讨论】:

【参考方案1】:

一代

它们通常由驱动程序本身在客户端生成。例如,在 ruby​​ 中,可以使用 BSON::ObjectID:

https://github.com/mongodb/bson-ruby/blob/master/lib/bson/object_id.rb#L369

您还可以生成自己的 ObjectId。如果您想使用业务标识符,这将特别有用。

易碎性

使用驱动程序生成的 ObjectIds 时,为低 使用自己的企业 ID 时,根据其可预测性(登录名、连续标识符...)略高

【讨论】:

是的,如果您有相关的 ObjectId 可用于分析,则可以预测它们。但我想你会同意,它比传统 DB 中通常的 Identity 列更难猜... 是的,增量 id 更容易猜到,但是 Mongo ObjectId 不能被认为是安全的。 而且由于它们不是随机的并且很容易被分解,因此您可以在 mongo shell 中执行此操作:ObjectId().getTimestamp() 以了解它的创建时间。 uuid 不会提供更多的独特性吗?使用这种算法,生成重复的 id 似乎并非不可能……“机器”-id 是从哪里来的?【参考方案2】:

它们不是随机的,很容易预测:

BSON ObjectID 是一个 12 字节的值 由一个 4 字节的时间戳组成 (自纪元以来的秒数),一个 3 字节 机器 id、一个 2 字节的进程 id 和一个 3字节计数器

http://www.mongodb.org/display/DOCS/Object+IDs

【讨论】:

仅供参考:链接的文档不再与引用的文本一致——它提到了“一个 5 字节的随机值”而不是使用“id”值。因此,本质上,有一个 32 位时间戳与一个 64 位随机初始化的计数器连接在一起。 结论是一样的: 如果您有来自同一系统的有效值,则很容易猜测其他 ObjectId 值。【参考方案3】:

这是 MongoDB ObjectID (http://jsfiddle.net/icodeforlove/rN3zb/) 的 javascript 实现

function ObjectIdDetails (id) 
    return 
        seconds: parseInt(id.slice(0, 8), 16),
        machineIdentifier: parseInt(id.slice(8, 14), 16),
        processId: parseInt(id.slice(14, 18), 16),
        counter: parseInt(id.slice(18, 24), 16)
    ;

因此,如果您拥有足够多的此类信息,它们就会泄露大量有关您的基础架构的信息。而且您还知道所有对象的创建日期。

IE:你有多少台服务器,每台服务器运行多少进程。

【讨论】:

【参考方案4】:

默认情况下,MongoDB 数据库驱动程序会生成一个 ObjectID 标识符,该标识符分配给每个文档的 _id 字段。在许多情况下,ObjectID 可以用作应用程序中的唯一标识符。

ObjectID 是一个 96 位的数字,其组成如下:

一个 4 字节的值,表示自 Unix 纪元以来的秒数(直到 2106 年才会用完秒数)

一个 3 字节的机器标识符(通常来自 MAC 地址),

一个 2 字节的进程 ID,并且

一个 3 字节的计数器,从一个随机值开始。

【讨论】:

【参考方案5】:

来自MongoDB官方文档links 它显示:

对象ID ObjectId 很小,可能是唯一的,生成速度快,并且 订购。 ObjectId 值由 12 个字节组成,其中前四个 bytes 是反映 ObjectId 创建的时间戳。 具体来说:

一个 4 字节的值,表示自 Unix 纪元以来的秒数, 一种 5字节随机值, 一个 3 字节的计数器,以随机数开始 价值。 在 MongoDB 中,存储在集合中的每个文档都需要一个 充当主键的唯一 _id 字段。如果插入的文档 省略 _id 字段,MongoDB 驱动程序会自动生成一个 _id 字段的 ObjectId。

【讨论】:

5 字节的“随机值”似乎不是随机的。其他答案表明它是机器标识符和进程 ID 的组合。 @Jontia 谢谢,5字节的随机值在一个一个插入时是不可变的!

以上是关于MongoDB 的 ObjectIds 是如何生成的?的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB(猫鼬)聚合计数集合中特定 ObjectID 的实例

如何使用 ObjectIds 数组从 Parse 中检索用户数组?

如何将 Autodesk 模型衍生 API 元数据中的 objectids 与 Forge Viewer 模型 dbids 匹配?

mongodb - 没有本地的聚合查找

Mongoose 聚合匹配 objectIds 数组

Mongoose Populate 不适用于 ObjectIds 数组