每个mongoDB中的文档都需要一个主键,这个主键在每个集合中是唯一的,默认会带唯一索引,主键为_id字段。我们同样可以使用别的值作为 _id字段的值,但是当程序没有提供_id时,mongo会自动生成一个 _id。

mongoDB默认的 _id为一个12字节的16进制的字符串,这个字符串中保存着有用的信息,具体构成如下图所示:
MongoDB主键ObjectId(_id)生成策略_ObjectId
最重要的时开头的四个字节的时间信息,为Unix时间戳。后面三个字节是机器ID,两个字节的进程ID,三个字节的计数器。计数器会自动增长,可以保证同一进程、同一时刻内不会重复。

​ _id由这四部分组成,就可以保证在分布式的情况下,保证 _id全局唯一。mongo如此设计就可以保证及时 _id是在驱动中生成(而不是在服务器端),也可以保证全局唯一。可以参考java mongo驱动中的ObejectId类(org.bson.types.ObjectId)。

​ 在文档(表)中没有创建时间字段的情况下,使用默认的_id还可以从主键中获取时间信息。

在对集合进行分片时,mongo只能确保分片键值是唯一的(唯一索引只对这个分片中的数据有效),不能在任一键上强制唯一,因为一个分片无法通过检查另一个分片来确认是否有重复值,即使主键_id字段也是一样,因此,如无必须,当对集合进行分片时,最好默认使用由驱动生成的ObjectId,这个可以确保唯一性。如果客户端没有强制唯一,当两个相同 _id的文档迁移到同一个分片上时,就会丢失数据。