Escalando o MySQL com Docker e MaxScale

postado em: Tutoriais | Comments

Vocês já conhecem o MySQL, mas já conhecem o MaxScale e o Docker?

A necessidade de se ter um serviço que fique 100% do tempo no ar, vem se tornando cada vez maior, principalmente quando falamos de banco de dados. Ter dois servidores que funcionem como Failover para catástrofes ( MASTER e SLAVE ) já não é mais suficiente. Você precisa ter uma arquitetura que suporte a carga de acessos e atenda a todas as requisições de forma ágil.Para isso, você precisa saber escalar a sua arquitetura.

O que é Escalabilidade?

Quatro características são essenciais para atingir os altos níveis de escalabilidade que as empresas atuais requerem. São elas:

  • A habilidade de tratar grandes cargas de trabalho;
  • A habilidade de entregar altos níveis de performance;
  • A capacidade de crescer fácil e rapidamente;
  • Preço e performance competitivos com o mercado.

Existem dois tipos de escalabilidade:

  • Escalabilidade horizontal ou scale out: consiste em adicionar uma nova máquina no cluster, visando aumentar a capacidade do sistema distribuído;
  • Escalabilidade vertical ou scale up: trata-se do upgrade em um servidor já existente na rede, podendo ser a substituição, reposição ou a adição de novos recursos, como memória ou discos rígidos, por exemplo.

O scale out, além de ser mais eficiente, você consegue reduzir custos com este tipo de escalonamento. Podendo atender mais, com menos recursos. Um exemplo de scale out é a estrutura abaixo.

 

Arquitetura altamente escalável
Arquitetura com MySQL, MaxScale e Docker.

A estrutura acima foi montada com os seguintes serviços / servidores:

  • Duas máquinas virtuais com o Docker instalado;
  • Cada máquina possui dois containers. Os de escrita (RW) e os somente leitura (RO);
  • Uma máquina virtual (Pode ser um container também) com o MaxScale configurado.

Quando a aplicação, ou o desenvolvedor se conectar ao ip do servidor do MaxScale e executar uma query, será feita uma análise se é uma query de escrita ou de consulta, assim, encaminhará a conexão para o seu backend processar. No caso do backend RW, só será enviada uma requisição para o servidor secundário, caso o primário caia. Já no caso do backend RO, é load balance, ou seja, uma requisição para cada servidor, salvo se um dos servidores cair, neste caso as requisições serão encaminhadas para apenas um dos servidores.

Se precisar aumentar a capacidade do cluster, basta subir mais containers ou mais servidores de Docker com mais containers instalados.

 Configurando o Docker

 

docker-logo

Vamos começar com a estrutura dos servidores, ou seja, o Docker. Mas, o que é o Docker?

Primeiro temos que definir o que não é Docker. Docker não é um sistema de virtualização tradicional. Enquanto em um ambiente de virtualização tradicional nós temos um S.O. completo e isolado, dentro do Docker nós temos recursos isolados que utilizando bibliotecas de kernel em comum (entre host e container), isso é possível pois o Docker utiliza como backend o nosso conhecido LXC. Docker é uma plataforma Open Source escrito em Go, que é uma linguagem de programação de alto desempenho desenvolvida dentro do Google, que facilita a criação e administração de ambientes isolados.

Fonte: www.mundodocker.com.br
Fonte: www.mundodocker.com.br

É claro que esta explicação breve, não nos dará o conhecimento ideal para montar a estrutura, e eu indico que façam uma leitura em alguns artigos no Mundo Docker caso não possuam conhecimento nesta tecnologia.

Agora que já sabemos o necessário sobre Docker, vamos subir os nossos containers no servidor DOCKER01 e DOCKER2. Eu não me preocupei em instalar o mysql dentro de uma imagem, utilizei a imagem oficial da Oracle que está no Docker Hub. Assim temos uma imagem 100% funcional e não perdemos tempo instalando e configurando.
Uma característica legal do Docker é que se você criar o container e criar um volume, ao excluir o container, os dados que foram colocados no volume mapeado, não serão excluídos. Assim você consegue matar e subir o seu container sem preocupações.

[email protected]:~# docker run --name MYSQLBOX01 -v /var/lib/mysql:/home/mysqlbox01 -e MYSQL_ROOT_PASSWORD=*** -p 3001:3306 -d mysql/mysql-server
[email protected]:~# docker run --name MYSQLBOX02 -v /var/lib/mysql:/home/mysqlbox02 -e MYSQL_ROOT_PASSWORD=*** -p 3002:3306 -d mysql/mysql-server
[email protected]:~# docker run --name MYSQLBOX03 -v /var/lib/mysql:/home/mysqlbox03 -e MYSQL_ROOT_PASSWORD=*** -p 3003:3306 -d mysql/mysql-server
[email protected]:~# docker run --name MYSQLBOX04 -v /var/lib/mysql:/home/mysqlbox04 -e MYSQL_ROOT_PASSWORD=*** -p 3004:3306 -d mysql/mysql-server

Agora que já temos os nosso quatro containers criados, vamos para o próximo nível.

Configurando o MySQL

mysql-logoPara este artigo, eu usei o MySQL 5.7 e testei replicação multi source, que é uma nova feature do MySQL, assim, garantimos que mesmo que um dos containers caia, não afete a replicação de dados entre os servidores. Este tipo de replicação faz com que um servidor consiga baixar os dados de dois ou mais servidores master, assim, um servidor não fica acorrentado ao seu único master. Para entender melhor como funciona uma replicação de MySQL e como criar os usuários corretamente, indico que façam a leitura de um outro artigo meu Alta disponibilidade com MySQL – Parte 2.

Para acessar um container que esteja rodando o MySQL, basta executar o comando:

