Должен ли я реализовать автоинкремент в MongoDB? - PullRequest
38 голосов
/ 11 июля 2011

Я делаю переход на MongoDB из MySQL. Мне знакомая архитектура для очень простой таблицы users будет иметь автоинкремент uid. См. Собственную документацию Mongo для этого варианта использования .

Мне интересно, является ли это лучшим архитектурным решением. С точки зрения UX, мне нравится иметь UID в качестве внешних ссылок, например, в более коротких URL: http://example.com/users/12345

Есть ли третий путь? Кто-то из IRC Freenode #mongodb предложил создать диапазон идентификаторов и кэшировать их. Я не уверен, как на самом деле реализовать это, или есть ли другой путь, по которому я могу пойти. Мне не обязательно даже саму _id увеличивать таким образом. Пока все users имеют уникальный номер uid в документе, я был бы счастлив.

Ответы [ 5 ]

79 голосов
/ 21 января 2013

Я категорически не согласен с автором выбранного ответа, что Нет идентификатора автоинкремента в MongoDB, и для этого есть веские причины . Мы не знаем причин, по которым 10gen не поощрял использование автоматически увеличивающихся идентификаторов. Это предположение. Я думаю, что 10gen сделал этот выбор, потому что проще обеспечить уникальность 12-байтовых идентификаторов в кластерной среде. Это стандартное решение, которое подходит большинству новичков, поэтому повышает популярность продукции, что хорошо для бизнеса 10gen.

Теперь позвольте мне рассказать всем о моем опыте использования ObjectIds в коммерческой среде.

Я строю социальную сеть. У нас около 6 миллионов пользователей, и у каждого пользователя около 20 друзей.

Теперь представьте, что у нас есть коллекция, в которой хранятся отношения между пользователями (которые следят за кем). Похоже, это

_id : ObjectId
user_id : ObjectId
followee_id : ObjectId

по которому мы имеем уникальный составной индекс {user_id, followee_id}. Мы можем оценить размер этого индекса как 12 * 2 * 6M * 20 = 2 ГБ. Теперь это показатель быстрого поиска людей, за которыми я следую. Для быстрого поиска людей, которые следуют за мной, мне нужен обратный индекс. Это еще 2 ГБ.

И это только начало. Я должен носить эти идентификаторы везде. У нас есть кластер деятельности, где мы храним вашу ленту новостей. Это каждое событие, которое вы или ваши друзья делаете. Представьте себе, сколько места занимает.

И, наконец, один из наших инженеров принял бессознательное решение и решил сохранить ссылки в виде строк, представляющих ObjectId, который удваивает его размер.

Что происходит, если индекс не помещается в ОЗУ? Ничего хорошего, говорит 10ген:

Когда индекс слишком велик, чтобы поместиться в ОЗУ, MongoDB должен прочитать его с диска, что намного медленнее, чем чтение из ОЗУ. Имейте в виду, что индекс помещается в ОЗУ, когда на сервере имеется ОЗУ, доступное для индекса, в сочетании с остальной частью рабочего набора.

Это означает, что чтение происходит медленно. Конфликт блокировки возрастает. Пишет становится медленнее. Я не вижу шока, когда вижу, что конфликт на 80% -ном уровне.

Прежде чем вы это знаете, у вас получился кластер 460 ГБ, который нужно разделить на осколки и которым довольно трудно манипулировать.

Facebook использует 64-битную длину в качестве идентификатора пользователя :) Для этого есть причина. Вы можете генерировать последовательные идентификаторы

  • по совету 10gen .
  • использование mysql в качестве хранилища счетчиков (если вас беспокоит скорость, взгляните на handlersocket )
  • используя созданный вами сервис генерации идентификаторов или используя что-то вроде Snowflake от Twitter.

Так вот мой общий совет всем. Пожалуйста, сделайте ваши данные как можно меньше. Когда ты вырастешь, это спасет тебя от многих бессонных ночей.

18 голосов
/ 11 июля 2011

Джош, В MongoDB нет идентификатора автоинкремента, и для этого есть веские причины. Я бы сказал, пойти с ObjectIds, которые являются уникальными в кластере.

Вы можете добавить автоинкремент для коллекции последовательностей и использовать findAndModify, чтобы получить следующий идентификатор для использования. Это, безусловно, добавит сложности вашему приложению и может также повлиять на возможность проверки вашей базы данных.

Пока вы можете гарантировать, что ваши сгенерированные идентификаторы будут уникальными, у вас все будет хорошо. Но головная боль будет там.

Дополнительную информацию по этому вопросу можно найти в этой статье в специальной группе Google для MongoDB:

http://groups.google.com/group/mongodb-user/browse_thread/thread/f57b712b2aae6f0b/b4315285e689b9a7?lnk=gst&q=projapati#b4315285e689b9a7

Надеюсь, это поможет.

Спасибо

15 голосов
/ 11 июля 2011

Итак, есть фундаментальная проблема с идентификаторами «автоинкремента». Когда у вас есть 10 разных серверов ( осколки в MongoDB), кто выбирает следующий идентификатор?

Если вам нужен один набор автоматически увеличивающихся идентификаторов, у вас должны быть единые полномочия для выбора этих идентификаторов. В MySQL это, как правило, довольно просто, поскольку у вас есть только один сервер, принимающий записи. Но в крупных развертываниях MongoDB используется шардинг, у которого нет этого «центрального органа».

MongoDB, использует 12-байтовый ObjectIds, так что каждый сервер может создавать новые документы уникальным образом, не полагаясь на один орган.

Итак, вот главный вопрос: «можете ли вы позволить себе иметь единственную власть» ?

Если это так, то вы можете использовать findAndModify для отслеживания «последнего наибольшего идентификатора», а затем вы можете вставить с ним.

Это процесс, описанный в вашей ссылке. Очевидным недостатком здесь является то, что вам технически нужно сделать две записи для каждой вставки. Это может не очень хорошо масштабироваться, вы, вероятно, хотите избежать этого в данных с высокой скоростью вставки. Это может работать для пользователей, вероятно, не будет работать для отслеживания кликов.

7 голосов
/ 11 июля 2011

В MongoDB нет ничего похожего на автоинкремент, но вы можете хранить свои собственные счетчики в выделенной коллекции и $ inc по соответствующему значению счетчика по мере необходимости. Поскольку $ inc является атомарной операцией, вы не увидите дубликатов.

3 голосов
/ 14 ноября 2014

По умолчанию значение Mongo ObjectId - то, которое используется в поле _id - увеличивается.

Mongo использует метку времени (секунды с начала эпохи Unix) в качестве первой 4-байтовой части своих 4-3-2-3 композиция, очень похожая (если не совсем) такая же композиция, как UUID версии 1.И этот ObjectId генерируется во время вставки (если пользователь / клиент не предоставляет другого типа _id)

Таким образом, ObjectId является порядковым по своей природе;кроме того, сортировка по умолчанию основана на этой возрастающей отметке времени.

Можно считать ее обновленной версией идентификаторов с автоинкрементным индексом (index ++), используемых во многих dbms.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...