MariaDB
 sql >> Base de Dados >  >> RDS >> MariaDB

Como executar e configurar o ProxySQL 2.0 para MySQL Galera Cluster no Docker


ProxySQL é um proxy SQL inteligente e de alto desempenho que suporta MySQL, MariaDB e ClickHouse. Recentemente, o ProxySQL 2.0 tornou-se GA e vem com novos recursos interessantes, como leituras consistentes de GTID, SSL de front-end, Galera e suporte nativo de replicação de grupo MySQL.

É relativamente fácil executar o ProxySQL como contêiner do Docker. Já escrevemos anteriormente sobre como executar o ProxySQL no Kubernetes como um contêiner auxiliar ou como um serviço do Kubernetes, que é baseado no ProxySQL 1.x. Nesta postagem do blog, usaremos a nova versão ProxySQL 2.x que usa uma abordagem diferente para a configuração do Galera Cluster.

Imagem do Docker ProxySQL 2.x


Lançamos um novo contêiner de imagem ProxySQL 2.0 Docker e está disponível no Docker Hub. O README fornece vários exemplos de configuração particularmente para Galera e MySQL Replication, pré e pós v2.x. As linhas de configuração podem ser definidas em um arquivo de texto e mapeadas no caminho do contêiner em /etc/proxysql.cnf para serem carregadas no serviço ProxySQL.

A tag "latest" da imagem ainda aponta para 1.x até que o ProxySQL 2.0 se torne oficialmente GA (ainda não vimos nenhum blog/artigo de lançamento oficial da equipe do ProxySQL). O que significa que, sempre que você instalar a imagem ProxySQL usando a tag mais recente do Váriosnines, você ainda obterá a versão 1.x com ela. Observe que as novas configurações de exemplo também habilitam as estatísticas da Web do ProxySQL (introduzidas na versão 1.4.4, mas ainda na versão beta) - um painel simples que resume a configuração geral e o status do próprio ProxySQL.

Suporte ProxySQL 2.x para Galera Cluster


Vamos falar mais detalhadamente sobre o suporte nativo do Galera Cluster. A nova tabela mysql_galera_hostgroups consiste nos seguintes campos:
  • writer_hostgroup : ID do hostgroup que conterá todos os membros que são escritores (read_only=0).
  • backup_writer_hostgroup : Se o cluster estiver sendo executado no modo multigravador (ou seja, houver vários nós com read_only=0) e max_writers estiver definido como um número menor que o número total de nós, os nós adicionais serão movidos para este grupo de hosts do gravador de backup.
  • reader_hostgroup : ID do hostgroup que conterá todos os membros que são leitores (ou seja, nós que têm read_only=1)
  • offline_hostgroup : Quando o monitoramento do ProxySQL determina que um host está OFFLINE, o host será movido para o offline_hostgroup.
  • ativo : um valor booleano (0 ou 1) para ativar um hostgroup
  • max_writers : Controla o número máximo de nós permitidos no grupo de hosts do gravador, conforme mencionado anteriormente, nós adicionais serão movidos para o backup_writer_hostgroup.
  • writer_is_also_reader : Quando 1, um nó no writer_hostgroup também será colocado no reader_hostgroup para que seja usado para leituras. Quando definido como 2, os nós do backup_writer_hostgroup serão colocados no reader_hostgroup, em vez dos nós no writer_hostgroup.
  • max_transactions_behind : determina o número máximo de conjuntos de gravação que um nó no cluster pode ter enfileirado antes que o nó seja SHUNNED para evitar leituras obsoletas (isso é determinado consultando a variável wsrep_local_recv_queue Galera).
  • comentário : Campo de texto que pode ser usado para qualquer finalidade definida pelo usuário

Aqui está um exemplo de configuração para mysql_galera_hostgroups em formato de tabela:
Admin> select * from mysql_galera_hostgroups\G
*************************** 1. row ***************************
       writer_hostgroup: 10
