Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Escalonamento automático com Amazon Aurora Serverless

O Amazon Aurora Serverless fornece um banco de dados relacional sob demanda, autoescalável e altamente disponível, que cobra apenas quando está em uso. Ele fornece uma opção relativamente simples e econômica para cargas de trabalho pouco frequentes, intermitentes ou imprevisíveis. O que torna isso possível é que ele é inicializado automaticamente, dimensiona a capacidade de computação para corresponder ao uso do seu aplicativo e, em seguida, é desligado quando não é mais necessário.

O diagrama a seguir mostra a arquitetura de alto nível do Aurora Serverless.

Com o Aurora Serverless, você obtém um endpoint (em oposição a dois endpoints para o banco de dados padrão provisionado do Aurora). Este é basicamente um registro DNS que consiste em uma frota de proxies que fica no topo da instância do banco de dados. De um ponto de servidor MySQL, significa que as conexões estão sempre vindo da frota de proxy.

Aurora Serverless Auto Scaling

No momento, o Aurora Serverless está disponível apenas para MySQL 5.6. Basicamente, você precisa definir a unidade de capacidade mínima e máxima para o cluster de banco de dados. Cada unidade de capacidade é equivalente a uma configuração específica de computação e memória. O Aurora Serverless reduz os recursos do cluster de banco de dados quando sua carga de trabalho está abaixo desses limites. O Aurora Serverless pode reduzir a capacidade até o mínimo ou aumentar a capacidade até a unidade de capacidade máxima.

O cluster será dimensionado automaticamente se uma das seguintes condições for atendida:

  • A utilização da CPU está acima de 70% OU
  • Mais de 90% das conexões estão sendo usadas

O cluster será reduzido automaticamente se ambas as condições a seguir forem atendidas:

  • A utilização da CPU cai abaixo de 30% E
  • Menos de 40% das conexões estão sendo usadas.

Algumas coisas notáveis ​​sobre o fluxo de dimensionamento automático do Aurora:

  • Ele só aumenta quando detecta problemas de desempenho que podem ser resolvidos por aumento.
  • Após a ampliação, o período de espera para a redução é de 15 minutos.
  • Após a redução, o período de espera para a próxima redução é de 310 segundos.
  • Ele é dimensionado para capacidade zero quando não há conexões por um período de 5 minutos.

Por padrão, o Aurora Serverless executa o dimensionamento automático sem interrupções, sem interromper nenhuma conexão de banco de dados ativa com o servidor. Ele é capaz de determinar um ponto de dimensionamento (um ponto no tempo em que o banco de dados pode iniciar com segurança a operação de dimensionamento). Sob as seguintes condições, no entanto, o Aurora Serverless pode não encontrar um ponto de escalabilidade:
  • Consultas ou transações de longa duração estão em andamento.
  • Tabelas temporárias ou bloqueios de tabela estão em uso.

Se um dos casos acima ocorrer, o Aurora Serverless continua tentando encontrar um ponto de dimensionamento para que possa iniciar a operação de dimensionamento (a menos que "Force Scaling" esteja ativado). Ele faz isso enquanto determina que o cluster de banco de dados deve ser dimensionado.

Observando o comportamento do Aurora Auto Scaling

Observe que no Aurora Serverless, apenas um pequeno número de parâmetros pode ser modificado e max_connections não é um deles. Para todos os outros parâmetros de configuração, os clusters do Aurora MySQL Serverless usam os valores padrão. Para max_connections, ele é controlado dinamicamente pelo Aurora Serverless usando a seguinte fórmula:

max_connections =GREATEST({log(DBInstanceClassMemory/805306368)*45},{log(DBInstanceClassMemory/8187281408)*1000})

Onde, log é log2 (log base-2) e "DBInstanceClassMemory" é o número de bytes de memória alocados para a classe de instância de banco de dados associada à instância de banco de dados atual, menos a memória usada pelos processos do Amazon RDS que gerenciam a instância. É muito difícil predeterminar o valor que o Aurora usará, portanto, é bom fazer alguns testes para entender como esse valor é dimensionado de acordo.

Aqui está nosso resumo de implantação do Aurora Serverless para este teste:

Para este exemplo, selecionei um mínimo de 1 unidade de capacidade Aurora, que é igual a 2 GB de RAM até a unidade de capacidade máxima de 256 com 488 GB de RAM.

Os testes foram realizados no sysbench, simplesmente enviando várias threads até atingir o limite de conexões do banco de dados MySQL. Nossa primeira tentativa de enviar 128 conexões de banco de dados simultâneas de uma só vez teve uma falha direta:

