python中Mongodb的Objectid 实现

python中Mongodb的Objectid 实现

Mongodb 作为非关系型数据库,默认实现 了Objectid 作为索引,对数据进行排序。

ojbectid 组成

在 ObjectId 类中,说明了objectid 的组成:

An ObjectId is a 12-byte unique identifier consisting of:

  - a 4-byte value representing the seconds since the Unix epoch,
  - a 5-byte random value,
  - a 3-byte counter, starting with a random value.

在 objectid 的函数中可以同样得知objectid的组成:

def __generate(self):
    """Generate a new value for this ObjectId.
        """

    # 4 bytes current time
    oid = struct.pack(">I", int(time.time()))

    # 5 bytes random
    oid += ObjectId._random()

    # 3 bytes inc
    with ObjectId._inc_lock:
        oid += struct.pack(">I", ObjectId._inc)[1:4]
        ObjectId._inc = (ObjectId._inc + 1) % (_MAX_COUNTER_VALUE + 1)

        self.__id = oid

这样我们就清楚了, o i d oid oid 由三部分组成

  • 4 bytes, 当前的 UNIX 时间,这个时间是秒级精度的
  • 5 bytes, 随机产生的字节
  • 3 bytes, 计数器

oid组成如下图所示:

oid

每部分含义

4字节时间

要理解 o i d oid oid 最开始的四个字节,我们需要理解 s t r u c t . p a c k ( ) struct.pack() struct.pack() 函数。

struct.pack(format, v1, v2, )

返回一个 bytes 对象,其中包含根据格式字符串 format 打包的值 v1, v2, … 参数个数必须与格式字符串所要求的值完全匹配。

源代码中struct.pack(">I", int(time.time()))>表示字节顺序为大端在先,I表示为按照python类型的整数转换为C类型的unsigned int.

5字节随机数

源码采用ObjectId._random() 来生成五字节的随机数,其对每一个进程生成一个 5 字节的随机数。

def _random(cls):
    """Generate a 5-byte random number once per process.
        """
    pid = os.getpid()
    if pid != cls._pid:
        cls._pid = pid
        cls.__random = _random_bytes()
    return cls.__random
_pid = os.getpid()
__random = _random_bytes()
...
def _random_bytes():
    """Get the 5-byte random field of an ObjectId."""
    return os.urandom(5)

3 字节计数器

with ObjectId._inc_lock:
    oid += struct.pack(">I", ObjectId._inc)[1:4]
    ObjectId._inc = (ObjectId._inc + 1) % (_MAX_COUNTER_VALUE + 1)

... 
_MAX_COUNTER_VALUE = 0xFFFFFF

源码中可以得知,oid_inc pack后的后三个字节有关,由于是大端模式,那么就是和_inc的低位字节有关。然后再更改 _inc 的值。从上面也可以得出 _inc 的取值范围是[0,0xFFFFFF] ,即[0,16777215]

那最初的_inc 是怎么生成的呢,_inc = SystemRandom().randint(0, _MAX_COUNTER_VALUE),也是一个[0,16777215]的随机数了。

小结

以上主要讲解了PyMongo 中对于 ObjectId 的实现,如果有什么问题,可以在评论区留言交流。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值