No MongoDB Sharding é uma forma de distribuir dados através de múltiplos servidores com o objetivo de ter um grande cluster de dados.
O Recurso de Sharding é utilizando quando se trabalha com grandes datasets, essa semana por exemplo vou precisar configurar um cluster de mongodb de com 3 máquinas que vão guardar 3 terabytes de dados, sendo assim neste caso é um Pré-Requisito criar um cluster com sharding e replicação.
Mas por que usar os dois recursos? por que a replicação vai garantir a redundancia dos seus dados e o sharding vai permitir que você aumente o tamanho do seu dataset, pois pode ser que no futuro 3 terabytes não sejam mais suficientes para armazenar todos os dados, sendo assim é só adicionar mais um servidor no sharding e o tamanho total de armazenamento irá aumentar.
Abaixo uma imagem da arquitetura do cluster:
Explicando essa arquitetura. No desenho é mostrado 1 servidor rodando um serviço chamado MongoService, esse serviço é o responsável por balancear essa carga entre os 2 servidores atrás dele que estarão replicados.
Em uma arquitetura ideal é interessante ter pelo menos 2 servidores com o MongoService para garantir uma alta disponibilidade e um proxy-loadbalancer na frente, nessa arquitetura só foi colocado um pois o cliente disponibilizou somente 3 máquinas.
Atrás desse servidor com o MongoService temos 2 servidores e em cada um deles será executado 2 serviços do MongoDB de forma diferente, sendo um deles para armazenar os dados, que chamados de DataServer e o outro será o ConfigServer que irá armazenar os metadados do cluster. Uma arquitetura minima viável para criar um cluster de sharding são pelo menos 6 máquinas, abaixo segue uma imagem da documentação oficial do mongodb.
Na imagem acima são:
- 2 servidores MongoService -
- 2 ConfigServer em Replica -
- 2 Servidores em Shard em replica
Bom, agora chega de imagens e arquitetura e vamos mão na massa,
vim /etc/hosts 192.168.0.108 mongoservice 192.168.0.106 mongodb1 192.168.0.107 mongodb2
Acima são os apontamentos do meu arquivo /etc/hosts, fiz esse apontamento pois toda a configuração vou fazer através de nomes. Lembrando que esse arquivo deve ser copiado para todas as máquinas para que elas se conversem através de nomes. Para fazer a instalação do mongodb é necessário configurar o repositório e fazer a instalação dos pacotes nas 3 máquinas conforme as instruções abaixo: Configurando os repositórios.
vim /etc/yum.repos.d/mongodb-org-3.4.repo # conteudo abaixo foi adicionado no arquivo acima [mongodb-org-3.4] name=MongoDB Repository baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/ gpgcheck=1 enabled=1 gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc
Agora a instalação.
yum -y install mongodb-org
Criando o Sharding e o ConfigServer. Primeiro acesse o servidor mongodb1 e rode os seguintes comandos:
mkdir -p /data/{db,configdb} mongod --replSet "rs0" --shardsvr --port 27017 & mongod --configsvr --replSet configReplSet &
Sendo executados os comandos acima, devem existir 2 serviços rodando na máquina, um na porta 27017 e outro na porta 27019. Para validar execute o comando abaixo:
[root@localhost system]# ss -ntpl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 *:27019 *:* users:(("mongod",pid=11751,fd=6)) LISTEN 0 128 *:22 *:* users:(("sshd",pid=1147,fd=3)) LISTEN 0 100 127.0.0.1:25 *:* users:(("master",pid=1947,fd=13)) LISTEN 0 128 *:27017 *:* users:(("mongod",pid=11685,fd=6)) LISTEN 0 128 :::22 :::* users:(("sshd",pid=1147,fd=4)) LISTEN 0 100 ::1:25 :::* users:(("master",pid=1947,fd=14))
Veja que os serviços que eu citei acima estão sendo mostrados na saida do comando ss -ntpl. Agora faça a mesma coisa no mongodb2. Criando a replica dos dados. Para criar a replica dos dados em qualquer um dos servidores você pode digitar as instruções abaixo:
[root@localhost ~]# mongo MongoDB shell version v3.4.3 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.4.3 Server has startup warnings: 2017-04-16T23:19:10.154-0400 I CONTROL [initandlisten] 2017-04-16T23:19:10.154-0400 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2017-04-16T23:19:10.154-0400 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2017-04-16T23:19:10.154-0400 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended. 2017-04-16T23:19:10.154-0400 I CONTROL [initandlisten] > rs.initiate( { _id : "rs0", members: [ { _id : 0, host : "mongodb1:27017" } ] })
Com os comandos acima o próprio servidor foi adicionado ao replicaset rs0 criado anteriormente, agora para adicionar o segundo servidor execute as linhas abaixo:
[root@localhost ~]# mongo MongoDB shell version v3.4.3 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.4.3 > rs0:PRIMARY> rs.add("mongodb2") { "ok" : 1 }
Para validar que eles estão em replica, você pode acessar o console do segundo servidor e validar se ele está aparecendo como SECONDARY:
[root@localhost ~]# mongo MongoDB shell version v3.4.3 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.4.3 rs0:SECONDARY>
Na saida do comando acima é possível ver que logo no console já aparece que o servidor faz parte do rs0 e está como SECONDARY. Agora para fazer a replica do configserver, em qualquer um dos dois servidores você pode executar as seguinte instrução dentro do console do mongodb.
[root@localhost ~]# mongo localhost:27019 MongoDB shell version v3.4.3 connecting to: localhost:27019 MongoDB server version: 3.4.3 Server has startup warnings: 2017-04-16T23:15:10.890-0400 I CONTROL [initandlisten] 2017-04-16T23:15:10.890-0400 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2017-04-16T23:15:10.890-0400 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2017-04-16T23:15:10.890-0400 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended. 2017-04-16T23:15:10.890-0400 I CONTROL [initandlisten] > > rs.initiate( { ... _id: "configReplSet", ... configsvr: true, ... members: [ ... { _id: 0, host: "mongodb1:27019" }, ... { _id: 1, host: "mongodb2:27019" } ... ] ... } ) { "ok" : 1 } configReplSet:OTHER>
No exemplo acima o cliente do mongodb foi executando para acessar a parta 27019 que é a responsável por fazer a replicação do configserver e a replica foi criada nela. Com todas as replicas configuradas é hora de configurar o service. Acesse agora o servidor mongoservice e execute o seguinte comando:
mongos --configdb configReplSet/mongodb1:27019,mongodb2:27019 &
Esse comando irá iniciar um processo na porta 27017.
[root@localhost ~]# ss -ntpl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 *:22 *:* users:(("sshd",pid=1078,fd=3)) LISTEN 0 100 127.0.0.1:25 *:* users:(("master",pid=1546,fd=13)) LISTEN 0 128 *:27017 *:* users:(("mongos",pid=11497,fd=4)) LISTEN 0 128 :::22 :::* users:(("sshd",pid=1078,fd=4)) LISTEN 0 100 ::1:25 :::* users:(("master",pid=1546,fd=14))
A saida do comando acima mostra isso. O mongoservice será o ponto de acesso para as replicas configuradas no começo do artigo, agora para acessa-lo será da seguinte maneira:
[root@localhost ~]# mongo mongoservice/admin Welcome to the MongoDB shell. mongos>
Note que agora o console está diferente e ao invés de ficar somente o sinal de maior ( > ), fica aparecendo mongos>, pois estamos acessando o service e não a base diretamente. Agora para adicionar o nosso cluster de shard execute a linha abaixo:
> sh.addShard( "rs0/mongodb1:27017,mongodb2:27017" ) 2017-04-16T23:45:03.496-0400 I NETWORK [conn2] Starting new replica set monitor for rs0/mongodb1:27017,mongodb2:27017 { "shardAdded" : "rs0", "ok" : 1 }
A saida do comando acima mostra que o shard foi adicionado com sucesso. No MongoService você pode adicionar quantos clusters de shard você precisar. Agora para criar um banco de dados dentro do seu cluster é necessário executar a instrução abaixo:
mongos> sh.enableSharding("alisson") 2017-04-16T23:46:51.918-0400 I SHARDING [conn2] distributed lock 'alisson' acquired for 'enableSharding', ts : 58f43aab9202a5538a1cb23c 2017-04-16T23:46:51.919-0400 I ASIO [NetworkInterfaceASIO-ShardRegistry-0] Connecting to mongodb1:27017 2017-04-16T23:46:51.920-0400 I ASIO [NetworkInterfaceASIO-ShardRegistry-0] Successfully connected to mongodb1:27017 2017-04-16T23:46:51.921-0400 I SHARDING [conn2] Placing [alisson] on: rs0 2017-04-16T23:46:51.921-0400 I SHARDING [conn2] Enabling sharding for database [alisson] in config db 2017-04-16T23:46:51.979-0400 I SHARDING [conn2] distributed lock with ts: 58f43aab9202a5538a1cb23c' unlocked. { "ok" : 1 }
Agora você pode acessar o banco de de dados e criar um documento e fazer uma busca para ver se já funciona:
mongos> use alisson; switched to db alisson mongos> db.documentos.insert({"nome":"teste"}) WriteResult({ "nInserted" : 1 }) mongos> db.documentos.find() 2017-04-16T23:48:19.957-0400 I ASIO [NetworkInterfaceASIO-TaskExecutorPool-0-0] Connecting to mongodb1:27017 2017-04-16T23:48:19.958-0400 I ASIO [NetworkInterfaceASIO-TaskExecutorPool-0-0] Successfully connected to mongodb1:27017 { "_id" : ObjectId("58f43afd058b0dbab981298e"), "nome" : "teste" } mongos> show dbs; admin 0.000GB alisson 0.000GB config 0.000GB mongos> show collections; documentos
Note que ao fazer o find do documento é mostrado no log que o dado é buscado dentro do servidor mongodb1. Agora eu reiniciei o servidor primary e fiz a mesma busca, note que agora ele busca no segundo servidor:
mongos> db.documentos.find() 2017-04-17T00:02:22.177-0400 I ASIO [NetworkInterfaceASIO-TaskExecutorPool-0-0] Connecting to mongodb2:27017 2017-04-17T00:02:22.179-0400 I ASIO [NetworkInterfaceASIO-TaskExecutorPool-0-0] Successfully connected to mongodb2:27017 { "_id" : ObjectId("58f43afd058b0dbab981298e"), "nome" : "teste" }
Agora para finalizar é importante adicionar autenticação ao mongodb, pois por padrão o usuário é o anonimo. Para fazer isso é só executar os comandos abaixo:
use admin db.createUser( { user: "alisson", pwd: "alisson123", roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] } )