sql >> Base de Datos >  >> RDS >> MariaDB

Cómo ejecutar y configurar ProxySQL 2.0 para MySQL Galera Cluster en Docker

ProxySQL es un proxy SQL inteligente y de alto rendimiento que admite MySQL, MariaDB y ClickHouse. Recientemente, ProxySQL 2.0 se ha convertido en GA y viene con nuevas funciones interesantes, como lecturas consistentes de GTID, SSL de interfaz, Galera y soporte nativo de replicación de grupo MySQL.

Es relativamente fácil ejecutar ProxySQL como contenedor Docker. Anteriormente escribimos sobre cómo ejecutar ProxySQL en Kubernetes como un contenedor auxiliar o como un servicio de Kubernetes, que se basa en ProxySQL 1.x. En esta publicación de blog, vamos a utilizar la nueva versión ProxySQL 2.x, que utiliza un enfoque diferente para la configuración de Galera Cluster.

Imagen de Docker de ProxySQL 2.x

Hemos lanzado un nuevo contenedor de imágenes de ProxySQL 2.0 Docker y está disponible en Docker Hub. El README proporciona una serie de ejemplos de configuración en particular para Galera y MySQL Replication, antes y después de v2.x. Las líneas de configuración pueden definirse en un archivo de texto y asignarse a la ruta del contenedor en /etc/proxysql.cnf para cargarse en el servicio ProxySQL.

La etiqueta "más reciente" de la imagen todavía apunta a 1.x hasta que ProxySQL 2.0 se convierta oficialmente en GA (todavía no hemos visto ningún blog/artículo de publicación oficial del equipo de ProxySQL). Lo que significa que cada vez que instale una imagen de ProxySQL con la última etiqueta de Variousnines, seguirá obteniendo la versión 1.x con ella. Tenga en cuenta que las nuevas configuraciones de ejemplo también habilitan las estadísticas web de ProxySQL (introducidas en 1.4.4 pero aún en versión beta), un panel simple que resume la configuración general y el estado de ProxySQL.

Compatibilidad con ProxySQL 2.x para el clúster de Galera

Hablemos sobre el soporte nativo de Galera Cluster con más detalle. La nueva tabla mysql_galera_hostgroups consta de los siguientes campos:

  • writer_hostgroup : ID del grupo host que contendrá a todos los miembros que son escritores (read_only=0).
  • backup_writer_hostgroup : Si el clúster se ejecuta en modo de escritura múltiple (es decir, hay varios nodos con read_only=0) y max_writers se establece en un número menor que el número total de nodos, los nodos adicionales se mueven a este grupo de host de escritura de respaldo.
  • grupo_host_lectores : ID del grupo host que contendrá todos los miembros que son lectores (es decir, nodos que tienen read_only=1)
  • offline_hostgroup : Cuando la supervisión de ProxySQL determina que un host está SIN CONEXIÓN, el host se moverá a offline_hostgroup.
  • activo : un valor booleano (0 o 1) para activar un grupo de host
  • max_escritores : Controla la cantidad máxima de nodos permitidos en el grupo de host de escritor, como se mencionó anteriormente, los nodos adicionales se moverán a backup_writer_hostgroup.
  • escritor_es_también_lector : Cuando es 1, un nodo en el grupo host_escritor también se colocará en el grupo host_lector para que se use para lecturas. Cuando se establece en 2, los nodos de backup_writer_hostgroup se colocarán en reader_hostgroup, en lugar de los nodos en Writer_hostgroup.
  • max_transactions_behind : determina la cantidad máxima de conjuntos de escritura que un nodo en el clúster puede haber puesto en cola antes de que el nodo sea DESCONECTADO para evitar lecturas obsoletas (esto se determina consultando la variable wsrep_local_recv_queue Galera).
  • comentar : Campo de texto que se puede utilizar para cualquier propósito definido por el usuario

Aquí hay una configuración de ejemplo para mysql_galera_hostgroups en formato de tabla:

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: 

ProxySQL realiza verificaciones de salud de Galera al monitorear el siguiente estado/variable de MySQL:

  • solo lectura - Si está activado, ProxySQL agrupará el host definido en reader_hostgroup a menos que write_is_also_reader sea 1.
  • wsrep_desync - Si está activado, ProxySQL marcará el nodo como no disponible y lo moverá a offline_hostgroup.
  • wsrep_reject_queries - Si esta variable está activada, ProxySQL marcará el nodo como no disponible y lo moverá a offline_hostgroup (útil en ciertas situaciones de mantenimiento).
  • wsrep_sst_donor_rejects_queries - Si esta variable está activada, ProxySQL marcará el nodo como no disponible mientras el nodo Galera sirve como donante de SST, moviéndolo a offline_hostgroup.
  • wsrep_local_state - Si este estado no es 4 (4 significa sincronizado), ProxySQL marcará el nodo como no disponible y lo moverá a offline_hostgroup.
  • wsrep_local_recv_queue - Si este estado es mayor que max_transactions_behind, el nodo será rechazado.
  • wsrep_cluster_status - Si este estado no es el primario, ProxySQL marcará el nodo como no disponible y lo moverá a offline_hostgroup.

