Olá, dev! Seja bem-vindo ao Dia 13 da sua preparação para a certificação MongoDB Associate Developer. Hoje exploraremos o mecanismo de particionamento horizontal do MongoDB: o Sharding. Veremos como distribuir terabytes de dados e cargas massivas de escrita entre múltiplos servidores de forma transparente para a aplicação.
1. Arquitetura de um Sharded Cluster
Um Sharded Cluster no MongoDB é composto por três componentes principais que trabalham de forma coordenada:
- Shards (Fragmentos): Cada shard armazena um subconjunto dos dados particionados. Em ambientes de produção, cada Shard é obrigatoriamente implantado como um Replica Set para assegurar redundância e alta disponibilidade local.
- Mongos (Query Routers): Instâncias leves e sem estado (stateless). A aplicação se conecta diretamente ao
mongoscomo se fosse um servidor MongoDB comum. Omongosinspeciona os metadados do cluster para rotear operações de escrita e leitura diretamente para os shards corretos. - Config Servers: Armazenam os metadados do cluster, mapeando exatamente quais faixas de dados (chunks) residem em cada shard. Também são configurados como um Replica Set dedicado.
2. A Escolha Crítica da `Shard Key`
A Shard Key é um campo indexado (ou índice composto) que dita como o MongoDB distribuirá os documentos da coleção entre os shards.
Estratégias de Sharding:
- Ranged Sharding (Por Intervalo): Documentos com valores próximos de chave ficam no mesmo shard. Otimiza consultas por faixa (ex:
{ idade: { $gte: 20, $lte: 30 } }), mas pode causar hotspots de escrita se o campo for monotônico (ex:createdAtfaz com que 100% das novas inserções caiam no mesmo shard final). - Hashed Sharding (Por Hash MD5): Calcula um hash de 64 bits do valor do campo. Distribui os documentos de maneira perfeitamente uniforme entre todos os shards, eliminando gargalos de escrita monotônica, mas penaliza consultas por intervalo, transformando-as em operações broadcast.
// Criando um índice hashed e habilitando o sharding na coleção
db.pedidos.createIndex({ clienteId: "hashed" })
sh.shardCollection("loja.pedidos", { clienteId: "hashed" })
3. As 3 Propriedades de Ouro de uma Shard Key
Para o exame de certificação, lembre-se sempre dos três pilares para avaliar se uma chave é adequada:
- Alta Cardinalidade (High Cardinality): A chave deve possuir um universo amplo de valores únicos (ex:
usuarioIdouuuidtêm alta cardinalidade;status: ['ABERTO', 'FECHADO']tem cardinalidade baixíssima e é péssima para Shard Key). - Baixa Frequência de Repetição (Low Frequency): Nenhum valor único deve representar uma fração massiva da coleção. Se um único ID concentrar 40% de todos os registros, causará a criação de um Jumbo Chunk (um pedaço que ultrapassa o tamanho limite e não pode ser dividido).
- Taxa de Mudança Não-Monotônica: Evite chaves que crescem sempre em uma única direção (como timestamps ou auto-incrementos em Ranged Sharding), pois todos os novos registros saturarão um único shard de escrita.
4. Chunks, Splits e o Balancer
- Chunk: Bloco contíguo de dados particionado por faixas da Shard Key. O tamanho padrão de um chunk é 64 MB.
- Chunk Split: Quando um chunk ultrapassa 64 MB, o roteador
mongoso divide em dois novos chunks lógicos. Essa divisão é apenas uma atualização de metadados nos Config Servers, sem movimentação física de arquivos. - Balancer: Processo em segundo plano que monitora a contagem de chunks em cada shard. Quando a diferença na distribuição ultrapassa o limiar de migração, o Balancer move chunks automaticamente entre os shards para restaurar o equilíbrio.
5. Performance de Consultas: Targeted vs. Scatter-Gather
- Targeted Query (Consulta Direcionada): A consulta contém a Shard Key no filtro. O
mongosenvia a requisição exclusivamente para o shard que possui o dado. Altamente eficiente e escalável. - Scatter-Gather Query (Consulta Broadcast): A consulta não contém a Shard Key. O
mongosprecisa enviar a busca para todos os shards do cluster, esperar a resposta de cada um e mesclar os resultados antes de devolver para o cliente. Deve ser evitada em rotinas de alta frequência.
// Exemplo no mongosh:
// Supondo que a Shard Key da coleção seja { clienteId: 1 }
// 1. Targeted Query (O mongos consulta apenas 1 shard):
db.pedidos.find({ clienteId: 4502 })
// 2. Scatter-Gather Query (O mongos dispara para TODOS os shards):
db.pedidos.find({ valorTotal: { $gt: 1000 } })
6. Diagnóstico Prático no `mongosh`
// 1. Obter o relatório completo da topologia do Sharded Cluster
sh.status()
// 2. Habilitar o particionamento em um banco de dados
sh.enableSharding("e_commerce")
// 3. Verificar o status do Balancer
sh.getBalancerState()
// 4. Iniciar ou pausar o processo de balanceamento
sh.startBalancer()
sh.stopBalancer()
7. Questões no Estilo Exame de Certificação
Questão 1: Uma aplicação de rastreamento de veículos insere milhões de posições por segundo com o campo dataHora sempre crescente. Ao utilizar Ranged Sharding com a chave { dataHora: 1 }, a equipe nota que um único shard está com 100% de CPU de escrita e os demais ociosos. Qual é a causa desse comportamento e a melhor solução?
A) O Balancer travou; deve-se reiniciar os Config Servers.
B) Chaves monotônicas em Ranged Sharding criam um ponto quente (write hotspot); a solução é utilizar Hashed Sharding na chave { dataHora: "hashed" } ou adotar uma Shard Key composta com alta cardinalidade não-monotônica (ex: { veiculoId: 1, dataHora: 1 }).
C) O tamanho padrão do chunk deve ser reduzido para 1 MB.
D) O MongoDB não suporta inserções simultâneas em múltiplos shards.
Resposta Correta: B. Valores estritamente crescentes em Ranged Sharding sempre caem no chunk de limite máximo superior (MaxKey), direcionando todo o tráfego de gravação para o mesmo shard. O Hashed Sharding ou chaves compostas resolvem essa distribuição.
Questão 2: O que acontece quando uma consulta find() é executada em uma coleção particionada sem incluir os campos da Shard Key no filtro de busca?
A) A operação falha imediatamente com um erro de sintaxe do mongos.
B) A consulta é executada como uma Targeted Query no nó Primary do Config Server.
C) A consulta é enviada como uma operação Scatter-Gather para todos os shards do cluster.
D) O MongoDB converte a consulta em um índice TTL temporário.
Resposta Correta: C. Sem a Shard Key no filtro, o mongos não sabe em qual shard os documentos residem, sendo obrigado a consultar todos os shards (Scatter-Gather).