Недавно два приложения были преобразованы, и в процессе запуска возникла ряд проблем (часть которых была вызвана недопониманием ObjectId)
Давайте сначала поймем объект:
Временная метка
Первые 4 цифры - это временная метка Unix, категория Int. Мы извлекаем первые 4 цифры ObjectID в приведенном выше примере «4DF2DCEC», а затем устанавливаем их в шестнадцатеричном или десятичном десятичном виде: «1307761900». Это число является временной меткой. Чтобы сделать эффект более очевидным, мы преобразуем эту временную метку в формат времени, к которому мы привыкли (точно в секунды)
$ DATE -D '1970-01-01 UTC 1307761900 SEC' -u
Суббота, 11 июня 2011 г. 03:11:40 UTC
Первые 4 байта фактически скрывают время создания документов, а временная метка находится в передней части персонажа, что означает, что объект ID будет примерно отсортирован с помощью вставки, которая играет большую роль в некоторых аспектах, таких как повышение эффективности поиска в качестве индекса и т. Д. Другое преимущество использования временных метков заключается в том, что некоторые дать клиента могут исходить, когда запись была введена через объект. Это также отвечает на реальность, что, когда мы создаем несколько объектов, быстро и непрерывно, мы обнаружим, что первые несколько цифр редко находят изменения, потому что они используют текущее время. Многие пользователи беспокоятся о синхронизации времени сервера. На самом деле, истинное значение этой метки времени не важно, если она постоянно увеличивается.
Машина
Следующие три байта 2CDCD2. Эти три байта являются уникальными идентификаторами хоста, где они расположены, и, как правило, являются хэш -значением имени хоста машины. Это гарантирует, что разные хосты генерируют различные значения хеша машины и гарантируют, что в распределении нет конфликта. Вот почему строки в объекте, сгенерированной одной и той же машиной, точно одинаковы.
пид
Вышеуказанная машина должна гарантировать, что объекты, генерируемые на разных машинах, не конфликтуют, в то время как PID - генерировать объекты, которые не конфликтуют в разных процессах MongoDB на одной и той же машине. Следующие два бита 0936 являются идентификаторами процесса, которые генерируют объекты.
Приращение
Первые девять байтов гарантируют, что объекты, генерируемые различными машинами и процессами в течение одной секунды, не конфликтуют. Следующие три байта A8B817 являются автоматически увеличенным счетчиком, чтобы гарантировать, что объекты, генерируемые в одну и ту же секунду, не находят конфликты, что позволяет от 256 до 3 -го мощности, равной уникальности 16777216 записей.
Объектная уникальность
Вы можете подумать, что в некоторой степени это может быть гарантированно уникальным, будь то на клиенте или на сервере.
Неправильное представление 1. Соответствует ли порядок документов?
Одиночная ситуация
Неэппаратная метка, машина, PID и Inc в ObjectId могут быть гарантированно быть уникальными, потому что на той же машине и в том же процессе.
Здесь есть проблема, операции MongoDB многопоточные. A, B, C ... Когда несколько потоков проводят операции в магазине, не гарантируется, каким может быть перед другим, так что это будет вне порядок.
Многопоточная, многочасовая или многопроцессорная ситуация
Давайте посмотрим на Mache и PID в ObjectId, который не может быть гарантированно уникальным. Тогда данные будут еще больше в порядке.
Решение:
Поскольку данные в сборе неупорядочены (включая сборы с ограниченным покрытием), самый простой способ сортировки ObjectId.
Есть два способа сортировки,
1. Монгодб заявление запроса
jQuery Query = new Query (); if (id! = null) {jquery.addcriteria (критерии. где ("_ id"). gt (id)); } jquery.with (new sort (sort.direction.asc, "_id"));2. Java.util.priorityQueue
Comporator <dbobject> Comporator = новый компаратор <dbobject> () {@override public int compare (dbobject o1, dbobject o2) {return ((objectid) o1.get ("_ id")). Compareto ((objectid) o2.get ("_ id")); }}; ПриоритетЗавершающееся представление 2: Когда несколько клиентов имеют высокую параллелию, можно ли гарантировать заказ (после сортировки)?
Если вы всегда убедитесь, что запись намного больше, чем показания (более одного секунды), это никогда не произойдет вне порядка.
Давайте посмотрим на следующий пример
Теперь посмотрите на рисунку, выньте данные дважды
первый
4df2dcec aaaa ffff 36a8b813
4df2dcec aaaa eeee 36a8b813
4DF2DCEC BBBB 1111 36A8B814
Второй раз
4df2dcec bbbb 1111 36a8b813
4df2dcec aaaa ffff 36a8b814
4df2dcec aaaa eeee 36a8b814
Теперь, если вы возьмете первое максимальное значение (4DF2DCEC BBBB 1111 36A8B814), чтобы сделать следующий результат запроса, тогда он будет пропущен
Три пункта второго раз, потому что (4DF2DCEC BBBB 1111 36A8B814) больше, чем все записи, взятые во второй раз.
Это приведет к потере данных.
Решение:
Поскольку временная метка ObjectID отключается до секунд, первыми четырьмя цифрами оператора противодействия являются номера машины и процессов.
1. Записи процесса до определенного интервала времени (более одной секунды), так что даже если номера машины и процесса вызывают расстройство, до интервала не будет расстройства.
2. Вставка с одной точкой, операция вставки, которая первоначально была распределена по нескольким точкам, теперь запрашивается одной точкой, чтобы убедиться, что машина и номер процесса одинаковы, а оператор противодействия используется для упорядочения записей.
Здесь мы использовали первый метод.
Недопонимание 3. Не устанавливайте dbobject_id с использованием mongodb для установки ObjectId?
Во время операции вставки MongoDB, когда New DBBASICOBject () каждый видит, что _ID не заполняется, если только _ID не установлен вручную. Так настроен на сервера?
Давайте посмотрим на код для операции вставки:
Класс реализации
public writeresult insert (list <dbobject> list, com.mongodb.writeconcern controgne, dbencoder encoder) {if (congence == null) {бросить новый allosalargumentException («Запись не может быть нулевым»); } return INSERT (List, True, Congewer, Encoder); }Вы можете видеть, что вам нужно добавить, по умолчанию добавить
Защищенная writeresult insert (list <dbobject> list, boolean upply Apply, com.mongodb.writeconcern contrice, dbencoder encoder) {if (encoder == null) encoder = defaultdbencoder.factory.create (); if (willtrace ()) {for (dbobject o: list) {trace ("save:" + _fullnamespace + "" + json.serialize (o)); }} if (должен (должен) {for (dbobject o: list) {Apply (o); _checkObject (o, false, false); ID объекта = O.Get ("_ ID"); if (id ancessionOf objectId) {((objectId) id) .notnew (); }}} WriterSult last = null; int cur = 0; int maxsize = _mongo.getMaxBsonObjectSize (); while (cur <list.size ()) {utmessage om = utmessage.insert (это, энкодер, беспокойство); for (; cur <list.size (); cur ++) {dbobject o = list.get (cur); Om.PutObject (O); // Ограничение для пакетной вставки составляет 4 x maxbson на сервере, используйте 2 x, чтобы быть безопасным, если (om.size ()> 2 * maxsize) {cur ++; перерыв; } / } вернуть последнее; }Автоматически добавлять операции ObjectId
/** * Вызовы {@link dbcollection#Apply (com.mongodb.dbobject, boolean)} с areyid = true * @param o <code> dbobject </code>, к которому можно добавить Fields * @Reurn. Модифицированный объект параметра */public Apply (dbobject o) {reture Apply (O, true); }/** * Calls {@link dbcollection#doApply (com.mongodb.dbobject)}, опционее, добавив автоматическое поле _id * @param jo, чтобы добавить поля в * @param Убедитесь, что добавить <code> _id </code> field * @return the modied obj = jo.get ("_id"); if (убедиться и id == null) {id = objectId.get (); jo.put ("_id", id); } doApply (jo); вернуть идентификатор; }Как вы можете видеть, ObjectId будет автоматически добавлен в пакет драйверов MongoDB.
Метод сохранения
public writeresult save (dbobject jo, writeconcern constry) {if (checkreadonly (true)) return null; _checkObject (jo, false, false); Идентификатор объекта = jo.get ("_id"); if (id == null || (id ancessionof objectId && ((objectId) id) .isnew ())) {if (id! = null && id ancementOf objectId) ((objectId) id) .notnew (); if (congence == null) return insert (jo); иначе вернуть вставку (Джо, беспокойство); } Dbobject q = new BasicDbobject (); Q.put ("_id", id); if (controce == null) return update (q, jo, true, false); иначе вернуть обновление (q, jo, true, false, congeach); }Подводя итог, по умолчанию, ObjectId генерируется клиентом, а не сервером без настройки.
Недоразумение 4. Может ли найти имодификацию действительно получить переменные автоматического интеграции?
Dbobject update = new BasicDbobject ("$ Inc", New BasicDBobject ("counter", 1)); Dbobject Query = new BasicDBobject ("_ ID", Key); Dbobject result = getmongotemplate (). GetCollection (collectionName) .findandModify (Query, Update); if (result == null) {dbobject doc = new basicdbobject (); doc.put ("counter", 1L); doc.put ("_ id", key); // insert (collectionName, doc); getMongotemplate (). Save (doc, collectionName); вернуть 1L; } return (long) result.get ("counter");Получение переменных автоинсюрена будет записано с использованием этого метода, но мы узнаем после выполнения.
Найдите работу, сначала выполните, выполните, а затем выполните изменение, поэтому, когда результат будет нулевым, его следует добавить и возвращать 0
Вышесказанное - это недоразумения и ряд проблем, вызванных ObjectId в MongoDB, которые редактор представил вам. Я надеюсь, что это будет полезно для вас. Если у вас есть какие -либо вопросы, пожалуйста, оставьте мне сообщение, и редактор ответит вам вовремя. Большое спасибо за вашу поддержку сайту wulin.com!