backup_writer_hostgroup: 20
       reader_hostgroup: 30
      offline_hostgroup: 9999
                 active: 1
            max_writers: 1
  writer_is_also_reader: 2
max_transactions_behind: 20
                comment: 

O ProxySQL realiza verificações de integridade do Galera monitorando o seguinte status/variável do MySQL:
  • somente leitura - Se ON, o ProxySQL agrupará o host definido em reader_hostgroup, a menos que writer_is_also_reader seja 1.
  • wsrep_desync - Se ATIVADO, o ProxySQL marcará o nó como indisponível, movendo-o para offline_hostgroup.
  • wsrep_reject_queries - Se esta variável estiver ON, o ProxySQL marcará o nó como indisponível, movendo-o para offline_hostgroup (útil em determinadas situações de manutenção).
  • wsrep_sst_donor_rejects_queries - Se esta variável estiver ATIVA, o ProxySQL marcará o nó como indisponível enquanto o nó Galera estiver servindo como doador SST, movendo-o para o offline_hostgroup.
  • wsrep_local_state - Se esse status retornar diferente de 4 (4 significa sincronizado), o ProxySQL marcará o nó como indisponível e o moverá para offline_hostgroup.
  • wsrep_local_recv_queue - Se este status for maior que max_transactions_behind, o nó será evitado.
  • wsrep_cluster_status - Se esse status retornar diferente de Primário, o ProxySQL marcará o nó como indisponível e o moverá para offline_hostgroup.

Dito isto, combinando esses novos parâmetros em mysql_galera_hostgroups junto com mysql_query_rules, o ProxySQL 2.x tem a flexibilidade de se encaixar em muito mais casos de uso do Galera. Por exemplo, pode-se ter um hostgroups de um único gravador, vários gravadores e vários leitores definidos como o grupo de hosts de destino de uma regra de consulta, com a capacidade de limitar o número de gravadores e um controle mais preciso sobre o comportamento de leituras obsoletas.

Compare isso com o ProxySQL 1.x, onde o usuário tinha que definir explicitamente um agendador para chamar um script externo para realizar as verificações de integridade de back-end e atualizar o estado dos servidores de banco de dados. Isso requer alguma personalização para o script (o usuário precisa atualizar o usuário/senha/porta do administrador do ProxySQL), além de depender de uma ferramenta adicional (cliente MySQL) para se conectar à interface de administração do ProxySQL.

Aqui está um exemplo de configuração do agendador de script de verificação de integridade Galera em formato de tabela para ProxySQL 1.x:
Admin> select * from scheduler\G
*************************** 1. row ***************************
         id: 1
     active: 1
interval_ms: 2000
   filename: /usr/share/proxysql/tools/proxysql_galera_checker.sh
       arg1: 10
       arg2: 20
       arg3: 1
       arg4: 1
       arg5: /var/lib/proxysql/proxysql_galera_checker.log
    comment:

Além disso, como o thread do agendador do ProxySQL executa qualquer script de forma independente, existem muitas versões de scripts de verificação de integridade disponíveis. Todas as instâncias do ProxySQL implantadas pelo ClusterControl usam o script padrão fornecido pelo pacote do instalador do ProxySQL.

No ProxySQL 2.x, as variáveis ​​max_writers e writer_is_also_reader podem determinar como o ProxySQL agrupa dinamicamente os servidores MySQL de backend e afetará diretamente a distribuição da conexão e o roteamento de consultas. Por exemplo, considere os seguintes servidores de back-end MySQL:
Admin> select hostgroup_id, hostname, status, weight from mysql_servers;
+--------------+--------------+--------+--------+
| hostgroup_id | hostname     | status | weight |
+--------------+--------------+--------+--------+
| 10           | DB1          | ONLINE | 1      |
| 10           | DB2          | ONLINE | 1      |
| 10           | DB3          | ONLINE | 1      |
+--------------+--------------+--------+--------+

