Eu tinha uma configuração de 3 estilhaços e fiquei sem capacidade, então adicionei mais 3 estilhaços. (Cada fragmento é um conjunto de réplicas). Mas os dados não são distribuídos uniformemente pelo cluster. Eu tenho meu chunkSize definido para o padrão de 64 MB:
mongos> db.settings.find( { _id:"chunksize" } )
{ "_id" : "chunksize", "value" : 64 }
Eu pensei que isso significava que quando um pedaço atinge 64 MB, ele se divide em dois pedaços iguais, ambos de tamanho 32 MB. É o que está demonstrado aqui . Isso não é correto?
Aqui está minha distribuição de sharding:
mongos> db.accounts.getShardDistribution()
Shard rs_0 at rs_0/mongo_rs_0_member_1:27018,mongo_rs_0_member_2:27019,mongo_rs_0_member_3:27020
data : 137.62GiB docs : 41991598 chunks : 1882
estimated data per chunk : 74.88MiB
estimated docs per chunk : 22312
Shard rs_1 at rs_1/mongo_rs_1_member_1:27018,mongo_rs_1_member_2:27019,mongo_rs_1_member_3:27020
data : 135.2GiB docs : 41159069 chunks : 1882
estimated data per chunk : 73.56MiB
estimated docs per chunk : 21869
Shard rs_2 at rs_2/mongo_rs_2_member_1:27018,mongo_rs_2_member_2:27019,mongo_rs_2_member_3:27020
data : 219.92GiB docs : 69739096 chunks : 1882
estimated data per chunk : 119.66MiB
estimated docs per chunk : 37055
Shard rs_3 at rs_3/mongo_rs_3_member_1:27018,mongo_rs_3_member_2:27019,mongo_rs_3_member_3:27020
data : 101.52GiB docs : 30650628 chunks : 1882
estimated data per chunk : 55.23MiB
estimated docs per chunk : 16286
Shard rs_4 at rs_4/mongo_rs_4_member_1:27018,mongo_rs_4_member_2:27019,mongo_rs_4_member_3:27020
data : 103.38GiB docs : 31071379 chunks : 1883
estimated data per chunk : 56.22MiB
estimated docs per chunk : 16500
Shard rs_5 at rs_5/mongo_rs_5_member_1:27018,mongo_rs_5_member_2:27019,mongo_rs_5_member_3:27020
data : 101.1GiB docs : 30516395 chunks : 1881
estimated data per chunk : 55.04MiB
estimated docs per chunk : 16223
Totals
data : 798.77GiB docs : 245128165 chunks : 11292
Shard rs_0 contains 17.23% data, 17.13% docs in cluster, avg obj size on shard : 3KiB
Shard rs_1 contains 16.92% data, 16.79% docs in cluster, avg obj size on shard : 3KiB
Shard rs_2 contains 27.53% data, 28.45% docs in cluster, avg obj size on shard : 3KiB
Shard rs_3 contains 12.7% data, 12.5% docs in cluster, avg obj size on shard : 3KiB
Shard rs_4 contains 12.94% data, 12.67% docs in cluster, avg obj size on shard : 3KiB
Shard rs_5 contains 12.65% data, 12.44% docs in cluster, avg obj size on shard : 3KiB
O que há com isso? Como os primeiros 3 conjuntos de fragmentos/réplicas podem ter um tamanho médio maior que 64 MB quando definido como chunkSize? Rs_2 é 119mb! Rs_2 tem 27,53% dos dados quando deveria ter 16,6%.
Eu tenho uma cardinalidade muito alta em meu shardkey, e não é monotonicamente crescente.
O que devo fazer aqui? Posso encontrar manualmente pedaços grandes e dividi-los, mas isso é uma dor. Devo reduzir meu chunkSize? Existe algum serviço/chamada que preciso executar para fazer isso automaticamente?
Muito para passar aqui, então vou pegar parte por parte, primeiro dividindo:
Não é bem assim que funciona. Se você tiver um bloco de 64 MB e executar manualmente um comando splitFind , obterá (por padrão) 2 blocos divididos no ponto médio. A divisão automática é feita de maneira diferente - os detalhes são realmente bastante complexos, mas use o que eu explico como regra geral e você estará perto o suficiente.
Cada um
mongos
rastreia quantos dados foram inseridos/atualizados para cada bloco (aproximadamente). Quando ele perceber que ~20% do tamanho máximo do bloco (portanto, 12-13MiB por padrão) foi gravado em um determinado bloco, ele tentará uma divisão automática desse bloco. Ele envia um comando splitVector para o primário que possui o chunk solicitando que ele avalie o intervalo do chunk e retorne quaisquer pontos de divisão em potencial. Se o primário responder com pontos válidos, os mongos tentarão se dividir nesses pontos. Se não houver pontos de divisão válidos, os mongos tentarão novamente esse processo quando as atualizações/gravações chegarem a 40%, 60% do tamanho máximo do bloco.Como você pode ver, isso não espera que um pedaço atinja o tamanho máximo antes de dividir, na verdade, deve acontecer muito antes disso e com um cluster operando normalmente, você não deve ver pedaços tão grandes em geral.
A única coisa que impede a ocorrência de blocos grandes é a funcionalidade de divisão automática descrita acima. Os tamanhos médios dos blocos sugerem que algo está impedindo que os blocos sejam divididos. Existem alguns motivos possíveis para isso, mas o mais comum é que a chave de estilhaço não é granular o suficiente.
Se seus intervalos de chunk chegarem a um único valor de chave, nenhuma outra divisão será possível e você obterá chunks "jumbo". Eu precisaria ver os intervalos para ter certeza, mas provavelmente você pode inspecioná-los manualmente com bastante facilidade,
sh.status(true)
mas para uma versão mais facilmente digerível, dê uma olhada nestas perguntas e respostas que postei sobre como determinar a distribuição de pedaços.Se esse for o problema, você realmente só tem 2 opções - viva com os pedaços jumbo (e possivelmente aumente o tamanho máximo do pedaço para permitir que eles se movam - qualquer coisa acima do máximo será abortada e marcada como "jumbo" pelos mongos) , ou fragmente novamente os dados com uma chave de fragmentação mais granular que impeça a criação de fragmentos de chave única.
Este é um equívoco bastante comum sobre o balanceador - ele não equilibra com base no tamanho dos dados, apenas equilibra o número de blocos (que você pode ver bem distribuídos) - dessa perspectiva, um bloco com 0 documentos conta apenas o igual a um com 250 mil documentos. Portanto, o motivo do desequilíbrio em termos de dados é devido ao desequilíbrio nos próprios blocos (alguns contêm muito mais dados do que outros).
Diminuir o tamanho do bloco faria com que os mongos verificassem os pontos de divisão com mais frequência, mas não ajudaria se as divisões estivessem falhando (o que as médias do tamanho do bloco sugerem que é o caso), apenas falhará com mais frequência. Como primeiro passo, eu encontraria os maiores pedaços (veja o link de perguntas e respostas acima) e os dividiria como prioridade primeiro.
Se você for fazer alguma divisão ou movimentação manual, recomendo desligar o balanceador para que ele não segure o bloqueio de metadados e não entre em ação assim que você começar a dividir. Geralmente também é uma boa ideia fazer isso em um horário de tráfego baixo, porque, caso contrário, a divisão automática que descrevi acima também pode interferir.
Depois de uma pesquisa rápida, não tenho nada genérico imediatamente à mão, mas já vi scripts usados para automatizar esse processo. Ele tende a precisar ser personalizado para se adequar ao problema específico (imagine um desequilíbrio devido a uma chave de fragmento monotônica versus um problema com a densidade de dados do bloco, por exemplo).