mongodb 的 ObjectId

2017/07/18

官方文档解释

ObjectId(<hexadecimal>)

这是一个12字节(12-byte)的 ObjectId,其中包括:

可选参数:

Field Type Description
hexadecimal String 可选,16进制字符串

ObjectId() 有以下属性和方法:

Attribute/Method Description
str 返回这个id的16进制表示的字符串
ObjectId.getTimestamp() 返回这个id编码的时间戳
ObjectId.toString() 返回字符串: ObjectId(...)
ObjectId.valueOf() 就是 属性 str返回的那个,一样的

解释一个真实的id

596cee8fd68096396dc0390b

时间戳

一个秒级的时间戳是10位十进制数的,如果采用无符号表示方法,那么n位二进制(n个bit)可以表示的最大数字是 2^n-1,现在需要表示秒级时间戳,就需要m bit的空间,也就是:

$$2^m - 1 >= 10^9$$ $$m >= log_{2}^(10^9 + 1)$$ $$m >= 29.8974$$

不过注意哈,objectid是用16进制表示的,我们知道4位二进制对应于1位16进制,所以要么是8位(对应于32位二进制),满足 $$m >= 29.8974$$ 要么是7位16进制(对应于28位二进制),不满足 $$m >= 29.8974$$ 所以很显然,m取 32,也就是说用8位16进制字符串(32bit)表示一个时间戳 这个在定义中就明确了:4字节的unix秒级时间戳,即32bit

分割ObjectId

596cee8fd68096396dc0390b => 596cee8f  d68096  396d  c0390b

596cee8f是16进制时间戳,转化为10进制: sadf d68096是机器代码,不会变 396d是进程代码,不会变 c0390b是计数器,从随机数开始增加

创建ObjectId

可以看到,数据符合我们的预期,中间两个代码没有变,前面的增加的是秒数,后面的是计数器(+1)

引用