English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Entendendo profundamente a gestão de sharding no MongoDB

Prólogo

No MongoDB (versão 3.2.9Aqui, o cluster particionado (sharded cluster) é uma maneira de expandir horizontalmente o desempenho do sistema de banco de dados, que pode armazenar o conjunto de dados distribuído em diferentes shards (shard), cada shard armazena apenas uma parte do conjunto de dados, o MongoDB garante que não haja dados duplicados entre os shards, a soma dos dados armazenados em todos os shards é o conjunto de dados completo. O armazenamento distribuído do conjunto de dados pode distribuir a carga em vários shards, cada shard é responsável por ler e escrever apenas uma parte dos dados, aproveitando ao máximo os recursos do sistema de shard, aumentando a capacidade de processamento do sistema de banco de dados.

O conjunto de dados é dividido em blocos de dados (chunk), cada bloco contém vários documentos (doc), e os blocos de dados são armazenados de forma distribuída no cluster de particionamento. O MongoDB é responsável por rastrear a distribuição dos blocos de dados nos shards, quais dados os shards armazenam, chamados de metadados do shard, armazenados no banco de dados config no config server, geralmente usando3O config server, todos os bancos de dados config nos config servers devem ser completamente idênticos. Através do mongos, é possível acessar diretamente o banco de dados config, verificar os metadados das partições; o mongo shell oferece a função sh auxiliar, que pode visualizar de forma segura as informações de metadados do cluster de particionamento.

Para consultar qualquer shard, apenas obterá a subconjunto de dados da collection na partição atual, não o conjunto de dados completo. A aplicação só precisa se conectar ao mongos, e todas as operações de leitura e escrita serão automaticamente roteadas para o shard correspondente pelo mongos. O MongoDB realiza a implementação subjetiva de particionamento para a aplicação através do mongos, para a aplicação, parece que está acessando o conjunto de dados completo.

primeiro, shard primário

No cluster de sharding, não todas as coleções são armazenadas distribuídas, apenas as coleções que utilizam sh.shardCollection() explicitamente para fragmentar a coleção serão armazenadas distribuídas em diferentes shards. Para coleções não fragmentadas (un-coleções fragmentadas), seus dados serão armazenados apenas no shard primário (Primary shard), por padrão, o shard primário é o shard originalmente criado para armazenar os dados das coleções não fragmentadas do banco de dados. Cada banco de dados tem um shard primário.

Cada banco de dados em um cluster de sharding tem um shard primário que contém todos os dados não-coleções fragmentadas para aquele banco de dados. Cada banco de dados tem seu próprio shard primário.

Por exemplo, um cluster de sharding com três shards: shard1, shard2, shard3, no shard fragmentado1Crie um banco de dados blog. Se o banco de dados bolg for fragmentado, o MongoDB criará automaticamente no shard2, shard3Crie um banco de dados blog com a mesma estrutura no banco de dados superior, o shard primário do banco de dados blog é Shard1.

Ilustração, Collection2O shard primário é ShardA.

Usar o comando movePrimary para alterar o shard primário padrão do banco de dados, as coleções não fragmentadas serão movidas do shard atual para o novo shard primário.

db.runCommand({ movePrimary : "test", to : "shard0001})

Após alterar o shard primário do banco de dados com o comando movePrimary, as informações de configuração no servidor de configuração são as mais recentes, enquanto as informações de configuração no cache do mongos ficam desatualizadas.MongoDB oferece o comando: flushRouterConfig para forçar o mongos a obter as informações de configuração mais recentes do servidor de configuração, atualizando o cache do mongos.

db.adminCommand({"flushRouterConfig":}1})

二,分片的元数据

不要直接到config server上查看分片集群的元数据信息,这些数据非常重要,安全的方式是通过mongos连接到config数据查看,或者使用sh辅助函数查看。

使用sh辅助函数查看

sh.status()

连接到mongos查看config数据库中的集合

mongos> use config

1,shards 集合保存分片信息

db.shards.find()

shard的数据存储在host指定的 replica set 或 standalone mongod中。

{
 "_id" : "shard_name",
 "host" : "replica_set_name"/host:port",
 "tag":[shard_tag1,shard_tag2] 
}

2,databases集合保存分片集群中所有数据库的信息,不管数据库是否分片

db.databases.find()

如果在数据库上执行sh.enableSharding(“db_name”) ,那么字段partitioned字段值就是true;primary 字段指定数据库的主分片(primary shard)。

{
 "_id" : "test",
 "primary" : "rs0",
 "partitioned" : true
}

3,collections集合保存所有已分片集合的信息,不包括非分片集合(un-sharded collections)

key是:分片的片键

db.collections.find()
{
 "_id" : "test.foo",
 "lastmodEpoch" : ObjectId("57dcd4899bd7f7111ec15f16")
 "lastmod" : ISODate("1970-02-19T17:02:47.296Z"),
 "dropped" : false,
 "key" : {
  "_id" : { 1
 },
 "unique" : true
}

4,chunks 集合保存数据块信息,

ns:分片的集合,结构是:db_name.collection_name

min 和 max: 片键的最小值和最大值

shard:块所在的分片

db.chunks.find()
{
 "_id" : "test.foo"-_id_MinKey",
 "lastmod" : Timestamp(1, 1),
 "lastmodEpoch" : ObjectId("57dcd4899bd7f7111ec15f16")
 "ns" : "test.foo",
 "min" : {
  "_id" : { 1
 },
 "max" : {
  "_id" : { 3087
 },
 "shard" : "rs0"
}

5A coleção de changelog registra as operações do cluster de fragmentação, incluindo a divisão e migração do chunk, a adição ou exclusão de shards

Campo what: representa o tipo de operação, por exemplo: multi-A operação de split representa a divisão do chunk

"what" : "addShard"
"what" : "shardCollection.start"
"what" : "shardCollection.end" 
"what" : "multi"-,

6A coleção de tags registra o tag do shard e o intervalo de chave do shard correspondente

{
 "_id" : { "ns" : "records.users", "min" : { "zipcode" : "10001},
 "ns" : "records.users",
 "min" : { "zipcode" : "10001},
 "max" : { "zipcode" : "10281},
 "tag" : "NYC"
}

7A coleção de configurações registra o estado do balancer e o tamanho do chunk, o tamanho padrão do chunk é64MB.

{"_id" : "chunksize", "value" :} 64 }
{"_id" : "balancer", "stopped" : false }

8A coleção de bloqueios registra o bloqueio distribuído (bloqueio distribuído), garantindo que apenas um instância de mongos possa executar tarefas administrativas no cluster de fragmentação.

O mongos, ao atuar como balancer, obterá um bloqueio distribuído e inserirá um documento no config.locks.

A coleção de bloqueios armazena um bloqueio distribuído. Isso garante que apenas uma instância de mongos possa executar tarefas administrativas no cluster ao mesmo tempo. O mongos atuando como balancer obtém um bloqueio inserindo um documento semelhante ao seguinte na coleção de bloqueios.

{
 "_id": "balancer"
 "process": "example.net:40000:1350402818:16807",
 "state": 2,
 "ts": ObjectId("507daeedf40e1879df62e5f3")
 "when": ISODate("2012-10-16T19:01:01.593Z"),
 "who": "example.net:40000:1350402818:16807:Balancer:282475249",
 "why": "doing balance round"
}

Terceiro, excluir a espécie

Ao excluir a espécie, é necessário garantir que os dados da espécie sejam movidos para outras espécies, para conjuntos fragmentados, use o balancer para migrar os blocos de dados, para conjuntos não fragmentados, é necessário modificar o shard principal do conjunto.

1,excluir os dados do conjunto fragmentado

step1,certifique-se de que o balancer está ativado

sh.setBalancerState(true);

step2,migrar todos os conjuntos fragmentados para outras espécies

use admin
db.adminCommand({"removeShard":"shard_name"})

O comando removeShard migra o bloco de dados da espécie atual para outras espécies, se houver muitos blocos de dados na espécie, o processo de migração pode demorar muito tempo.

step3,verificar o estado da migração do bloco de dados

use admin
db.runCommand({ removeShard: "shard_name" })

O comando removeShard permite verificar o estado da migração do bloco de dados, o campo remaining representa o número de blocos de dados restantes

{
  "msg": "draining ongoing",
 "state": "ongoing",
 "remaining": {
  "chunks": 42,
  "dbs": 1
 },
 "ok" : 1
}

step4,o bloco de dados foi migrado com sucesso

use admin
db.runCommand({ removeShard: "shard_name" })
{
 "msg": "removeshard completed successfully",
 "state": "completed",
 "shard" : "shard_name"
 "ok" : 1
}

2excluir bancos de dados não shardados

step1verificar bancos de dados não shardados

Bancos de dados não shardados incluem duas partes:

     1o banco de dados não é shardado, esses dados não usaram sh.enableSharding(“db_name”) , no banco de dados config, o campo partitioned desse banco de dados é false

     2a coleção não é shardada, ou seja, o shard atual é o shard primário dessa coleção

use config
db.databases.find({$or:[{"partitioned":false},{"primary":"shard_name"}]})

Para bancos de dados com partitioned=false, todos os dados são armazenados no shard atual; para bancos de dados com partitioned=true e primary="shard_name", isso indica que há dados não shardados (un-as coleções sharded (coleções divididas) armazenadas neste banco de dados, é necessário alterar o shard primário dessas coleções.

step2modificar o shard primário do banco de dados

db.runCommand( { movePrimary: "db_name", to: "new_shard" })

Quatro, adicionar sharding

Como o sharding armazena apenas uma parte do conjunto de dados, para garantir a alta disponibilidade dos dados, é recomendável usar um Replica Set como shard, mesmo que o Replica Set contenha apenas um membro. Conecte-se ao mongos e use a função auxiliar sh para adicionar sharding.

sh.addShard("replica_set_name/host:port)

Não é recomendável usar mongod standalone como shard

sh.addShard("host:port")

Cinco, chunks jumbos

Em alguns casos, os chunks podem continuar crescendo, ultrapassando o limite do tamanho do chunk, tornando-se chunks jumbos (chunks jumbos), e a razão para isso é que todos os documentos do chunk usam a mesma chave de shard (shard key), o que impede o MongoDB de dividir esse chunk. Se esse chunk continuar crescendo, isso levará a uma distribuição desigual dos chunks, tornando-se um gargalo de desempenho.

ao migrar chunks, há limites: o tamanho de cada chunk não pode exceder2.510.000 documentos, ou1.3multiplos do valor configurado. O valor padrão para o tamanho do chunk é64MB, chunks que excedem o limite são marcados como chunks jumbos pelo MongoDB, e o MongoDB não pode migrar chunks jumbos para outros shards.

O MongoDB não pode mover um bloco se o número de documentos no bloco exceder ou}} 250000 documentos ou 1.3 vezes o resultado da divisão do tamanho do bloco configurado pelo tamanho médio do documento.

1verificar grandes blocos

Usando sh.status(), você pode descobrir grandes blocos, e há um sinal de jumbo no final dos grandes blocos

 { "x" : 2 } -->> { "x" : 3 } em: shard-um Timestamp(2, 2) jumbo

2distribuir o grande bloco

Os grandes blocos não podem ser divididos, não podem ser distribuídos automaticamente pelo balancer, e devem ser distribuídos manualmente.

step1desativar o balancer

sh.setBalancerState(false)}

step2aumentar o valor de configuração do tamanho do bloco

Como o MongoDB não permite mover grandes blocos que excedem o limite de tamanho, é necessário temporariamente aumentar o valor de configuração do tamanho do bloco, e então distribuir uniformemente o grande bloco no cluster de shards.

use config
db.settings.save({"_id":"chunksize","value":"1024"})

step3mover o grande bloco

sh.moveChunk("db_name.collection_name",{sharded_filed:"value_in_chunk"},"new_shard_name")

step4ativar o balancer

sh.setBalancerState(true)

step5atualizar o cache de configuração do mongos

Força o mongos a sincronizar as informações de configuração do servidor de configuração e atualizar o cache.

use admin
db.adminCommand({ flushRouterConfig: 1 })

Seis, balancer

O balancer é transformado pelo mongos, isso significa que o mongos não só é responsável por rotear consultas para o shard correspondente, mas também é responsável pelo equilíbrio de dados. Geralmente, o MongoDB processa automaticamente o equilíbrio de dados, pode verificar o estado do balancer através de config.settings ou através da função auxiliar sh

sh.getBalancerState()

Retorna true, indicando que o balancer está em execução, o sistema processa automaticamente a equilíbrio de dados, o uso da função auxiliar sh pode desativar o balancer

sh.setBalancerState(false)}

O balancer não pode interromper imediatamente a operação de migração de chunks em andamento, quando o mongos se torna balancer, solicita um lock de balancer, verifica o conjunto config.locks,

use config
db.locks.find({"_id":"balancer"})
--ou 
sh.isBalancerRunning()

se state=2,o que significa que o balancer está em estado ativo, se state=0, significa que o balancer foi desligado.

O processo de equalização realmente envolve a migração de dados de um shard para outro shard, ou primeiramente dividir um grande chunk em chunks menores, e em seguida,迁移小块到其他shards, a migração e a divisão dos blocos aumentam a carga IO do sistema, é melhor limitar o tempo ativo do equalizador no tempo de inatividade do sistema, pode ser configurado o tempo ativo da janela do balancer, limitando o balancer a realizar operações de divisão e migração de dados no intervalo de tempo especificado.

use config
db.settings.update(
  {"_id":"balancer"},
  "$set":{"activeWindow":{"start":"23:00","stop":"04:00"}}),
  true
)

Os objetos que são divididos e movidos pelo equalizador são chunks, o equalizador garante apenas que o número de chunks seja equilibrado em cada shard, não necessariamente o número de documentos contidos em cada chunk. Pode haver alguns chunks que contêm muitos documentos, enquanto outros podem conter poucos, até mesmo nenhum documento. Portanto, deve-se escolher com cuidado a chave de índice do shard, ou seja, a chave de shard, se um campo pode atender à maioria das necessidades de consulta e distribuir uniformemente o número de documentos, então esse campo é a melhor escolha para a chave de shard.

Resumo

Isso é tudo o que há no artigo, espero que ajude um pouco no seu aprendizado ou trabalho, qualquer dúvida, podem deixar um comentário para trocar.

Você também pode gostar