【问题标题】:Why mongodb java driver uses random bytes instead of machine id in ObjectId?为什么 mongodb java 驱动程序在 ObjectId 中使用随机字节而不是机器 id?
【发布时间】:2023-03-28 03:24:01
【问题描述】:

很多人说 ObjectId 包括:

  • 一个 4 字节的值,表示自 Unix 纪元以来的秒数(直到 2106 年才会用完秒数)
  • 一个 3 字节的机器标识符(通常来自 MAC 地址),
  • 一个 2 字节的进程 ID,以及
  • 一个 3 字节的计数器,从一个随机值开始。

如果 objectId 包含所有这些元素,则可以保证所有 id 在集群中都是唯一的。但是文档说没有机器和进程 ID,并且 objectId 只包含一个随机值 (https://docs.mongodb.com/manual/reference/method/ObjectId)

我查看了java mongo驱动ObjectId的生成,找到了证据:

SecureRandom secureRandom = new SecureRandom();
RANDOM_VALUE1 = secureRandom.nextInt(0x01000000);
RANDOM_VALUE2 = (short) secureRandom.nextInt(0x00008000);

// ...

private ObjectId(final int timestamp, final int counter, final boolean checkCounter) {
    this(timestamp, RANDOM_VALUE1, RANDOM_VALUE2, counter, checkCounter);
}

因此,有可能(好吧,概率非常低,但仍然如此)两台机器生成相同的随机数,并且所有因此生成的 id 很可能会发生冲突。为什么会做出这样的决定?它仍然是完全独特的,但我不明白吗? 谢谢!

编辑:好吧,问题的目的是:我应该自己实现MAC地址和processId的检索并生成ObjectId还是留下随机的5个字节数,因为没有区别?

【问题讨论】:

  • 我不确定这个问题的目的是什么,但只是为了争论,您可以争辩说原始版本也不能保证 100% 的唯一性。话虽如此,这两种解决方案都给出了一个唯一的(“足够”?)id。
  • @TomSlabbaert 为什么原始版本不保证这一点?计数器(最后 3 个字节)保证在一台机器上生成的所有 id 都是唯一的。而address+process 5字节保证2台机器上生成的objectIds总是会不一样,因为2台机器总是有不同的mac地址(或者进程id,如果它们在单台机器上运行的话)

标签: java mongodb bson


【解决方案1】:

为什么 mongodb java driver 在 ObjectId 中使用随机字节而不是机器 id?

这种行为是mandated by the ObjectId specification

同一文档提供the rationale:

随机值:最初,该字段由机器 ID 和进程 ID 字段组成。由于实现选择,驱动程序之间存在许多分歧,并且机器 ID 字段传统上使用 MD5 散列算法,该算法不能在符合 FIPS 的机器上使用。为了允许所有驱动程序和 MongoDB 服务器之间的行为相似,这两个字段已被整理成一个 5 字节的随机值,对机器和进程来说是唯一的。

您不需要实现 ObjectId 生成,因为所有 MongoDB 驱动程序都必须提供此功能。

【讨论】:

  • 感谢您的链接!那么,如果我在普通机器上运行代码,我应该实现使用 MAC 地址生成 ObjectId 以实现 100% 唯一性的旧选项?
  • 您能解释一下原因吗?如果两台机器有不同的地址,那么生成的 ObjectId 是 100% 不同的。是否存在mac地址和进程id相同的情况?
猜你喜欢
  • 2013-05-25
  • 2014-01-31
  • 1970-01-01
  • 2016-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-16
  • 1970-01-01
相关资源
最近更新 更多