MongoDB e conjuntos de dados que não cabem na RAM, por mais que você se esforce

12

Isso depende muito do sistema, mas as chances são quase certas de que passaremos de um precipício arbitrário e entraremos em problemas reais. Estou curioso para saber que tipo de regra geral existe para uma boa proporção de RAM / espaço em disco. Estamos planejando nossa próxima rodada de sistemas e precisamos fazer algumas escolhas em relação à RAM, SSDs e quanto de cada um dos novos nós obterá.

Mas agora, para alguns detalhes de desempenho!

Durante o fluxo de trabalho normal de uma única execução de projeto, o MongoDB é atingido com uma porcentagem muito alta de gravações (70-80%). Quando o segundo estágio do pipeline de processamento é atingido, a leitura é extremamente alta, pois é necessário deduplicar os registros identificados na primeira metade do processamento. Este é o fluxo de trabalho para o qual "mantenha seu conjunto de trabalho na RAM", e estamos projetando em torno dessa suposição.

O conjunto de dados inteiro é atingido continuamente com consultas aleatórias de fontes derivadas do usuário final; embora a frequência seja irregular, o tamanho geralmente é muito pequeno (grupos de 10 documentos). Como isso é voltado para o usuário, as respostas precisam estar abaixo do limite "entediado agora" de 3 segundos. Esse padrão de acesso tem muito menos probabilidade de estar no cache, portanto, provavelmente ocorrerá ocorrências no disco.

Um fluxo de trabalho de processamento secundário é uma leitura alta das execuções de processamento anteriores que podem ter dias, semanas ou até meses e são executadas com pouca frequência, mas ainda precisam ser compactadas. Até 100% dos documentos na execução de processamento anterior serão acessados. Nenhuma quantidade de aquecimento de cache pode ajudar nisso, suspeito.

Os tamanhos dos documentos finalizados variam muito, mas o tamanho médio é de cerca de 8K.

A parte de alta leitura do processamento normal do projeto sugere fortemente o uso de réplicas para ajudar a distribuir o tráfego de leitura. Li em outro lugar que um 1:10 RAM-GB para HD-GB é uma boa regra geral para discos lentos. Como estamos pensando seriamente em usar SSDs muito mais rápidos, gostaria de saber se existe uma regra semelhante. polegar para discos rápidos.

Eu sei que estamos usando o Mongo de uma maneira em que tudo em cache realmente não vai funcionar, e é por isso que estou procurando maneiras de projetar um sistema que possa sobreviver a esse uso. A todo conjunto de dados será provavelmente mais de um TB dentro de meio ano e continuar crescendo.

sysadmin1138
fonte
Uma pergunta difícil bem feita.
gWaldo
Parece que você provavelmente enfrentará problemas de bloqueio de gravação antes de poder sintonizar muito o IO, honestamente. Se você martelar o banco de dados com gravações, provavelmente reterá bloqueios de gravação por tempo suficiente para que as consultas sejam paralisadas, independentemente da velocidade da IO subjacente. Algo como o Fusion IO pode reduzir um pouco o bloqueio de gravação, mas demora algum tempo, não é uma solução real.
MrKurt
@ MrKurt Parte do que estou tentando descobrir é quando preciso fazer um shard, além de quão robusto posso criar os nós de réplica individuais. Minha especificação provisória tem um cartão SSD baseado em PCIe envolvido.
sysadmin1138
Ah, entendi. Você pode considerar o sharding desde o início, nós fazemos shards de servidor único muito. Permite contornar o bloqueio de gravação e dimensionar efetivamente as gravações para o total de núcleos. Além disso, é fácil mover shards entre servidores posteriormente.
MrKurt

Respostas:

5

Isso vai ser um monte de pequenos pontos. Infelizmente, não há uma resposta única para sua pergunta, no entanto.

