Eu uso o MongoDB para armazenar valores medidos periodicamente. A cada ~100 ms, um monte de valores é inserido como documento. Funciona bem, mas estou preocupado com problemas de desempenho. (Eu uso inserções seguras, parece que no PyMongo esse é o padrão.)
O que acontece se houver mais inserções por segundo do que o mongod é capaz de salvar no disco rígido? Haverá algum aviso ou simplesmente falhará silenciosamente?
Existe algum método para monitorar a carga de gravação? Eu encontrei apenas o db.serverStatus().writeBacksQueued
que é sempre definido como falso quando eu o chamo. Como posso testar quantos dados devo inserir para preencher a fila de gravação?
mongostat
exibe bloqueios. Isso é algo com que eu deveria me preocupar?
insert query update delete getmore command flushes mapped vsize res faults locked db idx miss % qr|qw ar|aw netIn netOut conn repl time
*117 *0 *0 *0 0 2|0 0 17.4g 35.3g 3.76g 0 .:6.5% 0 0|0 0|0 124b 6k 2 SLV 09:58:10
*111 *0 *0 *0 0 2|0 0 17.4g 35.3g 3.76g 0 .:0.8% 0 0|0 0|0 124b 6k 2 SLV 09:58:11
*111 *0 *0 *0 0 2|0 0 17.4g 35.3g 3.76g 0 .:4.2% 0 0|0 0|0 124b 6k 2 SLV 09:58:1
Devo me preocupar com bloqueios de gravação? O que acontece com uma inserção durante um período de bloqueio de gravação? É enfileirado e armazenado posteriormente?
Estou pensando em uma configuração de replicação simples usando um mestre e um escravo. A sincronização inicial ou um processo de ressincronização bloqueia os bancos de dados?
(Estou usando a versão 2.4.3.)
Atualização: acho que respondi parcialmente à minha própria pergunta. Consegui obter até 12.000 inserções por segundo usando um loop while simples inserindo um pequeno documento de teste. Mas qr|qw ainda mostra que a fila de leitura e gravação ainda está vazia:
insert query update delete getmore command flushes mapped vsize res faults locked db idx miss % qr|qw ar|aw netIn netOut conn repl time
11234 *0 2 *0 1563 1|0 1 21.9g 44.3g 1.22g 0 testdb:58.9% 0 1|0 1|1 797k 980k 6 PRI 10:26:32
12768 *0 2 *0 1284 1|0 0 21.9g 44.3g 1.22g 0 testdb:58.0% 0 0|0 0|1 881k 1m 6 PRI 10:26:33
12839 *0 2 *0 1231 1|0 0 21.9g 44.3g 1.22g 0 testdb:60.3% 0 0|0 0|1 883k 1m 6 PRI 10:26:34
12701 *0 2 *0 910 1|0 0 21.9g 44.3g 1.22g 0 testdb:61.8% 0 0|0 0|1 858k 1m 6 PRI 10:26:35
12241 *0 2 *0 1206 1|0 0 21.9g 44.3g 1.22g 0 testdb:56.7% 0 0|0 0|0 843k 1m 6 PRI 10:26:36
11581 *0 2 *0 1406 1|0 0 21.9g 44.3g 1.22g 0 testdb:61.8% 0 0|0 0|1 811k 1m 6 PRI 10:26:37
8719 *0 2 *0 1210 1|0 0 21.9g 44.3g 1.22g 0 testdb:43.8% 0 0|0 0|1 618k 762k 6 PRI 10:26:38
11429 *0 2 *0 1469 1|0 0 21.9g 44.3g 1.22g 0 testdb:60.6% 0 0|0 0|1 804k 993k 6 PRI 10:26:39
12779 *0 2 *0 1092 1|0 0 21.9g 44.3g 1.22g 0 testdb:60.2% 0 1|0 0|1 872k 1m 6 PRI 10:26:40
12757 *0 2 *0 436 1|0 0 21.9g 44.3g 1.22g 0 testdb:59.7% 0 0|0 0|1 838k 432k 6 PRI 10:26:41
Suponho que isso signifique que as inserções sozinhas não causarão muitos problemas: "As filas tenderão a aumentar se você estiver fazendo muitas operações de gravação junto com outras operações pesadas de gravação, como remoções de longo alcance". (encontrado aqui ]
Minha pergunta em aberto: o que acontece com meus dados se a fila de gravação aumentar a longo prazo?
Você respondeu algumas de suas próprias perguntas aqui, especificamente, você tem uma ideia decente sobre o aspecto do bloqueio de gravação da equação - 12.000 inserções/s leva você a ~ 60% de bloqueio de gravação. Esse é um nível razoável para obter um desempenho consistente - você terá alguma contenção e algumas operações serão um pouco mais lentas, mas você realmente deseja começar a se preocupar em cerca de 80% - como muitas coisas, quando você começa a exceder os 80% disponíveis capacidade, você começará a encontrar problemas com muito mais frequência.
Em termos de outros gargalos, e especificamente a rapidez com que você pode gravar no disco - isso pode causar problemas, mas para examinar as estatísticas relevantes ao longo do tempo, eu recomendaria instalar o MMS com o plug-in munin-node para fornecer estatísticas de hardware e IO em além das estatísticas do MongoDB.
Quando você tiver isso, as métricas que você deve ficar de olho são:
É um pouco complicado então, mas aqui está uma ideia básica:
A outra peça desse quebra-cabeça, que ainda não mencionamos, é o diário. Isso também persistirá os dados no disco (por padrão, a cada 100 ms) e, portanto, será adicionado à carga do disco se estiver no mesmo volume. Portanto, se você estiver vendo uma alta utilização de disco, mover o diário para outro disco seria uma boa ideia.
Não há "números mágicos" reais para ficar abaixo, na maioria dos casos é tudo relativo, então obtenha uma boa linha de base para o seu tráfego normal, verifique se as coisas estão melhorando e talvez teste de carga para ver quais são seus limites e quando as coisas começar a degradar e você estará em boa forma.
Depois de todo esse preâmbulo, vamos a algumas de suas perguntas:
Se você começar a estressar o disco para os níveis descritos acima, eventualmente tudo vai desacelerar e em algum ponto (e isso dependerá de tempos limite, quão robusto é seu hardware, como você lida com exceções) suas gravações falharão - se se você estiver usando uma versão recente do pymongo, usará gravações seguras por padrão e elas falharão. Se você deseja ser um pouco mais paranóico, você pode ocasionalmente fazer uma preocupação de gravação de j:true que esperará para retornar OK até que a gravação tenha chegado ao diário (ou seja, no disco). Isso, é claro, será mais lento do que uma gravação segura normal, mas será uma indicação imediata de problemas relacionados à capacidade do disco, e você pode usá-lo para bloquear/enfileirar outras operações e atuar essencialmente como um acelerador para impedir que seu banco de dados seja sobrecarregado.
Acho que cobri o bloqueio geral no início, mas para responder a esta parte especificamente: primeiro, verifique se você está usando um conjunto de réplicas , não mestre/escravo. A implementação mestre/escravo está obsoleta e não é recomendada para uso em geral. Quanto à sincronização inicial, adicionará alguma carga ao primário em termos de leituras, mas não em termos de gravações, portanto, você deve estar bem em termos de bloqueio.
Como você provavelmente pode perceber pela explicação acima, a resposta depende muito de como você escreve seu aplicativo, como escolhe ter suas gravações reconhecidas e quanta capacidade você tem disponível. Você pode, essencialmente, estar tão seguro quanto desejar quando se trata de gravar em disco no MongoDB, mas há uma compensação de desempenho, conforme mencionado na
j:true
discussão acima.Geralmente, você deseja descobrir seu fator limitante - seja bloqueio, velocidade do disco etc.
Uma última coisa,
db.serverStatus().writeBacksQueued
na verdade, é uma métrica que só será diferente de zero em um ambiente fragmentado e tem a ver com garantir que as gravações em um bloco durante uma migração sejam tratadas adequadamente (tratadas pelo ouvinte de write -back ). Portanto, é essencialmente um arenque vermelho aqui - nada a ver com o volume geral de gravação.