Juntamente com a seguinte definição de hostgroups Galera:
Admin> select * from mysql_galera_hostgroups\G
*************************** 1. row ***************************
       writer_hostgroup: 10
backup_writer_hostgroup: 20
       reader_hostgroup: 30
      offline_hostgroup: 9999
                 active: 1
            max_writers: 1
  writer_is_also_reader: 2
max_transactions_behind: 20
                comment: 

Considerando que todos os hosts estão funcionando, o ProxySQL provavelmente agrupará os hosts conforme abaixo:

Vamos vê-los um por um:
Configuração Descrição
writer_is_also_reader=0
  • Agrupa os hosts em 2 grupos de hosts (writer e backup_writer).
  • O Writer faz parte do backup_writer.
  • Como o escritor não é um leitor, nada no hostgroup 30 (leitor) porque nenhum dos hosts está configurado com read_only=1. Não é uma prática comum no Galera habilitar o sinalizador somente leitura.
writer_is_also_reader=1
  • Agrupa os hosts em 3 grupos de hosts (gravador, gravador de backup e leitor).
  • A variável read_only=0 no Galera não tem efeito, portanto, o escritor também está no hostgroup 30 (leitor)
  • O Writer não faz parte do backup_writer.
writer_is_also_reader=2
  • Semelhante ao writer_is_also_reader=1, no entanto, o writer faz parte do backup_writer.

Com essa configuração, é possível ter várias opções de destino do grupo de hosts para atender a cargas de trabalho específicas. Gravações "Hotspot" podem ser configuradas para ir para apenas um servidor para reduzir conflitos de vários mestres, gravações não conflitantes podem ser distribuídas igualmente nos outros mestres, a maioria das leituras pode ser distribuída uniformemente em todos os servidores MySQL ou não gravadores, leituras críticas podem ser encaminhados para os servidores mais atualizados e as leituras analíticas podem ser encaminhadas para uma réplica escrava.

Implantação do ProxySQL para o Galera Cluster


Neste exemplo, suponha que já tenhamos um Galera Cluster de três nós implantado pelo ClusterControl, conforme mostrado no diagrama a seguir:

Nossos aplicativos Wordpress são executados no Docker enquanto o banco de dados Wordpress é hospedado em nosso Galera Cluster executado em servidores bare-metal. Decidimos executar um contêiner ProxySQL junto com nossos contêineres Wordpress para ter um melhor controle sobre o roteamento de consultas de banco de dados Wordpress e utilizar totalmente nossa infraestrutura de cluster de banco de dados. Como a proporção de leitura e gravação é de cerca de 80% a 20%, queremos configurar o ProxySQL para:
  • Encaminha todas as gravações para um nó Galera (menos conflito, foco na gravação)
  • Balance todas as leituras para os outros dois nós Galera (melhor distribuição para a maior parte da carga de trabalho)

Primeiramente, crie um arquivo de configuração do ProxySQL dentro do host do Docker para que possamos mapeá-lo em nosso contêiner:
$ mkdir /root/proxysql-docker
$ vim /root/proxysql-docker/proxysql.cnf

Em seguida, copie as seguintes linhas (explicaremos as linhas de configuração mais abaixo):
datadir="/var/lib/proxysql"

admin_variables=
{
    admin_credentials="admin:admin"
    mysql_ifaces="0.0.0.0:6032"
    refresh_interval=2000
    web_enabled=true
    web_port=6080
    stats_credentials="stats:admin"
}

mysql_variables=
{
    threads=4
    max_connections=2048
    default_query_delay=0
    default_query_timeout=36000000
    have_compress=true
    poll_timeout=2000
    interfaces="0.0.0.0:6033;/tmp/proxysql.sock"
    default_schema="information_schema"
    stacksize=1048576
    server_version="5.1.30"
    connect_timeout_server=10000
    monitor_history=60000
    monitor_connect_interval=200000
    monitor_ping_interval=200000
    ping_interval_server_msec=10000
    ping_timeout_server=200
    commands_stats=true
    sessions_sort=true
    monitor_username="proxysql"
    monitor_password="proxysqlpassword"
    monitor_galera_healthcheck_interval=2000
    monitor_galera_healthcheck_timeout=800
}