O MongoDB permite que o kernel do SO lide com o gerenciamento de memória. Além de lançar o máximo de RAM possível no problema, há apenas algumas coisas que podem ser feitas para 'gerenciar ativamente' o seu Conjunto de Trabalho.

A única coisa que você pode fazer para otimizar as gravações é primeiro consultar esse registro (fazer uma leitura), para que fique na memória de trabalho. Isso evitará os problemas de desempenho associados ao Global Lock em todo o processo (que deve se tornar per-db na v2.2)

Não existe uma regra rígida para a relação RAM x SSD, mas acho que as IOPS brutas dos SSDs devem permitir uma taxa muito mais baixa. Do alto da minha cabeça, 1: 3 é provavelmente o mais baixo com o qual você deseja ir. Mas, considerando os custos mais altos e as capacidades mais baixas, é provável que você precise manter essa proporção baixa de qualquer maneira.

Em relação às 'fases de gravação versus leitura', estou lendo corretamente que, uma vez que um registro é gravado, ele raramente é atualizado ("upserted")? Se for esse o caso, pode valer a pena hospedar dois clusters; o cluster de gravação normal e o cluster otimizado para leitura para dados "antigos" que não foram modificados em [X período] . Eu definitivamente habilitaria a leitura de escravos neste cluster. (Pessoalmente, eu gerenciaria isso incluindo um valor modificado em data nos documentos de objeto do seu banco de dados.)

Se você tem a capacidade de fazer um teste de carga antes de entrar no Prod, perf monitore o inferno dele. O MongoDB foi escrito com a suposição de que ele seria frequentemente implantado em VMs (seus sistemas de referência estão no EC2); portanto, não tenha medo de compartilhar as VMs.

gWaldo
fonte
Durante o processamento, um stub inicial do documento é criado e é atualizado continuamente por vários subestágios na primeira parte do processamento. Temos ponderado a possibilidade de fazer um preenchimento manual na criação inicial para reduzir a quantidade de extensão que estamos fazendo, mas nossa porcentagem atual de bloqueio de gravação é felizmente baixa.
sysadmin1138
O conselho para ler um registro antes de gravá-lo e inseri-lo na RAM não é um bom conselho. Desde a versão 2.0 (meados de 2011), o MongoDB rende se os dados a serem acessados ​​não estiverem na RAM; portanto, você está apenas causando uma leitura extra e uma ida e volta extra ao servidor sem uma boa razão, se fizer isso, pois o bloqueio não será realizada por essa duração de qualquer maneira.
Asya Kamsky
13

Isso serve como um adendo para as outras respostas postadas aqui, que discutem muitos dos elementos relevantes a serem considerados aqui. No entanto, há outro fator, muitas vezes esquecido, quando se trata da utilização eficiente da RAM em um sistema do tipo de acesso aleatório - o readahead.

Você pode verificar as configurações atuais do readahead (no Linux) executando blockdev --report(geralmente requer privilégios sudo / root). Isso imprimirá uma tabela com uma linha para cada dispositivo de disco. A coluna RA contém o valor para readahead. Esse valor é o número de setores de 512 bytes (a menos que o tamanho do setor não seja o padrão - observe que, no momento da redação desta postagem, até discos com tamanhos maiores são tratados como setores de 512 bytes pelo kernel) que são lidos em todos os acesso ao disco.

Você pode definir a configuração de readahead para um determinado dispositivo de disco executando:

blockdev --setra <value> <device name>

Ao usar um sistema RAID baseado em software, defina o cabeçote de leitura em cada dispositivo de disco e no dispositivo que corresponde ao controlador RAID.

Por que isso é importante? Bem, o readahead usa o mesmo recurso que o MongoDB está tentando usar para otimizar suas leituras para acesso seqüencial - RAM. Quando você está fazendo leituras seqüenciais em discos giratórios (ou dispositivos que se comportam como discos giratórios de qualquer maneira - EBS, estou olhando para você), buscar os dados próximos na RAM pode aumentar o desempenho maciçamente, economizar você em buscas e uma configuração de leitura de alta leitura em o ambiente certo pode obter resultados impressionantes.

