理解MongoDB默认的ObjectID

  

  

BSON ObjectID规范   BSON ObjectID

是由值组成的4字节时间戳(秒时代以来),一个3字节的机器id,一个2字节的进程id,一个3字节计数器。请注意,大端字节存储的时间戳和计数器字段必须与BSON的其余部分。这是因为他们比较逐字节我们想确保主要增加订单。格式:

  

,

  

           0   1   2   3.   4   5   6   7   8   9   10   11         时间   机   pid   公司            

  

,

  
      <李>时间戳。这是一个unix风格的时间戳。这是一个int代表签署1970年1月1日之前或之后的秒数(UTC)。   
  
      <李>机器。这是第一个三个字节的md5散列机器的主机名,mac/网络地址或虚拟机id。   
  
      <李> Pid。这是2个字节的进程的进程id(或线程id)生成对象id。   
  
      <李>增量。这是一个递增的值,或一个随机数如果一个计数器不能用于语言/运行时。   
  

BSON objectid可以是任何12字节的二进制字符串是独一无二的;然而,服务器本身和几乎所有的驱动程序使用上面的格式。

  

分段查看ObjectId的指令及结果如下:

  
  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>   
  

ObjectId占用12个字节的存储空间,由“;时间戳”;,“机器名”,“价格;PID号”,和“;计数器”;组成。使用机器名的好处是在分布式环境中能够避免单点计数的性能瓶颈。使用PID号的好处是支持同一机器内运行多个mongod实例。最终采用时间戳和计数器的组合来保证唯一性。

  

<>强时间戳

  

确保ObjectId唯一性依赖的是时间的顺序,不依赖时间的取值,因此集群节点的时间不必完全同步。既然ObjectId已经有了时间戳,那么在文档中就可以省掉一个时间戳了。在使用ObjectId提取时间时,应注意到MongoDB允许各节点时间不一致这一细节。

  

下面是查看时间戳的两种写法:

  
  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>   
  

<>强机器名

  

机器名通过Md5加密后取前三个字节,应该还是有重复概率的,配置生产集群时检查一下总不会错。另外,我也注意到重启MongoDB后Md5加密结果会发生变化,在利用ObjectID提取机器名信息时需格外注意。

  

<强> PID号

  

注意到每次重启mongod进程后PID号通常会发生变化就可以了。

  

<强>计数器

  

计数器占3个字节,表示的取值范围就是256 * 256 * 256 - 1=16777215。不妨认为MongDB性能的极限是单台设备一秒钟插入一千万条记录。以目前的水平看,单台设备一秒钟插入一万条就很不错了,因此ObjectID计数器的设计是够用的。

  

循环插入了一些记录、下面的查询中b是循环计数器,可以看出我机器上的ObjectId计数器是按顺序增加的:

  
  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>   
  

以下代码源自:http://www.cnblogs.com/xjk15082/archive/2011/09/18/2180792.html

  
  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>   
  
  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>  <李类=癮lt”>  <李>   
  

,

理解MongoDB默认的ObjectID