Habiendo dicho eso, al combinar estos nuevos parámetros en mysql_galera_hostgroups junto con mysql_query_rules, ProxySQL 2.x tiene la flexibilidad de adaptarse a muchos más casos de uso de Galera. Por ejemplo, se pueden tener grupos de host de un solo escritor, de varios escritores y de múltiples lectores definidos como el grupo de host de destino de una regla de consulta, con la capacidad de limitar la cantidad de escritores y un control más preciso sobre el comportamiento de las lecturas obsoletas.

Compare esto con ProxySQL 1.x, donde el usuario tenía que definir explícitamente un programador para llamar a un script externo para realizar las comprobaciones de estado del back-end y actualizar el estado de los servidores de la base de datos. Esto requiere cierta personalización de la secuencia de comandos (el usuario debe actualizar el usuario/contraseña/puerto de administrador de ProxySQL) además, dependía de una herramienta adicional (cliente MySQL) para conectarse a la interfaz de administración de ProxySQL.

Este es un ejemplo de configuración del programador de secuencias de comandos de comprobación de estado de Galera en formato de tabla 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:

Además, dado que el subproceso del programador ProxySQL ejecuta cualquier secuencia de comandos de forma independiente, existen muchas versiones de secuencias de comandos de verificación de estado disponibles. Todas las instancias de ProxySQL implementadas por ClusterControl utilizan el script predeterminado proporcionado por el paquete de instalación de ProxySQL.

En ProxySQL 2.x, las variables max_writers ywriter_is_also_reader pueden determinar cómo ProxySQL agrupa dinámicamente los servidores backend MySQL y afectará directamente la distribución de conexiones y el enrutamiento de consultas. Por ejemplo, considere los siguientes servidores back-end de 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      |
+--------------+--------------+--------+--------+

Junto con la siguiente definición de grupos de host de 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: 

Teniendo en cuenta que todos los hosts están en funcionamiento, lo más probable es que ProxySQL agrupe los hosts de la siguiente manera:

Veámoslos uno por uno:

Configuración Descripción
writer_is_also_reader=0
  • Agrupa los hosts en 2 grupos de hosts (escritor y backup_writer).
  • Writer es parte de backup_writer.
  • Dado que el escritor no es un lector, nada en el grupo de host 30 (lector) porque ninguno de los hosts está configurado con read_only=1. No es una práctica común en Galera habilitar el indicador de solo lectura.
escritor_es_también_lector=1
  • Agrupa los hosts en 3 grupos de hosts (escritor, backup_writer y lector).
  • La variable read_only=0 en Galera no tiene efecto, por lo que el escritor también está en el grupo de host 30 (lector)
  • Writer no es parte de backup_writer.
escritor_es_también_lector=2
  • Al igual que write_is_also_reader=1, sin embargo, el escritor es parte de backup_writer.

Con esta configuración, uno puede tener varias opciones para el destino del grupo de host para atender cargas de trabajo específicas. Las escrituras de "punto de acceso" se pueden configurar para que vayan a un solo servidor para reducir los conflictos entre varios maestros, las escrituras que no están en conflicto se pueden distribuir por igual en los otros maestros, la mayoría de las lecturas se pueden distribuir de manera uniforme en todos los servidores MySQL o no escritores, lecturas críticas se pueden reenviar a los servidores más actualizados y las lecturas analíticas se pueden reenviar a una réplica esclava.

Implementación de ProxySQL para el clúster de Galera

En este ejemplo, suponga que ya tenemos un Galera Cluster de tres nodos implementado por ClusterControl como se muestra en el siguiente diagrama:

Nuestras aplicaciones de Wordpress se ejecutan en Docker, mientras que la base de datos de Wordpress está alojada en nuestro Galera Cluster que se ejecuta en servidores bare-metal. Decidimos ejecutar un contenedor ProxySQL junto con nuestros contenedores de Wordpress para tener un mejor control sobre el enrutamiento de consultas de la base de datos de Wordpress y utilizar completamente nuestra infraestructura de clúster de base de datos. Dado que la proporción de lectura y escritura es de alrededor del 80 % al 20 %, queremos configurar ProxySQL para:

  • Reenviar todas las escrituras a un nodo de Galera (menos conflicto, concentrarse en escribir)
  • Equilibrar todas las lecturas a los otros dos nodos de Galera (mejor distribución para la mayor parte de la carga de trabajo)

En primer lugar, cree un archivo de configuración de ProxySQL dentro del host de Docker para que podamos asignarlo a nuestro contenedor:

$ mkdir /root/proxysql-docker
$ vim /root/proxysql-docker/proxysql.cnf

Luego, copie las siguientes líneas (explicaremos las líneas de configuración más abajo):

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 }
)

Ahora, hagamos una visita a algunas de las secciones más configurables. En primer lugar, definimos la configuración de los grupos de host de Galera de la siguiente manera:

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
    }
)

