Escritas locais distribuídas para volumes de trabalho somente de inserção
Nesta página
A fragmentação com reconhecimento de tags do MongoDB permite que os administradores controlem a distribuição de dados em um cluster fragmentado definindo intervalos dachave de shard e marcando-os em um ou mais shards.
Este tutorial usa zona junto com um sistema de cluster fragmentado de vários centros de dados e lógica do lado da aplicação para suportar gravações locais distribuídas, bem como alta disponibilidade de gravação no caso de um evento de eleição de conjunto de réplicas ou falha do centro de dados.
Ao definir as zonas e as faixas de zonas antes de fragmentar uma collection vazia ou não existente, a operação de collection de shards cria chunks para as faixas de zonas definidas, bem como quaisquer chunks adicionais para cobrir todo a faixa dos valores da chave de shard e executa uma distribuição inicial de shards com base nas faixas de zonas. Essa criação e distribuição inicial de chunks permite uma configuração mais rápida da fragmentação por zonas. Após a distribuição inicial, o balancer gerenciará a distribuição de chunks dali para a frente.
Consulte Predefinir zonas e faixas de zona para uma collection vazia ou não existente para ver um exemplo.
Importante
Os conceitos discutidos neste tutorial exigem uma arquitetura de implantação específica, bem como uma lógica no nível do aplicativo.
Esses conceitos exigem familiaridade com os clusters fragmentados do MongoDB, os conjuntos de réplicas e o comportamento geral das zonas.
This tutorial assumes an insert-only or insert-intensive workload. Os conceitos e estratégias discutidos neste tutorial não são adequados para casos de uso que exigem leituras ou atualizações rápidas.
Cenário
Considere um aplicativo de inserção intensiva, onde as leituras são pouco frequentes e de baixa prioridade em comparação com as gravações. A aplicação grava documento em uma collection fragmentada e requer tempo de atividade quase constante do reconhecimento de data center para suportar seus SLAs ou SLOs.
O seguinte representa uma visão parcial do formato do documento que a aplicação grava no reconhecimento de data center:
{ "_id" : ObjectId("56f08c447fe58b2e96f595fa"), "message_id" : 329620, "datacenter" : "alfa", "userid" : 123, ... } { "_id" : ObjectId("56f08c447fe58b2e96f595fb"), "message_id" : 578494, "datacenter" : "bravo", "userid" : 456, ... } { "_id" : ObjectId("56f08c447fe58b2e96f595fc"), "message_id" : 689979, "datacenter" : "bravo", "userid" : 789, ... }
Chave de fragmento
A collection usa o índice composto { datacenter : 1, userid : 1 }
como chave de fragmento.
O campo datacenter
em cada documento permite criar um intervalo de tags em cada valor de centro de dados distinto. Sem o campo datacenter
, não seria possível associar um documento a um centro de dados específico.
O campo userid
fornece um componente de alta cardinalidade e baixa frequência para a chave de shard relativa ao datacenter
.
Consulte Escolher uma chave de shard para obter instruções mais gerais sobre como selecionar uma chave de shard.
Arquitetura
O sistema consiste em dois centros de dados, alfa
e bravo
. Existem dois fragmentos, shard0000
e shard0001
. Cada fragmento é um conjunto de réplicas com três membros. shard0000
tem dois membros em alfa
e um membro de prioridade 0 em bravo
. shard0001
tem dois membros em bravo
e um membro de prioridade 0 em alfa
.
Etiquetas
Este aplicativo requer uma tag por datacenter. Cada fragmento tem uma tag atribuída a ele com base no datacenter que contém a maioria dos membros do conjunto de réplicas. Existem dois intervalos de tags, um para cada centro de dados.
alfa
Centro de dadosMarque shards com a maioria dos membros neste datacenter como
alfa
.Crie um intervalo de tags com:
um limite inferior de
{ "datacenter" : "alfa", "userid" : MinKey }
,um limite superior de
{ "datacenter" : "alfa", "userid" : MaxKey }
ea marcação
alfa
bravo
Centro de dadosMarque shards com a maioria dos membros neste datacenter como
bravo
.Crie um intervalo de tags com:
um limite inferior de
{ "datacenter" : "bravo", "userid" : MinKey }
,um limite superior de
{ "datacenter" : "bravo", "userid" : MaxKey }
ea marcação
bravo
Com base nas tags configuradas e nos intervalos das tags, mongos
roteia documentos com datacenter : alfa
para o data center alfa
e documentos com datacenter : bravo
para o data center bravo
.
Operações de Escrita
Se um documento inserido ou atualizado corresponder a um intervalo de tags configurado, ele só poderá ser gravado em um fragmento com a tag relacionada.
O MongoDB pode escrever documentos que não correspondem a uma faixa de tags configurada a nenhum shard no cluster.
Observação
O comportamento descrito acima exige que o cluster esteja em um estado estável, sem partes que violem uma faixa de tags configurada. Consulte a seção a seguir nobalanceador para obter mais informações.
Balancer
O balanceador migra as partes marcadas para o fragmento apropriado. Até a migração, os shards podem conter parte que violam as faixas de tags e tags configuradas. Após a conclusão do balanceamento, os shards devem conter apenas parte cujos intervalos não violem as tags e os intervalos de tags atribuídos.
Adicionar ou remover tags ou intervalos de tags pode resultar em migrações de partes. Depending on the size of your data set and the number of chunks a tag range affects, these migrations may impact cluster performance. Considere executar seu balanceador durante janelas agendadas específicas. See Schedule the Balancing Window for a tutorial on how to set a scheduling window.
Comportamento do aplicativo
Por padrão, o aplicativo grava no centro de dados mais próximo. Se o reconhecimento de data center local estiver inativo ou se as gravações nesse reconhecimento de data center não forem reconhecidas dentro de um período definido, a aplicação mudará para o outro reconhecimento de data center disponível alterando o valor do campo datacenter
antes de tentar gravar o documento no banco de dados.
O aplicativo suporta tempos limite de gravação. A aplicação usa a referência de escrita para definir um tempo limite para cada operação de gravação.
Se o aplicativo encontrar um erro de gravação ou tempo limite, ele modificará o campo datacenter
em cada documento e executará a gravação. Isso roteia o documento para o outro datacenter. Se ambos os data centers estiverem inativos, as gravações não poderão ser bem-sucedidas. Consulte Resolver falha de gravação.
O aplicativo verifica periodicamente a conectividade com quaisquer centros de dados marcados como "inativos". Se a conectividade for restaurada, o aplicativo poderá continuar executando operações normais de gravação.
Dada a lógica de comutação, bem como quaisquer balanceadores de carga ou mecanismos semelhantes em vigor para lidar com o tráfego de clientes entre os centros de dados, o aplicativo não pode prever em qual dos dois centros de dados um determinado documento foi gravado. To ensure that no documents are missed as a part of read operations, the application must perform broadcast queries by not including the datacenter
field as a part of any query.
O aplicativo realiza leituras usando uma preferência de leitura de nearest
para reduzir a latência.
É possível que uma operação de gravação seja bem-sucedida apesar de um erro de tempo limite relatado. O aplicação responde ao erro tentando reescrever o documento no outro datacenter - isso pode resultar na duplicação de um documento em ambos os datacenters. O aplicação resolve duplicatas como parte da lógica de leitura .
Lógica de switch
O aplicativo tem lógica para trocar de datacenter se uma ou mais gravações falharem ou se as gravações não forem confirmadas dentro de um período de tempo definido. O aplicativo modifica o campo datacenter
com base na marcação do datacenter de destino para direcionar o documento para esse datacenter.
Por exemplo, um aplicativo que tenta gravar no centro de dados alfa
pode seguir este procedimento geral:
Tentar escrever documento, especificando
datacenter : alfa
.Em caso de erro ou tempo limite de gravação, registre
alfa
como momentaneamente inativo.Tente escrever o mesmo documento, modificando
datacenter : bravo
.Em caso de erro ou tempo limite de gravação, registre
bravo
como momentaneamente inativo.Se
alfa
ebravo
estiverem inativos, registre e relate erros.
Consulte Resolver falha de gravação.
Procedimento
Configurar Marcações de Fragmento
Você deve estar conectado a um mongos
associado ao cluster fragmentado de destino para poder prosseguir. Você não pode criar tags conectando-se diretamente a um membro do conjunto de réplicas de fragmento .
Marque cada fragmento.
Marque cada fragmento no centro de dados alfa
com a marcação alfa
.
sh.addShardTag("shard0000", "alfa")
Marque cada fragmento no centro de dados bravo
com a marcação bravo
.
sh.addShardTag("shard0001", "bravo")
Você pode revisar as marcações atribuídas a qualquer fragmento específico executando sh.status()
.
Defina faixas para cada tag.
Defina o intervalo para o reconhecimento de data center alfa
e associe-o à tag alfa
usando o método sh.addTagRange()
. Esse método requer:
O namespace completo da coleção de destino.
O limite inferior inclusivo do intervalo.
O limite superior exclusivo do intervalo.
O nome da marcação.
sh.addTagRange( "<database>.<collection>", { "datacenter" : "alfa", "userid" : MinKey }, { "datacenter" : "alfa", "userid" : MaxKey }, "alfa" )
Defina o intervalo para o reconhecimento de data center bravo
e associe-o à tag bravo
usando o método sh.addTagRange()
. Esse método requer:
O namespace completo da coleção de destino.
O limite inferior inclusivo do intervalo.
O limite superior exclusivo do intervalo.
O nome da marcação.
sh.addTagRange( "<database>.<collection>", { "datacenter" : "bravo", "userid" : MinKey }, { "datacenter" : "bravo", "userid" : MaxKey }, "bravo" )
Os valores MinKey
e MaxKey
são valores especiais reservados para comparações. MinKey
sempre se compara como menor que todos os outros valores possíveis, enquanto MaxKey
sempre se compara como maior que todos os outros valores possíveis. Os intervalos configurados capturam cada usuário para cada datacenter
.
Revise as alterações.
Na próxima vez que o balanceador for executado, ele dividirá e migrará partes entre os fragmentos, respeitando as faixas e as tags.
Quando o balanceamento terminar, os fragmentos marcados como alfa
devem conter documentos apenas com datacenter : alfa
, enquanto os fragmentos marcados como bravo
devem conter apenas documentos com datacenter : bravo
.
Você pode revisar a distribuição de partes executando sh.status()
.
Resolver falha de gravação
Quando o centro de dados padrão do aplicativo está inativo ou inacessível, o aplicativo altera o campo datacenter
para o outro centro de dados.
Por exemplo, o aplicativo tenta gravar o seguinte documento no centro de dados alfa
por padrão:
{ "_id" : ObjectId("56f08c447fe58b2e96f595fa"), "message_id" : 329620, "datacenter" : "alfa", "userid" : 123, ... }
Se o aplicação receber um erro na tentativa de gravação ou se a confirmação de gravação demorar muito, o aplicação registrará o centro de dados como indisponível e alterará o campo datacenter
para ponto para o centro de dados bravo
.
{ "_id" : ObjectId("56f08c457fe58b2e96f595fb"), "message_id" : 329620, "datacenter" : "bravo", "userid" : 123, ... }
O aplicativo verifica periodicamente o centro de dados alfa
para conectividade. Se o centro de dados estiver acessível novamente, o aplicativo poderá retomar as gravações normais.
Observação
É possível que a gravação original em datacenter : alfa
tenha sido bem-sucedida, especialmente se o erro estiver relacionado a um tempo limite. Em caso afirmativo, o documento com message_id : 329620
agora pode ser duplicado em ambos os centros de dados. Os aplicativos devem resolver duplicatas como parte das operações de leitura.
Resolver documentos duplicados em leituras
A lógica de comutação do aplicativo permite a possível duplicação de documentos. Ao realizar leituras, o aplicativo resolve quaisquer documentos duplicados na camada do aplicativo.
A query a seguir pesquisar por documento onde o userid
está 123
. Observe que, embora userid
faça parte da chave fragmentada, a query não inclui o campo datacenter
e, portanto, não executa uma operação de leitura direcionada.
db.collection.find( { "userid" : 123 } )
Os resultados mostram que o documento com message_id
de 329620
foi inserido no MongoDB duas vezes, provavelmente como resultado de um atraso na confirmação da escrita.
{ "_id" : ObjectId("56f08c447fe58b2e96f595fa"), "message_id" : 329620 "datacenter" : "alfa", "userid" : 123, data : {...} } { "_id" : ObjectId("56f08c457fe58b2e96f595fb"), "message_id" : 329620 "datacenter" : "bravo", "userid" : 123, ... }
O aplicativo pode ignorar as duplicatas, pegando um dos dois documentos, ou pode tentar cortar as duplicatas até que reste apenas um único documento.
Um método para cortar duplicatas é usar o método ObjectId.getTimestamp()
para extrair o carimbo de data/hora do campo _id
. O aplicativo pode então manter o primeiro documento inserido ou o último documento inserido. Isso pressupõe que o campo _id
use o MongoDB ObjectId()
.
Por exemplo, usar getTimestamp()
no documento com ObjectId("56f08c447fe58b2e96f595fa")
retorna:
ISODate("2016-03-22T00:05:24Z")
Usar getTimestamp()
no documento com ObjectId("56f08c457fe58b2e96f595fb")
retorna:
ISODate("2016-03-22T00:05:25Z")