0

这是参考这个答案:https ://stackoverflow.com/a/5694803/762747

所以 BSON 对象 ID 包括:

[自纪元以来的 4 字节秒数,3 字节机器哈希,2 字节进程 ID,3 字节计数器]

mongoid/moped ( http://mongoid.org/ ) 使用什么逻辑来生成 3 字节计数器 - 它们是递增还是生成随机数?

如果有效,我们是否可以几乎确定 mongoid 生成的 BSON ObjectId 将是唯一的(并避免引用答案中的第 2 点)?

4

1 回答 1

2

我们几乎可以肯定 ObjectId 将是唯一的。:)

当不使用本机扩展(现在bson显然包含在 mongoid/moped 使用的 gem 中)时,使用了一个计数器。

def next(time = nil)
    @mutex.lock
    begin
      count = @counter = (@counter + 1) % 0xFFFFFF
    ensure
      @mutex.unlock rescue nil
    end
    generate(time || ::Time.new.to_i, count)
end

正如你在Generator课堂上看到的那样,它使用了一个计数器。

当使用本机 C 代码生成 ObjectId 时,也使用了一个计数器:

static VALUE rb_object_id_generator_next(int argc, VALUE* time, VALUE self)
{
  char bytes[12];
  unsigned long t;
  unsigned short pid = htons(getpid());

  if (argc == 0 || (argc == 1 && *time == Qnil)) {
    t = rb_current_time_milliseconds();
  }
  else {
    t = htonl(NUM2UINT(rb_funcall(*time, rb_intern("to_i"), 0)));
  }

  memcpy(&bytes, &t, 4);
  memcpy(&bytes[4], rb_bson_machine_id, 3);
  memcpy(&bytes[7], &pid, 2);
  memcpy(&bytes[9], (unsigned char*) &rb_bson_object_id_counter, 3);
  rb_bson_object_id_counter++;
  return rb_str_new(bytes, 12);
}

附录(感谢@ChrisHeald的提示)

假设正在使用的 Ruby 实现使用 GIL(全局解释器锁)并使用上面的 C 代码实现,C 代码在递增计数器时也是安全的rb_bson_object_id_counter,因为在调用此代码时会有一个外部锁.

于 2013-07-09T12:33:02.740 回答