Recientemente, las dos aplicaciones se transformaron y se produjeron una serie de problemas durante el proceso de lanzamiento (parte de las cuales fue causada por el malentendido de objetos)
Primero entendamos el ObjectId:
Marca de tiempo
Los primeros 4 dígitos son una marca de tiempo UNIX, una categoría INT. Extraemos los primeros 4 dígitos del ObjectId en el ejemplo anterior "4DF2DCEC", y luego los instalamos en hexadecimal a decimal: "1307761900". Este número es una marca de tiempo. Para hacer que el efecto sea más obvio, convertimos esta marca de tiempo en el formato de tiempo al que estamos acostumbrados (exactamente a segundos)
$ Date -D '1970-01-01 UTC 1307761900 SEC' -U
Sábado 11 de junio de 2011 03:11:40 UTC
Los primeros 4 bytes en realidad ocultan el tiempo de la creación de documentos, y la marca de tiempo está en la parte delantera del personaje, lo que significa que el ObjectId se clasificará más o menos por la inserción, lo que juega un papel importante en algunos aspectos, como mejorar la eficiencia de búsqueda como un índice, etc. Otra ventaja de usar los drogadictos de los clientes puede superar cuando el registro se inserta a través de objetos. Esto también responde a la realidad de que cuando creamos múltiples objetos de manera rápida y continua, encontraremos que los primeros dígitos rara vez encuentran cambios, porque están utilizando la hora actual. Muchos usuarios están preocupados por la sincronización del tiempo del servidor. De hecho, el verdadero valor de esta marca de tiempo no es importante, siempre que aumente constantemente.
Máquina
Los siguientes tres bytes son 2CDCD2. Estos tres bytes son los identificadores únicos del host donde se encuentran, y generalmente son el valor hash del nombre del host de la máquina. Esto garantiza que diferentes hosts generen diferentes valores de hash de la máquina y garanticen que no haya conflicto en la distribución. Esta es la razón por la cual las cadenas en el objeto generado por la misma máquina son exactamente las mismas.
pid
La máquina anterior es asegurarse de que los objetos generados en diferentes máquinas no entren en conflicto, mientras que el PID es generar objetos que no entran en conflicto en diferentes procesos MongoDB en la misma máquina. Los siguientes dos bits de 0936 son los identificadores de proceso que generan objetos.
Incremento
Los primeros nueve bytes garantizan que los objetos generados por diferentes máquinas y procesos en un segundo no confisen. Los siguientes tres bytes A8B817 son un contador aumentado automáticamente para garantizar que los objetos generados en el mismo segundo no encuentren conflictos, lo que permite una potencia de 256 a 3er igual a la singularidad de los registros 167777216.
Singularidad de objetos
Puede pensar que hasta cierto punto, se puede garantizar que sea único, ya sea en el cliente o en el servidor.
Concepto erróneo 1. ¿El orden del documento es consistente con la orden de inserción?
Situación de un solo enhebrado
Se puede garantizar que la marca de tiempo, la máquina, PID e Inc en ObjectId sean únicas porque en la misma máquina y el mismo proceso.
Aquí hay un problema, las operaciones de MongoDB son multiprocesos. A, B, C ... Cuando varios hilos realizan operaciones en la tienda, no se garantiza cuál puede ser antes que el otro, por lo que estará fuera de servicio.
Situación de múltiples marcas, múltiples o múltiples procesos
Veamos el Macheo y el PID en ObjectId que no se puede garantizar que sean únicos. Entonces los datos estarán aún más fuera de servicio.
Solución:
Dado que los datos en la recopilación están desordenados (incluida la recopilación limitada), la forma más fácil es ordenar el ObjectId.
Hay dos formas de clasificar,
1. Declaración de consulta de MongoDB
jQuery Query = New Query (); if (id! = null) {jQuery.AddCriteria (criterio.where ("_ id"). gt (id)); } jQuery.with (nuevo sort (sort.direction.asc, "_id"));2.java.util.priorityqueue
Comparator <DBObject> comparator = new Comparator <DBObject> () {@Override public int Compare (dbObject o1, dbObject o2) {return ((objectId) o1.get ("_ id")). Comparación ((objectId) o2.get ("_ id")); }}; Priorityqueue <dbObject> queue = new Priorityqueue <DBObject> (200, comparador);Concepto erróneo 2: Cuando varios clientes tienen una alta concurrencia, ¿se puede garantizar el pedido (después del orden)?
Si siempre se asegura de que la escritura sea mucho mayor que la lectura (más de un segundo intervalo), esto nunca sucederá fuera de servicio.
Echemos un vistazo al siguiente ejemplo
Ahora vea la figura, elimine los datos dos veces
primero
4DF2DCEC AAAA FFFF 36A8B813
4DF2DCEC AAAA EEEE 36A8B813
4DF2DCEC BBBB 1111 36A8B814
La segunda vez
4DF2DCEC BBBB 1111 36A8B813
4DF2DCEC AAAA FFFF 36A8B814
4DF2DCEC AAAA EEEE 36A8B814
Ahora, si toma el primer valor máximo (4DF2DCEC BBBB 1111 36A8B814) para hacer el siguiente resultado de la consulta, entonces se perderá
Los tres elementos de la segunda vez, porque (4DF2DCEC BBBB 1111 36A8B814) son mayores que todos los registros tomados por segunda vez.
Esto conducirá a la pérdida de datos.
Solución:
Dado que la marca de tiempo de ObjectId se corta a segundos, los primeros cuatro dígitos del mostrador son los números de máquina y proceso.
1. Procese registros antes de un cierto intervalo de tiempo (más de un segundo), de modo que incluso si la máquina y los números de proceso causan desorden, no habrá trastorno antes del intervalo.
2. Inserción de un solo punto, la operación de inserción que se distribuyó originalmente a varios puntos, ahora se consulta por un punto para garantizar que la máquina y el número de proceso sean los mismos, y el operador de contador se usa para hacer que los registros ordenen ordenes.
Aquí, utilizamos el primer método.
Malentendido 3. ¿No establezca dbobject_id usando MongoDB para establecer ObjectId?
Durante la operación de inserción de MongoDB, cuando el nuevo dbbasicObject (), todos vean que _id no se completa, a menos que _id se establezca manualmente. Entonces, ¿está configurado en el servidor?
Echemos un vistazo al código para la operación de inserción:
Clase de implementación
Public WriterSult Insert (List <DBObject> List, com.MonGodb.WriteConcern Concern, dbenCoder Coder) {if (preocupation == null) {tirar nueva ilegalargumentException ("La preocupación de escritura no puede ser nula"); } return insert (lista, verdadero, preocupación, codificador); }Puede ver que necesita agregar, el valor predeterminado es agregar
Inserto de escritor protegido (List <DBObject> List, Boolean debería aplicar, com.mongoDB.WriteConCern Concern, dbencoder coder) {if (encoder == null) encoder = defaultdbencoder.factory.create (); if (willtrace ()) {for (dbobject o: list) {traza ("guardar:" + _fullNamespace + "" + json.serialize (o)); }} if (deberapply) {for (dbobject o: list) {aplicar (o); _CheckObject (o, falso, falso); Objeto id = o.get ("_ id"); if (id instanceOf objectId) {((objectId) id) .NotNeW (); }}} WriterSult Last = NULL; int cur = 0; int maxSize = _Mongo.getMaxBSOnObjectSize (); while (cur <list.size ()) {outMessage om = outMessage.insert (this, codificador, preocupación); for (; cur <list.size (); cur ++) {dbobject o = list.get (cur); om.putObject (o); // El límite para la inserción por lotes es 4 x maxbson en el servidor, use 2 x para ser seguro si (om.size ()> 2 * maxsize) {cur ++; romper; }} last = _connector.say (_db, om, preocupación); } retorno Último; }Agregar automáticamente las operaciones de ObjectId
/** * llamadas {@link dbCollection#aplicar (com.mongoDB.DBObject, boolean)} con ASCANSED = true * @param o <code> dbobject </code> a los que agregar campos * @return el objeto de parámetro modificado */público objeto (dBobject o) {return (o, true); }/** * llamadas {@link dbCollection#doapply (com.mongoDb.dbObject)}, opcionalmente agregando un campo _id automático * @param Jo objeto a agregar campos a * @param asegurar si A agregar un <código> _id </código> campo * @return el objeto modificado <código> o </ </ </ </ </ </ </ </ </ </ </ </ </ </ </ </ </ </scode, el código público. = Jo.get ("_id"); if (asegurar && id == null) {id = objectId.get (); Jo.put ("_id", id); } doapply (Jo); ID de retorno; }Como puede ver, ObjectId se agregará automáticamente al paquete de controladores MongoDB.
El método de guardar
Public WriterSult Save (DBObject Jo, WriteConcern Concern) {if (checkReadonly (true)) return null; _CheckObject (Jo, falso, falso); Objeto id = Jo.get ("_id"); if (id == null || (id instanceOf objectId && ((objectId) id) .isNew ())) {if (id! = null && id instanceOf objectId) ((objectId) id) .NotNeW (); if (preocupación == null) return insert (Jo); else Devuelve Insertar (Jo, preocupación); } DbObject q = new BasicDBObject (); q.put ("_id", id); if (preocupación == nulo) actualización de retorno (q, jO, true, falso); de lo contrario de la actualización de retorno (Q, Jo, verdadero, falso, preocupación); }Para resumir, por defecto, ObjectId es generado por el cliente y no por el servidor sin configuración.
Malentendido 4. ¿Puede FindandModify realmente obtener variables de incremento automático?
Dbobject Update = new BasicDBObject ("$ Inc", new BasicDBObject ("contador", 1)); DBObject query = new BasicDBObject ("_ id", clave); DBObject result = getMongoTemplate (). GetCollection (CollectionName) .FindandModify (consulta, actualización); if (result == null) {dbObject doc = new BasicDBObject (); doc.put ("contador", 1l); doc.put ("_ id", clave); // Insertar (CollectionName, DOC); getMongoTemplate (). Save (DOC, CollectionName); regresar 1l; } return (long) result.get ("contador");Obtener variables de autoincremento se escribirá utilizando este método, pero lo averiguaremos después de la ejecución.
FindandModify Operation, primero ejecute Buscar y luego ejecute Modify, por lo que cuando el resultado es nulo, debe agregarse y devolver 0 0
Lo anterior son los malentendidos y una serie de problemas causados por ObjectId en MongoDB que el editor le presentó. Espero que te sea útil. Si tiene alguna pregunta, déjame un mensaje y el editor le responderá a tiempo. ¡Muchas gracias por su apoyo al sitio web de Wulin.com!