mysql_galera_hostgroups =
(
    {
        writer_hostgroup=10
        backup_writer_hostgroup=20
        reader_hostgroup=30
        offline_hostgroup=9999
        max_writers=1
        writer_is_also_reader=1
        max_transactions_behind=30
        active=1
    }
)

mysql_servers =
(
    { address="db1.cluster.local" , port=3306 , hostgroup=10, max_connections=100 },
    { address="db2.cluster.local" , port=3306 , hostgroup=10, max_connections=100 },
    { address="db3.cluster.local" , port=3306 , hostgroup=10, max_connections=100 }
)

mysql_query_rules =
(
    {
        rule_id=100
        active=1
        match_pattern="^SELECT .* FOR UPDATE"
        destination_hostgroup=10
        apply=1
    },
    {
        rule_id=200
        active=1
        match_pattern="^SELECT .*"
        destination_hostgroup=30
        apply=1
    },
    {
        rule_id=300
        active=1
        match_pattern=".*"
        destination_hostgroup=10
        apply=1
    }
)

mysql_users =
(
    { username = "wordpress", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 },
    { username = "sbtest", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 }
)

Agora, vamos fazer uma visita a algumas das seções de configuração. Primeiramente, definimos a configuração dos hostgroups do Galera conforme abaixo:
mysql_galera_hostgroups =
(
    {
        writer_hostgroup=10
        backup_writer_hostgroup=20
        reader_hostgroup=30
        offline_hostgroup=9999
        max_writers=1
        writer_is_also_reader=1
        max_transactions_behind=30
        active=1
    }
)

Hostgroup 10 será o writer_hostgroup, hostgroup 20 para backup_writer e hostgroup 30 para leitor. Definimos max_writers como 1 para que possamos ter um hostgroup de gravador único para o hostgroup 10 para onde todas as gravações devem ser enviadas. Em seguida, definimos writer_is_also_reader como 1, o que tornará todos os nós do Galera também leitores, adequados para consultas que podem ser distribuídas igualmente para todos os nós. Hostgroup 9999 é reservado para offline_hostgroup se o ProxySQL detectar nós Galera não operacionais.

Em seguida, configuramos nossos servidores MySQL com padrão para hostgroup 10:
mysql_servers =
(
    { address="db1.cluster.local" , port=3306 , hostgroup=10, max_connections=100 },
    { address="db2.cluster.local" , port=3306 , hostgroup=10, max_connections=100 },
    { address="db3.cluster.local" , port=3306 , hostgroup=10, max_connections=100 }
)

Com as configurações acima, o ProxySQL irá "ver" nossos grupos de hosts conforme abaixo:

Em seguida, definimos o roteamento da consulta por meio de regras de consulta. Com base em nosso requisito, todas as leituras devem ser enviadas para todos os nós do Galera, exceto o gravador (hostgroup 20) e todo o resto é encaminhado para o hostgroup 10 para um único gravador:
mysql_query_rules =
(
    {
        rule_id=100
        active=1
        match_pattern="^SELECT .* FOR UPDATE"
        destination_hostgroup=10
        apply=1
    },
    {
        rule_id=200
        active=1
        match_pattern="^SELECT .*"
        destination_hostgroup=20
        apply=1
    },
    {
        rule_id=300
        active=1
        match_pattern=".*"
        destination_hostgroup=10
        apply=1
    }
)

Por fim, definimos os usuários do MySQL que serão passados ​​pelo ProxySQL:
mysql_users =
(
    { username = "wordpress", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 },
    { username = "sbtest", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 }
)