[email protected]:~# docker exec -it NOME OU ID DO CONTAINER bash

 Vamos até o my.cnf e vamos configurá-lo da seguinte forma:

binlog-checksum = CRC32
binlog-format = MIXED
expire_logs_days = 2
enforce_gtid_consistency = true
gtid_mode = on
master_info_repository = TABLE
master_verify_checksum = 1
max_binlog_size = 200M
max_relay_log_size = 200M
log-bin = MYSQLBOX01-bin                
log-bin-index = MYSQLBOX01-bin.index    
log_bin_trust_function_creators = 1
relay_log_info_repository = TABLE
report_host = MYSQLBOX01                
server_id = 1

Só não esqueça de fazer isto em todos os containers e trocar o ID e o nome do container. Feito isso, saia do container com CTRL + P + Q, pare e suba o container.

Agora para sincronizar os servidores, você deve se conectar no MySQL e executar o seguinte comando:

mysql> CHANGE MASTER TO MASTER_HOST="IPDOSERVIDOR", MASTER_USER="USER", MASTER_PASSWORD="******", MASTER_PORT=3002, MASTER_AUTO_POSITION = 1 FOR CHANNEL 'MYSQLBOX02';

 Explicando:

  • MASTER_HOST é o IP do servidor de Docker;
  • MASTER_PORT é a porta aberta no servidor de Docker, que é passada por parâmetro quando criamos o container;
  • FOR CHANNEL pode ser qualquer nome, mas, eu preferi colocar o nome do container que é dono da porta e IP que configurei

Então podemos configurar da seguinte forma

Exemplo de sincronização
Exemplo de sincronização

Para startar a replicação, execute o comando:

mysql> START SLAVE FOR CHANNEL 'mysqlbox01';

O nome do CHANNEL é aquele que passamos no comando acima no “FOR CHANNEL”, então, precisamos subir os três canais que configuramos, por container. 

Com os nossos MySQL configurados e sincronizados, vamos ao próximo passo.

Configurando o MaxScale

 

 

MaxScale_MySQLBOX

 

O MaxScale é uma plataforma do MariaDB de roteamento de dados de aplicativos para banco de dados. É feita uma filtragem das querys que estão chegando via TCP e é feito o encaminhamento destas requisções para o cluster de bancos que fica abaixo. O MaxScale simplifica a interoperabilidade entre bancos de dados, ou seja, ajuda torna mais fácil e escalável a comunicação transparente entre aplicação e banco de dados. Se quiser saber um pouco mais sobre esta ferramenta, basta acessar este link.

Para baixar o pacote, você pode acessar este link e fazer o download compatível com a sua distro e versão. Como estou usando o Ubuntu 16.04, vou baixar o maxscale-1.4.3-1.ubuntu.xenial.x86_64.deb e o instalar com o comando:

[email protected]:~# dpkg --install maxscale-1.4.3-1.ubuntu.xenial.x86_64.deb

Precisamos criar um usuário nos servidores de MySQL para que o MaxScale se conecte e consiga monitorar.

mysql> GRANT REPLICATION SLAVE ON *.* TO [email protected]'%' IDENTIFIED BY '*************';

Com o MaxScale instalado, crie o diretório /etc/maxscale.d e dentro dele vamos colocar o arquivo de configuração “maxscale.conf”.

# Global parameters

[maxscale]
threads=1

# Servers

[MYSQLBOX01]
type=server
address=10.1.1.1
port=3001
protocol=MySQLBackend

[MYSQLBOX02]
type=server
address=10.1.1.1
port=3002
protocol=MySQLBackend

[MYSQLBOX03]
type=server
address=10.1.1.2
port=3003
protocol=MySQLBackend

[MYSQLBOX04]
type=server
address=10.1.1.2
port=3004
protocol=MySQLBackend

# Monitor

[MySQL Monitor]
type=monitor
module=mysqlmon
servers=MYSQLBOX01,MYSQLBOX02,MYSQLBOX03,MYSQLBOX04
user=USER
passwd=PASSWORD
monitor_interval=10000

# Services

[Read-Only Service]
type=service
router=readconnroute
servers=MYSQLBOX03,MYSQLBOX04
user=USER
passwd=PASSWORD
router_options=slave

[Read-Write Service]
type=service
router=readwritesplit
servers=MYSQLBOX01,MYSQLBOX02
user=USER
passwd=PASSWORD
max_slave_connections=100%

# Listener

[Read-Only Listener]
type=listener
service=Read-Only Service
protocol=MySQLClient
port=3306

[Read-Write Listener]
type=listener
service=Read-Write Service
protocol=MySQLClient
port=3306

Em algumas distros, não é criado o systemd e nem o service do MaxScale, logo, precisamos criar esta configuração em /etc/systemd/system/maxscale.service

[Unit]
Description=MariaDB MaxScale
After=network.target

[Service]
PIDFile=/var/run/maxscale/maxscale.pid
ExecStart=/usr/bin/maxscale -f /etc/maxscale.d/maxscale.cnf
ExecReload=/bin/kill -HUP $MAINPID
Type=fork

 Feito isso, execute os comandos:

[email protected]:~# systemctl daemon-reload
[email protected]:~# systemctl start maxscale
[email protected]:~# systemctl enable maxscale

Com todos os serviços configurados, você agora já possui uma estrutura escalável. Se precisar atender mais requisições, basta subir novos containers e os colocar no MaxScale para fazer o balanceamento da carga entre eles.

Allan Moraes

Allan Moraes é gaúcho e entusiasta open source. Trabalha em uma Startup com foco em Plataforma como Serviço (PaaS), é especialista em MySQL, High Availability e High Scalability Architecture.