O Moodle é uma plataforma muito popular para executar cursos online. Com a situação que vemos em 2020, o Moodle, juntamente com comunicadores como o Zoom, forma a espinha dorsal dos serviços que permitem o aprendizado on-line e a educação em casa. A demanda colocada nas plataformas Moodle aumentou significativamente em relação aos anos anteriores. Novas plataformas foram construídas, carga adicional foi colocada nas plataformas que, historicamente, atuavam apenas como uma ferramenta auxiliar e agora se destinam a impulsionar todo o esforço educacional. Como escalar o Moodle? Temos um blog sobre este tema. Como dimensionar o back-end do banco de dados para o Moodle? Bem, isso é outra história. Vamos dar uma olhada nisso, pois dimensionar bancos de dados não é a coisa mais fácil de fazer, especialmente se o Moodle adicionar seu próprio toque.
Como ponto de entrada, usaremos a arquitetura descrita em um de nossos posts anteriores. Cluster MariaDB com ProxySQL e Keepalived em cima das coisas.
Como você pode ver, temos um cluster MariaDB de três nós com ProxySQL que divide leituras seguras do restante do tráfego com base no usuário.
<?php // Moodle configuration file
unset($CFG);
global $CFG;
$CFG = new stdClass();
$CFG->dbtype = 'mysqli';
$CFG->dblibrary = 'native';
$CFG->dbhost = '192.168.1.222';
$CFG->dbname = 'moodle';
$CFG->dbuser = 'moodle';
$CFG->dbpass = 'pass';
$CFG->prefix = 'mdl_';
$CFG->dboptions = array (
'dbpersist' => 0,
'dbport' => 6033,
'dbsocket' => '',
'dbcollation' => 'utf8mb4_general_ci',
'readonly' => [
'instance' => [
'dbhost' => '192.168.1.222',
'dbport' => 6033,
'dbuser' => 'moodle_safereads',
'dbpass' => 'pass'
]
]
);
$CFG->wwwroot = 'http://192.168.1.200/moodle';
$CFG->dataroot = '/var/www/moodledata';
$CFG->admin = 'admin';
$CFG->directorypermissions = 0777;
require_once(__DIR__ . '/lib/setup.php');
// There is no php closing tag in this file,
// it is intentional because it prevents trailing whitespace problems!
Usuário, como mostrado acima, é definido no arquivo de configuração do Moodle. Isso nos permite enviar gravações e todas as instruções SELECT de forma automática e segura que exigem consistência de dados para o nó do gravador enquanto ainda enviamos alguns dos SELECTs para os nós restantes no MariaDB Cluster.
Vamos supor que essa configuração específica não seja suficiente para nós. Quais são as opções que temos? Temos dois elementos principais na configuração - MariaDB Cluster e ProxySQL. Vamos considerar os problemas de ambos os lados:
- O que pode ser feito se a instância ProxySQL não puder lidar com o tráfego?
- O que pode ser feito se o MariaDB Cluster não puder lidar com o tráfego?
Vamos começar com o primeiro cenário.
A instância ProxySQL está sobrecarregada
No ambiente atual, apenas uma instância do ProxySQL pode manipular o tráfego - aquela para a qual o IP virtual aponta. Isso nos deixa com uma instância ProxySQL que está agindo como standby - funcionando, mas não usada para nada. Se a instância ativa do ProxySQL estiver se aproximando da saturação da CPU, há algumas coisas que você pode querer fazer. Primeiro, obviamente, você pode dimensionar verticalmente - aumentar o tamanho de uma instância do ProxySQL pode ser a maneira mais fácil de permitir que ela lide com tráfego mais alto. Lembre-se de que o ProxySQL, por padrão, está configurado para usar 4 threads.
Se você quiser utilizar mais núcleos de CPU, este é o configuração que você precisa alterar também.
Como alternativa, você pode tentar dimensionar horizontalmente. Em vez de usar duas instâncias ProxySQL com VIP, você pode colocar ProxySQL com hosts Moodle. Então você deseja reconfigurar o Moodle para se conectar ao ProxySQL no host local, de preferência através do soquete Unix - é a maneira mais eficiente de se conectar ao ProxySQL. Não há muita configuração que usamos com o ProxySQL, portanto, usar várias instâncias do ProxySQL não deve adicionar muita sobrecarga. Se desejar, você sempre pode configurar o ProxySQL Cluster para ajudá-lo a manter as instâncias do ProxySQL sincronizadas em relação à configuração.
O cluster MariaDB está sobrecarregado
Agora estamos falando de um assunto mais sério. É claro que aumentar o tamanho das instâncias ajudará, como sempre. Por outro lado, a escala horizontal é um pouco limitada devido à limitação de “leituras seguras”. Claro, você pode adicionar mais nós ao cluster, mas pode usá-los apenas para leituras seguras. Até que ponto isso permite escalar horizontalmente, depende da carga de trabalho. Para carga de trabalho somente leitura pura (navegar pelo conteúdo, fóruns, etc), parece muito bom:
MySQL [(none)]> SELECT hostgroup, srv_host, srv_port, status, queries FROM stats_mysql_connection_pool WHERE hostgroup IN (20, 10) AND status='ONLINE';
+-----------+---------------+----------+--------+---------+
| hostgroup | srv_host | srv_port | status | Queries |
+-----------+---------------+----------+--------+---------+
| 20 | 192.168.1.204 | 3306 | ONLINE | 5683 |
| 20 | 192.168.1.205 | 3306 | ONLINE | 5543 |
| 10 | 192.168.1.206 | 3306 | ONLINE | 553 |
+-----------+---------------+----------+--------+---------+
3 rows in set (0.002 sec)
Esta é praticamente uma proporção de 1:20 - para uma consulta que atinge o escritor, temos 20 “leituras seguras” que podem ser distribuídas pelos nós restantes. Por outro lado, quando começamos a modificar os dados, a proporção muda rapidamente.
MySQL [(none)]> SELECT hostgroup, srv_host, srv_port, status, queries FROM stats_mysql_connection_pool WHERE hostgroup IN (20, 10) AND status='ONLINE';
+-----------+---------------+----------+--------+---------+
| hostgroup | srv_host | srv_port | status | Queries |
+-----------+---------------+----------+--------+---------+
| 20 | 192.168.1.204 | 3306 | ONLINE | 3117 |
| 20 | 192.168.1.205 | 3306 | ONLINE | 3010 |
| 10 | 192.168.1.206 | 3306 | ONLINE | 6807 |
+-----------+---------------+----------+--------+---------+
3 rows in set (0.003 sec)
Esta é uma saída depois de emitir várias notas, criar tópicos de fórum e adicionar algum conteúdo do curso. Como você pode ver, com essa proporção de consultas seguras/inseguras, o gravador será saturado antes dos leitores, portanto, dimensionar adicionando mais nós não é adequado.
O que pode ser feito a respeito? Existe uma configuração chamada “latência”. De acordo com o arquivo de configuração, ele determina quando é seguro ler a tabela após a gravação. Quando a escrita acontece, a tabela é marcada como modificada e pelo tempo de “latência” todos os SELECTs serão enviados para o nó do gravador. Uma vez que o tempo maior que a “latência” tenha passado, os SELECTs daquela tabela podem ser enviados novamente para os nós de leitura. Lembre-se de que, com o MariaDB Cluster, o tempo necessário para que o conjunto de gravação seja aplicado em todos os nós é normalmente muito baixo, contado em milissegundos. Isso nos permitiria definir a latência bem baixa no arquivo de configuração do Moodle, por exemplo, o valor como 0.1s (100 milissegundos) deve estar bem. Claro, se você tiver algum problema, você sempre pode aumentar esse valor ainda mais.
Outra opção para testar seria confiar puramente no MariaDB Cluster para dizer quando a leitura é segura e quando não é. Existe uma variável wsrep_sync_wait que pode ser configurada para forçar verificações de causalidade em vários padrões de acesso (leituras, atualizações, inserções, exclusões, substituições e comandos SHOW). Para nosso propósito, seria suficiente garantir que as leituras sejam executadas com a causalidade imposta, portanto, definiremos essa variável como '1'.
Faremos essa alteração em todos os nós do cluster MariaDB. Também precisaremos reconfigurar o ProxySQL para divisão de leitura/gravação com base nas regras de consulta, não apenas nos usuários, como fizemos anteriormente. Também removeremos o usuário ‘moodle_safereads’, pois não é mais necessário nesta configuração.
Configuramos três regras de consulta que distribuem o tráfego com base na consulta. SELECT … FOR UPDATE é enviado para o nó do gravador, todas as consultas SELECT são enviadas para os leitores e todo o resto (INSERT, DELETE, REPLACE, UPDATE, BEGIN, COMMIT e assim por diante) também é enviado para o nó do gravador.
Isso nos permite garantir que todas as leituras possam ser distribuídas entre os nós do leitor, permitindo assim uma escala horizontal através da adição de mais nós ao MariaDB Cluster.
Esperamos que com essas duas dicas você possa escalar seu backend de banco de dados Moodle muito mais fácil e em maior extensão