Definimos transaction_persistent como 0 para que todas as conexões provenientes desses usuários respeitem as regras de consulta para roteamento de leituras e gravações. Caso contrário, as conexões acabariam atingindo um grupo de hosts que anula o propósito de balanceamento de carga. Não se esqueça de criar esses usuários primeiro em todos os servidores MySQL. Para o usuário do ClusterControl, você pode usar o recurso Gerenciar -> Esquemas e Usuários para criar esses usuários.

Agora estamos prontos para iniciar nosso contêiner. Vamos mapear o arquivo de configuração do ProxySQL como montagem de ligação ao iniciar o contêiner ProxySQL. Assim, o comando de execução será:
$ docker run -d \
--name proxysql2 \
--hostname proxysql2 \
--publish 6033:6033 \
--publish 6032:6032 \
--publish 6080:6080 \
--restart=unless-stopped \
-v /root/proxysql/proxysql.cnf:/etc/proxysql.cnf \
severalnines/proxysql:2.0

Por fim, altere o banco de dados Wordpress apontando para a porta 6033 do contêiner ProxySQL, por exemplo:
$ docker run -d \
--name wordpress \
--publish 80:80 \
--restart=unless-stopped \
-e WORDPRESS_DB_HOST=proxysql2:6033 \
-e WORDPRESS_DB_USER=wordpress \
-e WORDPRESS_DB_HOST=passw0rd \
wordpress

Neste ponto, nossa arquitetura está mais ou menos assim:

Se você deseja que o contêiner ProxySQL seja persistente, mapeie /var/lib/proxysql/ para um volume do Docker ou uma montagem de ligação, por exemplo:
$ docker run -d \
--name proxysql2 \
--hostname proxysql2 \
--publish 6033:6033 \
--publish 6032:6032 \
--publish 6080:6080 \
--restart=unless-stopped \
-v /root/proxysql/proxysql.cnf:/etc/proxysql.cnf \
-v proxysql-volume:/var/lib/proxysql \
severalnines/proxysql:2.0

Tenha em mente que a execução com armazenamento persistente como o acima tornará nosso /root/proxysql/proxysql.cnf obsoleto na segunda reinicialização. Isso se deve à configuração multicamada do ProxySQL em que se /var/lib/proxysql/proxysql.db existir, o ProxySQL pulará as opções de carregamento do arquivo de configuração e carregará o que estiver no banco de dados SQLite (a menos que você inicie o serviço proxysql com --initial bandeira). Dito isso, o próximo gerenciamento de configuração do ProxySQL deve ser realizado via console de administração do ProxySQL na porta 6032, em vez de usar o arquivo de configuração.

Monitoramento


Log do processo ProxySQL por padrão logando no syslog e você pode visualizá-los usando o comando docker padrão:
$ docker ps
$ docker logs proxysql2

Para verificar o hostgroup atual, consulte a tabela runtime_mysql_servers:
$ docker exec -it proxysql2 mysql -uadmin -padmin -h127.0.0.1 -P6032 --prompt='Admin> '
Admin> select hostgroup_id,hostname,status from runtime_mysql_servers;
+--------------+--------------+--------+
| hostgroup_id | hostname     | status |
+--------------+--------------+--------+
| 10           | 192.168.0.21 | ONLINE |
| 30           | 192.168.0.21 | ONLINE |
| 30           | 192.168.0.22 | ONLINE |
| 30           | 192.168.0.23 | ONLINE |
| 20           | 192.168.0.22 | ONLINE |
| 20           | 192.168.0.23 | ONLINE |
+--------------+--------------+--------+

Se o gravador selecionado cair, ele será transferido para o offline_hostgroup (HID 9999):
Admin> select hostgroup_id,hostname,status from runtime_mysql_servers;
+--------------+--------------+--------+
| hostgroup_id | hostname     | status |
+--------------+--------------+--------+
| 10           | 192.168.0.22 | ONLINE |
| 9999         | 192.168.0.21 | ONLINE |
| 30           | 192.168.0.22 | ONLINE |
| 30           | 192.168.0.23 | ONLINE |
| 20           | 192.168.0.23 | ONLINE |
+--------------+--------------+--------+