Para um sistema como o MongoDB, em que seu acesso geralmente será aleatório em um conjunto de dados, isso desperdiça memória que é melhor usada em outros lugares. O sistema, que como mencionado em outro lugar, também gerencia a memória do MongoDB, alocará um pedaço de memória para leitura quando solicitado, e, portanto, deixará menos RAM para o MongoDB usar efetivamente.

Escolher o tamanho correto do readahead é complicado e depende do seu hardware, da configuração, do tamanho do bloco, do tamanho da faixa e dos próprios dados. Se você mudar para SSDs, por exemplo, desejará uma configuração baixa, mas quão baixa dependerá dos dados.

Para explicar: você deseja garantir que o readahead seja alto o suficiente para gerar um documento completo e não precise voltar ao disco. Vamos usar o tamanho médio de 8k mencionado - já que os setores no disco geralmente têm 512 bytes, seriam necessários 16 acessos ao disco para ler todo o documento sem leitura. Se você tivesse um readahead de 16 setores ou mais, leria o documento inteiro com apenas uma viagem para o disco.

Na verdade, como os buckets de índice do MongoDB têm 8k, você nunca desejará definir o readahead abaixo de 16, ou serão necessários 2 acessos ao disco para ler em um bucket de índice. Uma boa prática geral é começar com a configuração atual, reduzir pela metade e, em seguida, reavaliar a utilização da RAM e a E / S e seguir em frente.

Adam C
fonte
1
Informações valiosas que definitivamente serão úteis quando tivermos algum hardware em casa. Obrigado!
sysadmin1138
3

Você deve considerar o uso de réplicas para consultas do usuário final e o fluxo de trabalho em outras máquinas.

Usando sua regra geral 1:10, você está vendo cerca de 128 GB de RAM para 1 TB de armazenamento em disco; Embora hoje alguns SSDs acessíveis pretendam atingir> 60K IOPS, os números do mundo real podem diferir bastante, assim como se você está usando RAID com seus SSDs ou não, e se estiver, o cartão RAID também é extremamente importante .

No momento deste post, passar de 128 GB de RAM DDR3 ECC para 256 GB parece ser cerca de 2000 $ extra em um servidor Intel de 1U, e isso fornecerá uma proporção de 1: 5 com 1 TB de dados, o que eu acho que seria um proporção ainda melhor. Se você precisar que sua carga de trabalho seja concluída o mais rápido possível, mais RAM definitivamente ajudará, mas é realmente tão urgente?

Você precisará fazer também alguns ajustes no sistema de arquivos, algo como "noatime, data = writeback, nobarrier" no ext4, e talvez seja necessário fazer alguns ajustes nas configurações do kernel para extrair o máximo de desempenho possível do seu sistema.

Se você optar pelo RAID, o RAID-10 será uma boa escolha, e com o controlador RAID adequado oferecerá um aumento de desempenho, mas reduzirá pela metade o espaço disponível. Você também pode procurar no RAID50 se quiser um aumento de desempenho decente sem reduzir pela metade o espaço disponível. O risco de executar um RAID é que você não tem mais acesso ao TRIM em suas unidades, o que significa que, de vez em quando, é necessário mover seus dados, interromper o RAID, TRIM as unidades e recriar o RAID.

Por fim, você precisa decidir quanta complexidade deseja, quanto dinheiro deseja gastar e com que rapidez deseja que sua carga de trabalho seja processada. Também avaliaria se o MongoDB é o banco de dados ideal para usar, pois você ainda pode usar o Mongo para consultas de usuários finais que precisam de respostas rápidas, mas usa outra coisa para processar seus dados, que não precisam estar prontos em alguns segundos , e também pode permitir que você espalhe sua carga de trabalho por várias máquinas com mais facilidade.

gekkz
fonte