El grupo de host 10 será el grupo de host del escritor, el grupo de host 20 para el escritor de respaldo y el grupo de host 30 para el lector. Configuramos max_writers en 1 para que podamos tener un grupo de host de un solo escritor para el grupo de host 10 donde se deben enviar todas las escrituras. Luego, definimos escritor_es_también_lector en 1, lo que hará que todos los nodos de Galera también sean lectores, adecuados para consultas que se pueden distribuir por igual a todos los nodos. Hostgroup 9999 está reservado para offline_hostgroup si ProxySQL detecta nodos Galera no operativos.

Luego, configuramos nuestros servidores MySQL con el grupo de host 10 predeterminado:

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 }
)

Con las configuraciones anteriores, ProxySQL "verá" nuestros grupos de host de la siguiente manera:

Luego, definimos el enrutamiento de consultas a través de reglas de consulta. Según nuestro requisito, todas las lecturas deben enviarse a todos los nodos de Galera excepto al escritor (grupo de host 20) y todo lo demás se reenvía al grupo de host 10 para un solo escritor:

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
    }
)

Finalmente, definimos los usuarios de MySQL que se pasarán a través de 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 }
)

Establecemos transaction_persistent en 0 para que todas las conexiones provenientes de estos usuarios respeten las reglas de consulta para el enrutamiento de lecturas y escrituras. De lo contrario, las conexiones terminarían llegando a un grupo de host, lo que anula el propósito del balanceo de carga. No olvide crear esos usuarios primero en todos los servidores MySQL. Para el usuario de ClusterControl, puede usar la función Administrar -> Esquemas y usuarios para crear esos usuarios.

Ahora estamos listos para comenzar nuestro contenedor. Vamos a asignar el archivo de configuración de ProxySQL como montaje de enlace al iniciar el contenedor de ProxySQL. Por lo tanto, el comando de ejecución 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

Finalmente, cambie la base de datos de Wordpress que apunta al puerto de contenedor ProxySQL 6033, por ejemplo:

$ 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

En este punto, nuestra arquitectura se parece a esto:

Si desea que el contenedor ProxySQL sea persistente, asigne /var/lib/proxysql/ a un volumen de Docker o un montaje de enlace, por ejemplo:

$ 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

Tenga en cuenta que ejecutar con almacenamiento persistente como el anterior hará que nuestro /root/proxysql/proxysql.cnf quede obsoleto en el segundo reinicio. Esto se debe a la configuración multicapa de ProxySQL, por lo que si existe /var/lib/proxysql/proxysql.db, ProxySQL omitirá las opciones de carga del archivo de configuración y cargará lo que esté en la base de datos SQLite en su lugar (a menos que inicie el servicio proxysql con --initial bandera). Habiendo dicho eso, la próxima administración de configuración de ProxySQL debe realizarse a través de la consola de administración de ProxySQL en el puerto 6032, en lugar de usar el archivo de configuración.

Monitoreo

El registro de procesos de ProxySQL se registra de forma predeterminada en syslog y puede verlos utilizando el comando estándar de la ventana acoplable:

$ docker ps
$ docker logs proxysql2

Para verificar el grupo de host actual, consulte la tabla 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 |
+--------------+--------------+--------+

Si el escritor seleccionado deja de funcionar, se transferirá a 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 |
+--------------+--------------+--------+

Los cambios de topología anteriores se pueden ilustrar en el siguiente diagrama:

También hemos habilitado la interfaz de usuario de estadísticas web con admin-web_enabled=true. Para acceder a la interfaz de usuario web, simplemente vaya al host de Docker en el puerto 6080, por ejemplo:http://192.168.0.200:8060 y se le solicitará una ventana emergente de nombre de usuario/contraseña. Ingrese las credenciales como se define en admin-stats_credentials y debería ver la siguiente página:

Al monitorear la tabla de conexiones de MySQL, podemos obtener una descripción general de la distribución de conexiones para todos los grupos de host:

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       |
+-----------+--------------+--------+----------+-------------+---------+

El resultado anterior muestra que el grupo de host 30 no procesa nada porque nuestras reglas de consulta no tienen este grupo de host configurado como grupo de host de destino.

Las estadísticas relacionadas con los nodos de Galera se pueden ver en la tabla 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

El conjunto de resultados devuelve el estado de estado/variable de MySQL relacionado para cada nodo de Galera para una marca de tiempo en particular. En esta configuración, configuramos la verificación de estado de Galera para que se ejecute cada 2 segundos (monitor_galera_healthcheck_interval=2000). Por lo tanto, el tiempo máximo de conmutación por error sería de alrededor de 2 segundos si ocurre un cambio de topología en el clúster.

Referencias

  • Compatibilidad con Galera nativa de ProxySQL
  • Solución de HA y clustering:ProxySQL como enrutador inteligente para Galera y Group Replication
  • Imagen de ProxySQL Docker de Variousnines
  • Cómo monitorear ProxySQL con Prometheus y ClusterControl