Recentemente, as duas aplicações foram transformadas e uma série de problemas ocorreu durante o processo de lançamento (parte do qual foi causada pelo mal -entendido objectid)
Vamos primeiro entender o objectId:
Timestamp
Os 4 primeiros dígitos são um registro de data e hora do UNIX, uma categoria int. Extraímos os 4 primeiros dígitos do ObjectID no exemplo acima "4DF2DCEC" e os instalamos em hexadecimal ao decimal: "1307761900". Este número é um registro de data e hora. Para tornar o efeito mais óbvio, convertemos esse registro de data e hora no formato de tempo que estamos acostumados (exatamente em segundos)
$ DAT -D '1970-01-01 UTC 1307761900 Sec' -u
Sábado, 11 de junho de 2011 03:11:40 UTC
Os 4 primeiros bytes realmente ocultam o horário da criação de documentos, e o registro de data e hora está na frente do personagem, o que significa que o objectId será classificado aproximadamente pela inserção, o que desempenha um grande papel em alguns aspectos, como melhorar a eficiência da pesquisa como um índice, etc. Outra vantagem do uso de registros de data e hora é que alguns clientes podem parecer que o registro foi inserido. Isso também responde à realidade de que, quando criamos vários objetos de maneira rápida e contínua, descobriremos que os primeiros dígitos raramente encontram alterações, porque estão usando o tempo atual. Muitos usuários estão preocupados com a sincronização do tempo do servidor. De fato, o verdadeiro valor desse registro de data e hora não é importante, desde que esteja constantemente aumentando.
Máquina
Os próximos três bytes são 2CDCD2. Esses três bytes são os identificadores exclusivos do host em que estão localizados e geralmente são o valor do hash do nome do host da máquina. Isso garante que hosts diferentes gerem valores diferentes de hash da máquina e garantem que não haja conflito na distribuição. É por isso que as seqüências de caracteres no objeto geradas pela mesma máquina são exatamente as mesmas.
PID
A máquina acima é garantir que os objetos gerados em diferentes máquinas não conflitem, enquanto o PID é gerar objetos que não conflitam em diferentes processos do MongoDB na mesma máquina. Os próximos dois bits de 0936 são os identificadores de processo que geram objetos.
Incremento
Os nove primeiros bytes garantem que os objetos gerados por diferentes máquinas e processos em um segundo não conflitem. Os próximos três bytes A8B817 são um contador aumentado automaticamente para garantir que os objetos gerados no mesmo segundo não encontrem conflitos, permitindo que 256 a 3ª potência igual à singularidade dos registros 16777216.
ObjectId Singularidade
Você pode pensar que, até certo ponto, pode ser garantido que seja único, seja no cliente ou no servidor.
Equívoco 1. A ordem do documento é consistente com a ordem de inserção?
Situação de rosca única
O registro de data e hora, a máquina, o PID e o INC no ObjectID podem ser garantidos como exclusivos porque na mesma máquina e no mesmo processo.
Há um problema aqui, as operações do MongoDB são multi-thread. A, B, C ... Quando vários threads conduzem operações na loja, não é garantido qual pode estar diante do outro, para que fique fora de ordem.
Situação multithreaded, multi-máquinas ou multipocessos
Vejamos o Mache e o PID no ObjectID que não podem ser garantidos para serem únicos. Em seguida, os dados estarão ainda mais fora de ordem.
Solução:
Como os dados da coleção não são ordenados (incluindo a coleção limitada), a maneira mais fácil é classificar o ObjectID.
Existem duas maneiras de classificar,
1. Declaração de consulta MONGODB
jQuery Query = new Query (); if (id! = null) {jQuery.addcriteria (critério.where ("_ id"). gt (id)); } jQuery.with (new Sort (Sort.direction.asc, "_id"));2.java.util.priorityQueue
Comparador <dBObject> comparador = novo comparador <DBObject> () {@Override public int Compare (dbObject o1, dbObject o2) {return ((objectId) o1.get ("_ id")). Compareto ((objectId) o2.get ("_ id"); }}; PriorityQueue <dBObject> fila = new priorityQueue <dBobject> (200, comparador);Equívoco 2: Quando vários clientes têm alta concorrência, o pedido pode ser garantido (após a classificação)?
Se você sempre garantir que a gravação seja muito maior que a leitura (mais de um segundo intervalo), isso nunca acontecerá fora de ordem.
Vamos dar uma olhada no exemplo seguinte
Agora veja a figura, retire os dados duas vezes
primeiro
4df2dcec aaaa ffff 36a8b813
4df2dcec aaaa eeee 36a8b813
4DF2DCEC BBBB 1111 36A8B814
A segunda vez
4df2dcec bbbb 1111 36a8b813
4df2dcec aaaa ffff 36a8b814
4df2dcec aaaa eeee 36a8b814
Agora, se você aceitar o primeiro valor máximo (4df2dcec bbbb 1111 36a8b814) para fazer o próximo resultado da consulta, será perdido
Os três itens da segunda vez, porque (4DF2DCEC BBBB 1111 36A8B814) são maiores do que todos os registros tirados pela segunda vez.
Isso levará à perda de dados.
Solução:
Como o registro de data e hora do ObjectID é cortado para segundos, os quatro primeiros dígitos do operador do balcão são os números da máquina e do processo.
1. O processo registra antes de um determinado intervalo de tempo (mais de um segundo), de modo que, mesmo que a máquina e o número de processos causem transtorno, não haverá desordem antes do intervalo.
2. A inserção de ponto único, a operação de inserção que foi originalmente distribuída para vários pontos, agora é consultada por um ponto para garantir que a máquina e o número do processo sejam os mesmos, e o operador do contador é usado para fazer os registros ordenados.
Aqui, usamos o primeiro método.
Incomposição 3. Não defina dbobject_id usando o MongoDB para definir o ObjectID?
Durante a operação de inserção do MongoDB, quando o novo dbBasicoBject (), todo mundo vê que _id não está preenchido, a menos que _id seja definido manualmente. Então, ele está configurado no servidor?
Vamos dar uma olhada no código para a operação de inserção:
Classe de implementação
Public WriterSult Insert (List <DBObject> List, com.mongodb.writeconcern Preocupor, codificador dBencoder) {if (preocupação == null) {lança nova ilegalArgumentException ("escrever preocupação não pode ser nula"); } return insert (list, true, preocupação, codificador); }Você pode ver que precisa adicionar, o padrão é adicionar
Lista de inserção de WriterSult Protected (List <dBObject>, Boolean deve aplicar, com.mongodb.writeconcern preocupação, codificador dbencoder) {if (coder == null) codificador = defaultDBencoder.Factory.Create (); if (willTrace ()) {for (dbObject o: list) {trace ("salvar:" + _fullNamespace + "" + json.serialize (o)); }} if (deve aplicar) {for (dbObject o: list) {Aplicar (o); _CheckObject (o, falso, falso); ID do objeto = o.get ("_ id"); if (Instância de IDOf ObjectId) {((objectId) id) .NotNew (); }}} WriterSult last = null; int cur = 0; int maxsize = _mongo.getMaxbsonObjectSize (); while (cur <list.size ()) {outmessage om = outmessage.insert (este, codificador, preocupação); para (; cur <list.size (); cur ++) {dbObject o = list.get (cur); om.putObject (O); // O limite para inserção em lote é 4 x maxbson no servidor, use 2 x para ser seguro se (om.size ()> 2 * maxsize) {cur ++; quebrar; }} last = _connector.say (_db, om, preocupação); } retornar por último; }Adicione automaticamente operações ObjectId
/** * Chamadas {@link dbCollection#Aplicar (com.mongodb.dbobject, boolean)} com garantia = true * @param o <code> dbObject </code> para que adicionar campos * @return o objeto de parâmetro modificado */public objeto Aplicar (dbObject o) {Return Appl (O, O, O, O, o True); }/** * chama {@link dbCollection#doapply (com.mongodb.dbobject)}, opcionalmente adicionando um campo automático _id * @param jo objeto para adicionar campos a * @param garantir que você deve adicionar um objeto de serem don @(code) * @PendAl. = jo.get ("_id"); if (garantiriD && id == null) {id = objectid.get (); jo.put ("_id", id); } doapply (jo); ID de retorno; }Como você pode ver, o ObjectID será adicionado automaticamente ao pacote de driver MongoDODB.
O método de salvar
Public WriterSult Save (DBObject Jo, WriteConcern Preocup) {if (checkReadonly (true)) retornar nulo; _CheckObject (Jo, falso, falso); ID do objeto = jo.get ("_id"); if (id == NULL || (Instância de IDOf ObjectId && ((objectId) id) .isnew ())) {if (id! = null && id instanceof objectId) ((objectId) id) .notNew (); if (preocupação == null) retornar inserção (jo); caso contrário, retornam inserção (Jo, preocupação); } DbObject q = new BasicDBObject (); q.put ("_id", id); if (preocupação == NULL) Atualização de retorno (q, jo, true, false); else Return update (Q, Jo, True, False, preocupação); }Para resumir, por padrão, o ObjectID é gerado pelo cliente e não pelo servidor sem configurar.
Mal-entendimento 4. O FindandModify pode realmente obter variáveis de incremento automático?
DbObject update = new BasicDBObject ("$ INC", new BasicDBObject ("contador", 1)); DBObject Query = new BasicDBObject ("_ Id", chave); DbObject resultado = getMongotemplate (). GetCollection (coleçãoName) .FindandModify (consulta, atualização); if (resultado == null) {dbObject doc = new BasicDBObject (); doc.put ("contador", 1l); doc.put ("_ id", chave); // insert (coleção, Doc); getMongotemplate (). Save (Doc, coleçãoName); retornar 1L; } return (long) resultado.get ("contador");Obter variáveis de auto -increment será gravado usando esse método, mas descobriremos após a execução.
Operação FindAndModify, primeiro execute o encontro e depois execute modificado; portanto, quando o resultado é nulo, ele deve ser adicionado e devolvido 0
O exposto acima são os mal -entendidos e uma série de problemas causados pelo ObjectId em MongoDB que o editor apresentou a você. Espero que seja útil para você. Se você tiver alguma dúvida, deixe -me uma mensagem e o editor responderá a você a tempo. Muito obrigado pelo seu apoio ao site wulin.com!