当前位置:   article > 正文

MongoDB ObjectId() 是如何实现的 “千万级” 分布式唯一 ID?_mongodb id

mongodb id

谈起分布式 ID,经常会聊到的一些方案是使用 Twitter 的 Snowflake 算法、UUID、数据库自增 ID 等。前些时间看了下 MongoDB ObjectId() 的实现原理,也不失为一种好的实现思路,正如标题所描述的,本文会给大家分享下在 MongoDB 中是如何实现的 “千万级” 分布式唯一 ID。

MongoDB 一开始的设计就是用来做为分布式数据库,插入数据时默认使用 _id 做为主键,下面这个 _id 就是 MongoDB 中开源的分布式系统 ID 算法ObjectId()生成的。

  1. new ObjectId("632c6d93d65f74baeb22a2c9")
  2. 复制代码

关于其组成需要指出一个误区,网上很多介绍 MongoDB ObjectId() 的文章,都有这样一段描述:

  1. // 过时的规则,现在已经不用 机器标识 + 进程号
  2. // 一种猜测,现在大多应用容器化,在容器内有独立的进程空间,它的进程号永远可能都为 1,还有创建几台虚拟机,其中的 hostname 可能也都为 localhost
  3. 4 字节的时间戳 + 3 个字节机器标识码 + 2 个字节进程号 + 3 个字节自增数
  4. 复制代码

很长一段时间我也一直这样认为,直到前些时间看了源码之后,发现中间的 3 个字节机器标识码 + 2 个字节进程号已被替换为 5 个字节的进程唯一标识,之后翻阅了 MongoDB 官方文档 描述也确实如此。

  1. // 当前 ObjectId 实现规则
  2. 4 字节的时间戳(单位:秒) + 5 个字节的进程唯一标识 + 3 个字节自增数
  3. 复制代码

这个组成规则反映出几个问题:

  • 因为前 4 个字节使用了时间戳,以 “秒” 为单位,总体上是递增的,也就是为什么我们有时可以使用 _id 替换 创建时间做为排序规则的依据,另外一个疑问,如果用 _id 做为时间筛选条件,该怎么做?
  • 中间 5 个字节随机值,是进程唯一标识,在进程启动之后,只需要生成一次。
  • 在一些限定条件下谈 ObjectId() 的 “唯一性”,后 3 个字节为自增数,1 个字节等于 8 位,在 1 秒之内,可以产生 Math.pow(2, 24) - 1 = 16777215 个唯一 ID,因此文章开头我用了 “千万级” 描述,这已经够了,当下突破这个限制几乎不太可能。

实现自定义 UniqueId()

下面让我们开始实践,参考

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/648295
推荐阅读
相关标签
  

闽ICP备14008679号