• MongoDB ObjectId() 是如何实现的 “千万级” 分布式唯一 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()

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

  • 相关阅读:
    堆排序详解
    ANSYS_Q3D仿真激光发射的寄生电感
    从日志读取关键数据,按照相关日期进行数据分析
    【算法刷题 | 栈】3.16(有效的括号、删除字符串中的所有相邻重复项、逆波兰表达式求值)
    渗透测试-xml注入以及xxe漏洞
    学习react的getSnapshotBeforeUpdate和其他生命周期
    idea 基础设置
    光点高校数据中台,助力高校信息化迎来发展新格局_光点科技
    MasterAlign相机参数设置-增益调节
    【Java成王之路】EE初阶第十四篇:(网络原理) 4
  • 原文地址:https://blog.csdn.net/m0_73311735/article/details/127105243