$ sysbench \
/usr/share/sysbench/oltp_read_write.lua \
--report-interval=2 \
--threads=128 \
--delete_inserts=5 \
--time=360 \
--max-requests=0 \
--db-driver=mysql \
--db-ps-mode=disable \
--mysql-host=${_HOST} \
--mysql-user=sbtest \
--mysql-db=sbtest \
--mysql-password=password \
--tables=20 \
--table-size=100000 \
run

O comando acima retornou imediatamente o erro 'Muitas conexões':

FATAL: unable to connect to MySQL server on host 'aurora-sysbench.cluster-cdw9q2wnb00s.ap-southeast-1.rds.amazonaws.com', port 3306, aborting...
FATAL: error 1040: Too many connections

Ao analisar as configurações de max_connection, obtivemos o seguinte:

mysql> SELECT @@hostname, @@max_connections;
+----------------+-------------------+
| @@hostname     | @@max_connections |
+----------------+-------------------+
| ip-10-2-56-105 |                90 |
+----------------+-------------------+

Acontece que o valor inicial de max_connections para nossa instância do Aurora com uma capacidade de banco de dados (2 GB de RAM) é 90. Na verdade, esse valor é muito menor do que o previsto se calculado usando a fórmula fornecida para estimar o valor de max_connections:

mysql> SELECT GREATEST({log2(2147483648/805306368)*45},{log2(2147483648/8187281408)*1000});
+------------------------------------------------------------------------------+
| GREATEST({log2(2147483648/805306368)*45},{log2(2147483648/8187281408)*1000}) |
+------------------------------------------------------------------------------+
|                                                                     262.2951 |
+------------------------------------------------------------------------------+

Isso significa simplesmente que DBInstanceClassMemory não é igual à memória real da instância do Aurora. Deve ser bem mais baixo. De acordo com este segmento de discussão, o valor da variável é ajustado para levar em conta a memória já em uso para serviços do SO e daemon de gerenciamento RDS.

No entanto, alterar o valor padrão de max_connections para algo mais alto também não nos ajudará, pois esse valor é controlado dinamicamente pelo cluster do Aurora Serverless. Assim, tivemos que reduzir o valor dos threads iniciais do sysbench para 84 porque os threads internos do Aurora já reservavam cerca de 4 a 5 conexões via 'rdsadmin'@'localhost'. Além disso, também precisamos de uma conexão extra para fins de gerenciamento e monitoramento.

Então, executamos o seguinte comando (com --threads=84):

$ sysbench \
/usr/share/sysbench/oltp_read_write.lua \
--report-interval=2 \
--threads=84 \
--delete_inserts=5 \
--time=600 \
--max-requests=0 \
--db-driver=mysql \
--db-ps-mode=disable \
--mysql-host=${_HOST} \
--mysql-user=sbtest \
--mysql-db=sbtest \
--mysql-password=password \
--tables=20 \
--table-size=100000 \
run

Depois que o teste acima foi concluído em 10 minutos (--time=600), executamos o mesmo comando novamente e, neste momento, algumas das variáveis ​​e status notáveis ​​foram alterados conforme mostrado abaixo:

mysql> SELECT @@hostname AS hostname, @@max_connections AS max_connections, 
(SELECT VARIABLE_VALUE FROM global_status WHERE VARIABLE_NAME = 'THREADS_CONNECTED') AS threads_connected, 
(SELECT VARIABLE_VALUE FROM global_status WHERE VARIABLE_NAME = 'UPTIME') AS uptime;
+--------------+-----------------+-------------------+--------+
| hostname     | max_connections | threads_connected | uptime |
+--------------+-----------------+-------------------+--------+
| ip-10-2-34-7 |             180 | 179               | 157    |
+--------------+-----------------+-------------------+--------+

Observe que max_connections agora dobrou para 180, com um nome de host diferente e um pequeno tempo de atividade como se o servidor estivesse apenas começando. Do ponto de vista do aplicativo, parece que outra "instância de banco de dados maior" assumiu o endpoint e configurou com uma variável max_connections diferente. Olhando para o evento Aurora, aconteceu o seguinte:

Wed, 04 Sep 2019 08:50:56 GMT The DB cluster has scaled from 1 capacity unit to 2 capacity units.

Então, acionamos o mesmo comando sysbench, criando outras 84 conexões com o endpoint do banco de dados. Após a conclusão do teste de estresse gerado, o servidor dimensiona automaticamente a capacidade de até 4 DB, conforme mostrado abaixo:

mysql> SELECT @@hostname AS hostname, @@max_connections AS max_connections, 
(SELECT VARIABLE_VALUE FROM global_status WHERE VARIABLE_NAME = 'THREADS_CONNECTED') AS threads_connected,
(SELECT VARIABLE_VALUE FROM global_status WHERE VARIABLE_NAME = 'UPTIME') AS uptime;
+---------------+-----------------+-------------------+--------+
| hostname      | max_connections | threads_connected | uptime |
+---------------+-----------------+-------------------+--------+
| ip-10-2-12-75 |             270 | 6                 | 300    |
+---------------+-----------------+-------------------+--------+

Você pode dizer olhando para o nome de host diferente, max_connection e valor de tempo de atividade se comparado ao anterior. Outras instâncias maiores "assumiram" o papel da instância anterior, onde a capacidade do banco de dados era igual a 2. O ponto de escala real é quando a carga do servidor estava caindo e quase atingindo o chão. Em nosso teste, se mantivéssemos a conexão completa e a carga do banco de dados consistentemente alta, o dimensionamento automático não ocorreria.

Ao observar as duas capturas de tela abaixo, podemos dizer que o dimensionamento só acontece quando nosso Sysbench conclui seu teste de estresse por 600 segundos, porque esse é o ponto mais seguro para executar o dimensionamento automático.
Capacidade de banco de dados sem servidor   Utilização da CPU Utilização da CPU

Ao analisar os eventos do Aurora, ocorreram os seguintes eventos:

Wed, 04 Sep 2019 16:25:00 GMT Scaling DB cluster from 4 capacity units to 2 capacity units for this reason: Autoscaling.
Wed, 04 Sep 2019 16:25:05 GMT The DB cluster has scaled from 4 capacity units to 2 capacity units.

Finalmente, geramos muito mais conexões até quase 270 e esperamos até terminar, para chegar à capacidade de 8 DB:

mysql> SELECT @@hostname as hostname, @@max_connections AS max_connections, 
(SELECT VARIABLE_VALUE FROM global_status WHERE VARIABLE_NAME = 'THREADS_CONNECTED') AS threads_connected,
(SELECT VARIABLE_VALUE FROM global_status WHERE VARIABLE_NAME = 'UPTIME') AS uptime;
+---------------+-----------------+-------------------+--------+
| hostname      | max_connections | threads_connected | uptime |
+---------------+-----------------+-------------------+--------+
| ip-10-2-72-12 |            1000 | 144               | 230    |
+---------------+-----------------+-------------------+--------+

Na instância de 8 unidades de capacidade, o valor de MySQL max_connections agora é 1000. Repetimos etapas semelhantes maximizando as conexões de banco de dados e até o limite de 256 unidades de capacidade. A tabela a seguir resume a unidade de capacidade geral do banco de dados versus o valor max_connections em nossos testes até a capacidade máxima do banco de dados:

Escalonamento forçado

Como mencionado acima, o Aurora Serverless só executará o dimensionamento automático quando for seguro fazê-lo. No entanto, o usuário tem a opção de forçar o dimensionamento da capacidade do banco de dados a acontecer imediatamente marcando a caixa de seleção Forçar dimensionamento na opção 'Configuração de dimensionamento adicional':

Quando o dimensionamento forçado está ativado, o dimensionamento ocorre assim que o tempo limite é atingido atingido que é de 300 segundos. Esse comportamento pode causar interrupção do banco de dados de seu aplicativo onde as conexões ativas com o banco de dados podem ser descartadas. Observamos o seguinte erro ao forçar o dimensionamento automático após atingir o tempo limite:

FATAL: mysql_drv_query() returned error 1105 (The last transaction was aborted due to an unknown error. Please retry.) for query 'SELECT c FROM sbtest19 WHERE id=52824'
FATAL: `thread_run' function failed: /usr/share/sysbench/oltp_common.lua:419: SQL error, errno = 1105, state = 'HY000': The last transaction was aborted due to an unknown error. Please retry.

O acima significa simplesmente que, em vez de encontrar o momento certo para escalar verticalmente, o Aurora Serverless força a substituição da instância a ocorrer imediatamente após atingir seu tempo limite, o que faz com que as transações sejam anuladas e revertidas. Tentar novamente a consulta abortada pela segunda vez provavelmente resolverá o problema. Essa configuração pode ser usada se seu aplicativo for resiliente a quedas de conexão.

Resumo


O escalonamento automático do Amazon Aurora Serverless é uma solução de escalonamento vertical, em que uma instância mais poderosa assume o controle de uma instância inferior, utilizando a tecnologia de armazenamento compartilhado do Aurora com eficiência. Por padrão, a operação de escalonamento automático é realizada de forma integrada, por meio do qual o Aurora encontra um ponto de escalonamento seguro para realizar a alternância de instâncias. Um tem a opção de forçar o dimensionamento automático com riscos de queda de conexões de banco de dados ativas.