As alterações de topologia acima podem ser ilustradas no diagrama a seguir:

Também ativamos a interface do usuário de estatísticas da web com admin-web_enabled=true. Para acessar a interface do usuário da web, basta acessar o host do Docker na porta 6080, por exemplo:http://192.168.0.200:8060 e você será solicitado com um pop-up de nome de usuário/senha. Insira as credenciais conforme definido em admin-stats_credentials e você deverá ver a seguinte página:

Ao monitorar a tabela de pool de conexão do MySQL, podemos obter uma visão geral da distribuição de conexão para todos os grupos de hosts:
Admin> select hostgroup, srv_host, status, ConnUsed, MaxConnUsed, Queries from stats.stats_mysql_connection_pool order by srv_host;
+-----------+--------------+--------+----------+-------------+---------+
| hostgroup | srv_host     | status | ConnUsed | MaxConnUsed | Queries |
+-----------+--------------+--------+----------+-------------+---------+
| 20        | 192.168.0.23 | ONLINE | 5        | 24          | 11458   |
| 30        | 192.168.0.23 | ONLINE | 0        | 0           | 0       |
| 20        | 192.168.0.22 | ONLINE | 2        | 24          | 11485   |
| 30        | 192.168.0.22 | ONLINE | 0        | 0           | 0       |
| 10        | 192.168.0.21 | ONLINE | 32       | 32          | 9746    |
| 30        | 192.168.0.21 | ONLINE | 0        | 0           | 0       |
+-----------+--------------+--------+----------+-------------+---------+

A saída acima mostra que o hostgroup 30 não processa nada porque nossas regras de consulta não têm esse hostgroup configurado como hostgroup de destino.

As estatísticas relacionadas aos nós Galera podem ser visualizadas na tabela mysql_server_galera_log:
Admin>  select * from mysql_server_galera_log order by time_start_us desc limit 3\G
*************************** 1. row ***************************
                       hostname: 192.168.0.23
                           port: 3306
                  time_start_us: 1552992553332489
                success_time_us: 2045
              primary_partition: YES
                      read_only: NO
         wsrep_local_recv_queue: 0
              wsrep_local_state: 4
                   wsrep_desync: NO
           wsrep_reject_queries: NO
wsrep_sst_donor_rejects_queries: NO
                          error: NULL
*************************** 2. row ***************************
                       hostname: 192.168.0.22
                           port: 3306
                  time_start_us: 1552992553329653
                success_time_us: 2799
              primary_partition: YES
                      read_only: NO
         wsrep_local_recv_queue: 0
              wsrep_local_state: 4
                   wsrep_desync: NO
           wsrep_reject_queries: NO
wsrep_sst_donor_rejects_queries: NO
                          error: NULL
*************************** 3. row ***************************
                       hostname: 192.168.0.21
                           port: 3306
                  time_start_us: 1552992553329013
                success_time_us: 2715
              primary_partition: YES
                      read_only: NO
         wsrep_local_recv_queue: 0
              wsrep_local_state: 4
                   wsrep_desync: NO
           wsrep_reject_queries: NO
wsrep_sst_donor_rejects_queries: NO
                          error: NULL

O conjunto de resultados retorna a variável/estado de status do MySQL relacionado para cada nó Galera para um carimbo de data/hora específico. Nesta configuração, configuramos a verificação de integridade do Galera para ser executada a cada 2 segundos (monitor_galera_healthcheck_interval=2000). Portanto, o tempo máximo de failover seria de cerca de 2 segundos se ocorrer uma alteração de topologia no cluster.

Referências

  • Suporte a ProxySQL Native Galera
  • Solução de HA e clustering:ProxySQL como roteador inteligente para Galera e replicação de grupo
  • Imagem do ProxySQL Docker por Variousnines
  • Como monitorar o ProxySQL com Prometheus e ClusterControl