MySQL InnoDB Cluster consiste em 3 componentes:
- Replicação de grupo MySQL (um grupo de servidores de banco de dados que se replica entre si com tolerância a falhas).
- Roteador MySQL (roteador de consulta para os nós de banco de dados íntegros)
- MySQL Shell (ajudante, cliente, ferramenta de configuração)
Na primeira parte deste passo a passo, vamos implantar um MySQL InnoDB Cluster. Há vários tutoriais práticos disponíveis on-line, mas este passo a passo abrange todas as etapas/comandos necessários para instalar e executar o cluster em um só lugar. Abordaremos as operações de monitoramento, gerenciamento e dimensionamento, bem como algumas pegadinhas ao lidar com o MySQL InnoDB Cluster na segunda parte deste post do blog.
O diagrama a seguir ilustra nossa arquitetura pós-implantação:
Vamos implantar um total de 4 nós; Uma replicação de grupo MySQL de três nós e um nó de roteador MySQL co-localizado dentro do servidor de aplicativos. Todos os servidores estão rodando no Ubuntu 18.04 Bionic.
Instalando o MySQL
As etapas a seguir devem ser executadas em todos os nós do banco de dados db1, db2 e db3.
Em primeiro lugar, temos que fazer algum mapeamento de host. Isso é crucial se você deseja usar o nome do host como o identificador de host no InnoDB Cluster e esta é a maneira recomendada de fazer. Mapeie todos os hosts da seguinte forma dentro de /etc/hosts:
$ vi /etc/hosts
192.168.10.40 router apps
192.168.10.41 db1 db1.local
192.168.10.42 db2 db2.local
192.168.10.43 db3 db3.local
127.0.0.1 localhost localhost.localdomain
Pare e desative o AppArmor:
$ service apparmor stop
$ service apparmor teardown
$ systemctl disable apparmor
Baixe o repositório de configuração APT mais recente do site do repositório MySQL Ubuntu em https://repo.mysql.com/apt/ubuntu/pool/mysql-apt-config/m/mysql-apt-config/ . No momento da redação deste artigo, o mais recente é datado de 15 de outubro de 2019, que é mysql-apt-config_0.8.14-1_all.deb:
$ wget https://repo.mysql.com/apt/ubuntu/pool/mysql-apt-config/m/mysql-apt-config/mysql-apt-config_0.8.14-1_all.deb
Instale o pacote e configure-o para "mysql-8.0":
$ dpkg -i mysql-apt-config_0.8.14-1_all.deb
Instale a chave GPG:
$ apt-key adv --recv-keys --keyserver ha.pool.sks-keyservers.net 5072E1F5
Atualize o repolimento:
$ apt-get update
Instale o Python e seguido pelo servidor MySQL e shell MySQL:
$ apt-get -y install mysql-server mysql-shell
Você será presenteado com os seguintes assistentes de configuração:
- Definir uma senha root - Especifique uma senha forte para o usuário root do MySQL.
- Defina o método de autenticação - Escolha "Usar método de autenticação legado (manter compatibilidade com MySQL 5.x)"
MySQL deve ter sido instalado neste momento. Verifique com:
$ systemctl status mysql
Certifique-se de obter um estado "ativo (em execução)".
Preparando o servidor para o cluster InnoDB
As etapas a seguir devem ser executadas em todos os nós do banco de dados db1, db2 e db3.
Configure o servidor MySQL para dar suporte à Replicação de Grupo. A maneira mais fácil e recomendada de fazer isso é usar o novo MySQL Shell:
$ mysqlsh
Autentique-se como usuário root local e siga o assistente de configuração conforme mostrado no exemplo abaixo:
MySQL JS > dba.configureLocalInstance("[email protected]:3306");
Depois de autenticado, você deve receber várias perguntas como as seguintes:
Respostas a essas perguntas com as seguintes respostas:
- Escolha 2 - Crie uma nova conta de administrador para o cluster InnoDB com concessões mínimas necessárias
- Nome da conta:[email protected]%
- Senha:mys3cret&&
- Confirme a senha:mys3cret&&
- Deseja realizar as alterações de configuração necessárias?:y
- Deseja reiniciar a instância após configurá-la?:y
Não se esqueça de repetir o procedimento acima em todos os nós do banco de dados. Neste ponto, o daemon MySQL deve estar escutando todos os endereços IP e a Replicação de Grupo está habilitada. Agora podemos prosseguir para criar o cluster.
Criando o cluster
Agora estamos prontos para criar um cluster. No db1, conecte-se como administrador de cluster do MySQL Shell:
MySQL|JS> shell.connect('[email protected]:3306');
Creating a session to '[email protected]:3306'
Please provide the password for '[email protected]:3306': ***********
Save password for '[email protected]:3306'? [Y]es/[N]o/Ne[v]er (default No): Y
Fetching schema names for autocompletion... Press ^C to stop.
Your MySQL connection id is 9
Server version: 8.0.18 MySQL Community Server - GPL
No default schema selected; type \use <schema> to set one.
<ClassicSession:[email protected]:3306>
Você deve estar conectado como [email protected] (você pode saber olhando a string do prompt antes de '>'). Agora podemos criar um novo cluster:
MySQL|db1:3306 ssl|JS> cluster = dba.createCluster('my_innodb_cluster');
Verifique o status do cluster:
MySQL|db1:3306 ssl|JS> cluster.status()
{
"clusterName": "my_innodb_cluster",
"defaultReplicaSet": {
"name": "default",
"primary": "db1:3306",
"ssl": "REQUIRED",
"status": "OK_NO_TOLERANCE",
"statusText": "Cluster is NOT tolerant to any failures.",
"topology": {
"db1:3306": {
"address": "db1:3306",
"mode": "R/W",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.18"
}
},
"topologyMode": "Single-Primary"
},
"groupInformationSourceMember": "db1:3306"
}
Neste ponto, apenas db1 faz parte do cluster. O modo de topologia padrão é Single-Primary, semelhante a um conceito de conjunto de réplicas em que apenas um nó é um gravador por vez. Os nós restantes no cluster serão leitores.
Preste atenção no status do cluster que diz OK_NO_TOLERANCE e mais explicações na chave statusText. Em um conceito de conjunto de réplicas, um nó não fornecerá tolerância a falhas. São necessários no mínimo 3 nós para automatizar o failover do nó primário. Nós vamos olhar para isso mais tarde.
Agora adicione o segundo nó, db2 e aceite o método de recuperação padrão, "Clone":
MySQL|db1:3306 ssl|JS> cluster.addInstance('[email protected]:3306');
A captura de tela a seguir mostra o progresso da inicialização do db2 após executarmos o comando acima. A operação de sincronização é realizada automaticamente pelo MySQL:
Verifique o status do cluster e do db2:
MySQL|db1:3306 ssl|JS> cluster.status()
{
"clusterName": "my_innodb_cluster",
"defaultReplicaSet": {
"name": "default",
"primary": "db1:3306",
"ssl": "REQUIRED",
"status": "OK_NO_TOLERANCE",
"statusText": "Cluster is NOT tolerant to any failures.",
"topology": {
"db1:3306": {
"address": "db1:3306",
"mode": "R/W",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.18"
},
"db2:3306": {
"address": "db2:3306",
"mode": "R/O",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.18"
}
},
"topologyMode": "Single-Primary"
},
"groupInformationSourceMember": "db1:3306"
}
Neste ponto, temos dois nós no cluster, db1 e db2. O status ainda está mostrando OK_NO_TOLERANCE com mais explicações no valor statusText. Conforme declarado acima, a Replicação de Grupo do MySQL requer pelo menos 3 nós em um cluster para tolerância a falhas. É por isso que temos que adicionar o terceiro nó como mostrado a seguir.
Adicione o último nó, db3 e aceite o método de recuperação padrão, "Clone" semelhante ao db2:
MySQL|db1:3306 ssl|JS> cluster.addInstance('[email protected]:3306');
A captura de tela a seguir mostra o progresso da inicialização do db3 após executarmos o comando acima. A operação de sincronização é realizada automaticamente pelo MySQL:
Verifique o status do cluster e do db3:
MySQL|db1:3306 ssl|JS> cluster.status()
{
"clusterName": "my_innodb_cluster",
"defaultReplicaSet": {
"name": "default",
"primary": "db1:3306",
"ssl": "REQUIRED",
"status": "OK",
"statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
"topology": {
"db1:3306": {
"address": "db1:3306",
"mode": "R/W",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.18"
},
"db2:3306": {
"address": "db2:3306",
"mode": "R/O",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.18"
},
"db3:3306": {
"address": "db3:3306",
"mode": "R/O",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.18"
}
},
"topologyMode": "Single-Primary"
},
"groupInformationSourceMember": "db1:3306"
}
Agora o cluster parece bom, onde o status é OK e o cluster pode tolerar até um nó com falha por vez. O nó primário é db1 onde mostra "primary":"db1:3306" e "mode":"R/W", enquanto outros nós estão no estado "R/O". Se você verificar os valores read_only e super_read_only nos nós RO, ambos serão exibidos como verdadeiros.
Nossa implantação do MySQL Group Replication agora está completa e sincronizada.
Implantando o roteador
No servidor de aplicativos em que vamos executar nosso aplicativo, verifique se o mapeamento do host está correto:
$ vim /etc/hosts
192.168.10.40 router apps
192.168.10.41 db1 db1.local
192.168.10.42 db2 db2.local
192.168.10.43 db3 db3.local
127.0.0.1 localhost localhost.localdomain
Pare e desative o AppArmor:
$ service apparmor stop
$ service apparmor teardown
$ systemctl disable apparmor
Em seguida, instale o pacote do repositório MySQL, semelhante ao que fizemos ao realizar a instalação do banco de dados:
$ wget https://repo.mysql.com/apt/ubuntu/pool/mysql-apt-config/m/mysql-apt-config/mysql-apt-config_0.8.14-1_all.deb
$ dpkg -i mysql-apt-config_0.8.14-1_all.deb
Adicionar chave GPG:
$ apt-key adv --recv-keys --keyserver ha.pool.sks-keyservers.net 5072E1F5
Atualize a lista de repositórios:
$ apt-get update
Instale o roteador e o cliente MySQL:
$ apt-get -y install mysql-router mysql-client
O MySQL Router agora está instalado em /usr/bin/mysqlrouter. O roteador MySQL fornece um sinalizador de bootstrap para configurar automaticamente a operação do roteador com um cluster MySQL InnoDB. O que precisamos fazer é especificar a string URI para um dos nós do banco de dados como o usuário administrador do cluster InnoDB (clusteradmin).
Para simplificar a configuração, executaremos o processo mysqlrouter como usuário root:
$ mysqlrouter --bootstrap [email protected]:3306 --directory myrouter --user=root
Aqui está o que devemos obter depois de especificar a senha para o usuário clusteradmin:
O comando bootstrap nos ajudará a gerar o arquivo de configuração do roteador em /root/myrouter/mysqlrouter.conf. Agora podemos iniciar o daemon mysqlrouter com o seguinte comando do diretório atual:
$ myrouter/start.sh
Verifique se as portas previstas estão escutando corretamente:
$ netstat -tulpn | grep mysql
tcp 0 0 0.0.0.0:6446 0.0.0.0:* LISTEN 14726/mysqlrouter
tcp 0 0 0.0.0.0:6447 0.0.0.0:* LISTEN 14726/mysqlrouter
tcp 0 0 0.0.0.0:64470 0.0.0.0:* LISTEN 14726/mysqlrouter
tcp 0 0 0.0.0.0:64460 0.0.0.0:* LISTEN 14726/mysqlrouter
Agora nosso aplicativo pode usar a porta 6446 para leitura/gravação e 6447 para conexões MySQL somente leitura.
Conectando-se ao cluster
Vamos criar um usuário de banco de dados no nó mestre. No db1, conecte-se ao servidor MySQL via shell MySQL:
$ mysqlsh [email protected]:3306
Mude do modo Javascript para o modo SQL:
MySQL|localhost:3306 ssl|JS> \sql
Switching to SQL mode... Commands end with ;
Crie um banco de dados:
MySQL|localhost:3306 ssl|SQL> CREATE DATABASE sbtest;
Crie um usuário de banco de dados:
MySQL|localhost:3306 ssl|SQL> CREATE USER [email protected]'%' IDENTIFIED BY 'password';
Conceda o usuário ao banco de dados:
MySQL|localhost:3306 ssl|SQL> GRANT ALL PRIVILEGES ON sbtest.* TO [email protected]'%';
Agora nosso banco de dados e usuário está pronto. Vamos instalar o sysbench para gerar alguns dados de teste. No servidor de aplicativos, faça:
$ apt -y install sysbench mysql-client
Agora podemos testar no servidor de aplicativos para conectar ao servidor MySQL via roteador MySQL. Para conexão de gravação, conecte-se à porta 6446 do host do roteador:
$ mysql -usbtest -p -h192.168.10.40 -P6446 -e 'select user(), @@hostname, @@read_only, @@super_read_only'
+---------------+------------+-------------+-------------------+
| user() | @@hostname | @@read_only | @@super_read_only |
+---------------+------------+-------------+-------------------+
| [email protected] | db1 | 0 | 0 |
+---------------+------------+-------------+-------------------+
Para conexão somente leitura, conecte-se à porta 6447 do host do roteador:
$ mysql -usbtest -p -h192.168.10.40 -P6447 -e 'select user(), @@hostname, @@read_only, @@super_read_only'
+---------------+------------+-------------+-------------------+
| user() | @@hostname | @@read_only | @@super_read_only |
+---------------+------------+-------------+-------------------+
| [email protected] | db3 | 1 | 1 |
+---------------+------------+-------------+-------------------+
Parece bom. Agora podemos gerar alguns dados de teste com o sysbench. No servidor de aplicativos, gere 20 tabelas com 100.000 linhas por tabela conectando-se à porta 6446 do servidor de aplicativos:
$ sysbench \
/usr/share/sysbench/oltp_common.lua \
--db-driver=mysql \
--mysql-user=sbtest \
--mysql-db=sbtest \
--mysql-password=password \
--mysql-port=6446 \
--mysql-host=192.168.10.40 \
--tables=20 \
--table-size=100000 \
prepare
Para realizar um teste simples de leitura e gravação na porta 6446 por 300 segundos, execute:
$ sysbench \
/usr/share/sysbench/oltp_read_write.lua \
--report-interval=2 \
--threads=8 \
--time=300 \
--db-driver=mysql \
--mysql-host=192.168.10.40 \
--mysql-port=6446 \
--mysql-user=sbtest \
--mysql-db=sbtest \
--mysql-password=password \
--tables=20 \
--table-size=100000 \
run
Para cargas de trabalho somente leitura, podemos enviar a conexão MySQL para a porta 6447:
$ sysbench \
/usr/share/sysbench/oltp_read_only.lua \
--report-interval=2 \
--threads=1 \
--time=300 \
--db-driver=mysql \
--mysql-host=192.168.10.40 \
--mysql-port=6447 \
--mysql-user=sbtest \
--mysql-db=sbtest \
--mysql-password=password \
--tables=20 \
--table-size=100000 \
run
Conclusão
É isso. Nossa configuração do MySQL InnoDB Cluster agora está completa com todos os seus componentes em execução e testados. Na segunda parte, veremos as operações de gerenciamento, monitoramento e dimensionamento do cluster, bem como soluções para vários problemas comuns ao lidar com o MySQL InnoDB Cluster. Fique atento!