ProxySQL es uno de los mejores proxies que existen para MySQL. Introdujo una gran cantidad de opciones para los administradores de bases de datos. Hizo posible dar forma al tráfico de la base de datos retrasando, almacenando en caché o reescribiendo consultas sobre la marcha. También se puede utilizar para crear un entorno en el que las conmutaciones por error no afectarán a las aplicaciones y serán transparentes para ellas. Ya cubrimos las características más importantes de ProxySQL en publicaciones de blog anteriores:
- Cómo usar ClusterControl y ProxySQL para almacenar consultas en caché
- Cómo construir un firewall SQL con ClusterControl y ProxySQL
- Cómo implementar un clúster de ProxySQL
- Cómo implementar fácilmente un entorno de replicación MySQL con ProxySQL para alta disponibilidad
Incluso tenemos un tutorial que cubre ProxySQL y muestra cómo se puede usar en configuraciones de MySQL y MariaDB.
Recientemente se ha lanzado ProxySQL 2.0.3, siendo un lanzamiento de parche para la serie 2.0. Se están solucionando errores y la línea 2.0 parece comenzar a obtener la tracción que se merece. En esta publicación de blog, nos gustaría analizar los principales cambios introducidos en ProxySQL 2.0.
Lecturas causales usando GTID
Todos los que tuvieron que lidiar con el retraso de la replicación y lucharon con escenarios de lectura tras escritura que se ven afectados por el retraso de la replicación definitivamente estarán muy contentos con esta característica. Hasta ahora, en los entornos de replicación de MySQL, la única forma de garantizar lecturas causales era leer del maestro (y no importa si usa la replicación asincrónica o semisincrónica). Otra opción era optar por Galera, que tenía una opción para aplicar lecturas causales desde siempre (primero solía ser wsrep-causal-reads y ahora es wsrep-sync-wait). Recientemente (en 8.0.14) la replicación del grupo MySQL obtuvo una característica similar. Sin embargo, la replicación regular, por sí sola, no puede solucionar este problema. Afortunadamente, ProxySQL está aquí y nos brinda una opción para definir según la regla de consulta con lo que lee el grupo de host que coincide con esa regla de consulta debe ser consistente. La implementación viene con el lector de binlog ProxySQL y puede funcionar con el formato de binlog ROW para MySQL 5.7 y posteriores. Solo se admite Oracle MySQL debido a la falta de funcionalidad requerida en MariaDB. Esta función y sus detalles técnicos se han explicado en el blog oficial de ProxySQL.
SSL para conexiones front-end
ProxySQL siempre tuvo soporte para la conexión SSL de back-end, pero carecía de cifrado SSL para las conexiones provenientes de los clientes. Esto no fue tan importante dado que el patrón de implementación recomendado era ubicar ProxySQL en los nodos de la aplicación y usar un socket Unix seguro para conectarse desde la aplicación al proxy. Esta sigue siendo una recomendación, especialmente si usa ProxySQL para almacenar consultas en caché (los sockets de Unix son más rápidos que la conexión TCP, incluso los locales y con caché es bueno evitar introducir latencia innecesaria). Lo bueno es que con ProxySQL 2.0 ahora hay una opción, ya que introdujo la compatibilidad con SSL para las conexiones entrantes. Puede habilitarlo fácilmente configurando mysql-have_ssl en "verdadero". Habilitar SSL no tiene un impacto inaceptable en el rendimiento. Al contrario, según los resultados del blog oficial de ProxySQL, la caída del rendimiento es muy baja.
Compatibilidad nativa con el clúster de Galera
Galera Cluster ha sido compatible con ProxySQL casi desde el principio, pero hasta ahora se hizo a través de un script externo que (típicamente) ha sido llamado desde el planificador interno de ProxySQL. Dependía de la secuencia de comandos garantizar que la configuración de ProxySQL fuera adecuada, que el escritor (o escritores) se detectara y configurara correctamente en el grupo de host de escritores. El script pudo detectar los diferentes estados que puede tener el nodo de Galera (Principal, No principal, Sincronizado, Donante/Desincronizado, Uniéndose, Unido) y marcó el nodo en consecuencia como disponible o no. El problema principal es que el guión original nunca tuvo la intención de ser otra cosa que la prueba de concepto escrita en Bash. Sin embargo, como se distribuyó junto con ProxySQL, comenzó a mejorarse y modificarse por colaboradores externos. Otros (como Percona) buscaron crear sus propios scripts, incluidos con su software. Se han introducido algunas correcciones en el script del repositorio de ProxySQL, otras se han introducido en la versión Percona del script. Esto generó confusión y, aunque todos los scripts de uso común manejaron el 95 % de los casos de uso, ninguno de los más populares realmente cubría todas las diferentes situaciones y variables que el clúster de Galera podría terminar usando. Afortunadamente, ProxySQL 2.0 viene con soporte nativo para Galera Cluster. Esto hace que ProxySQL admita internamente la replicación de MySQL, la replicación de grupos de MySQL y ahora Galera Cluster. La forma en que se hace es muy similar. Nos gustaría cubrir la configuración de esta función, ya que puede no ser clara a primera vista.
Al igual que con la replicación de MySQL y la replicación de grupo de MySQL, se ha creado una tabla en ProxySQL:
mysql> show create table mysql_galera_hostgroups\G
*************************** 1. row ***************************
table: mysql_galera_hostgroups
Create Table: CREATE TABLE mysql_galera_hostgroups (
writer_hostgroup INT CHECK (writer_hostgroup>=0) NOT NULL PRIMARY KEY,
backup_writer_hostgroup INT CHECK (backup_writer_hostgroup>=0 AND backup_writer_hostgroup<>writer_hostgroup) NOT NULL,
reader_hostgroup INT NOT NULL CHECK (reader_hostgroup<>writer_hostgroup AND backup_writer_hostgroup<>reader_hostgroup AND reader_hostgroup>0),
offline_hostgroup INT NOT NULL CHECK (offline_hostgroup<>writer_hostgroup AND offline_hostgroup<>reader_hostgroup AND backup_writer_hostgroup<>offline_hostgroup AND offline_hostgroup>=0),
active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 1,
max_writers INT NOT NULL CHECK (max_writers >= 0) DEFAULT 1,
writer_is_also_reader INT CHECK (writer_is_also_reader IN (0,1,2)) NOT NULL DEFAULT 0,
max_transactions_behind INT CHECK (max_transactions_behind>=0) NOT NULL DEFAULT 0,
comment VARCHAR,
UNIQUE (reader_hostgroup),
UNIQUE (offline_hostgroup),
UNIQUE (backup_writer_hostgroup))
1 row in set (0.00 sec)
Hay numerosos ajustes para configurar y los repasaremos uno por uno. En primer lugar, hay cuatro grupos de host:
- Writer_hostgroup:contendrá todos los escritores (con read_only=0) hasta la configuración 'max_writers'. Por defecto es solo un escritor
- Backup_writer_hostgroup:contiene los escritores restantes (read_only=0) que quedan después de agregar 'max_writers' awriter_hostgroup
- Reader_hostgroup:contiene lectores (read_only=1), también puede contener escritores de respaldo, según la configuración 'writer_is_also_reader'
- Offline_hostgroup:contiene nodos que se consideraron no utilizables (fuera de línea o en un estado que hace que sea imposible manejar el tráfico)
Luego tenemos las configuraciones restantes:
- Activo:si la entrada en mysql_galera_hostgroups está activa o no
- Max_writers:cuántos nodos como máximo se pueden colocar en el grupo de host de escritores
- Writer_is_also_reader:si se establece en 0, los escritores (read_only=0) no se colocarán en reader_hostgroup. Si se establece en 1, los escritores (read_only=0) se colocarán en reader_hostgroup. Si se establece en 2, los nodos de backup_writer_hostgroup se colocarán en reader_hostgroup. Este es un poco complejo, por lo tanto, presentaremos un ejemplo más adelante en esta publicación de blog
- Max_transactions_behind:basado en wsrep_local_recv_queue, la cola máxima aceptable. Si la cola en el nodo excede max_transactions_behind, el nodo dado se marcará como SHUNNED y no estará disponible para el tráfico
La principal sorpresa podría ser el manejo de los lectores, que es diferente a cómo funcionaba el script incluido en ProxySQL. En primer lugar, lo que debe tener en cuenta es el hecho de que ProxySQL usa read_only=1 para decidir si el nodo es un lector o no. Esto es común en configuraciones de replicación, no tan común en Galera. Por lo tanto, lo más probable es que desee utilizar la configuración 'writer_is_also_reader' para configurar cómo se deben agregar los lectores al grupo de host_lectores. Consideremos tres nodos de Galera, todos ellos tienen read_only=0. También tenemos max_writers=1 porque queremos dirigir todas las escrituras hacia un nodo. Configuramos mysql_galera_hostgroups de la siguiente manera:
SELECT * FROM mysql_galera_hostgroups\G
*************************** 1. row ***************************
writer_hostgroup: 10
backup_writer_hostgroup: 30
reader_hostgroup: 20
offline_hostgroup: 40
active: 1
max_writers: 1
writer_is_also_reader: 0
max_transactions_behind: 0
comment: NULL
1 row in set (0.00 sec)
Repasemos todas las opciones:
escritor_es_también_lector=0
mysql> SELECT hostgroup_id, hostname FROM runtime_mysql_servers;
+--------------+------------+
| hostgroup_id | hostname |
+--------------+------------+
| 10 | 10.0.0.103 |
| 30 | 10.0.0.101 |
| 30 | 10.0.0.102 |
+--------------+------------+
3 rows in set (0.00 sec)
Este resultado es diferente de lo que vería en los scripts:allí tendría los nodos restantes marcados como lectores. Aquí, dado que no queremos que los escritores sean lectores y dado que no hay ningún nodo con read_only=1, no se configurarán lectores. Un escritor (según max_writers), los nodos restantes en backup_writer_hostgroup.
escritor_es_también_lector=1
mysql> SELECT hostgroup_id, hostname FROM runtime_mysql_servers;
+--------------+------------+
| hostgroup_id | hostname |
+--------------+------------+
| 10 | 10.0.0.103 |
| 20 | 10.0.0.101 |
| 20 | 10.0.0.102 |
| 20 | 10.0.0.103 |
| 30 | 10.0.0.101 |
| 30 | 10.0.0.102 |
+--------------+------------+
6 rows in set (0.00 sec)
Aquí queremos que nuestros escritores actúen como lectores, por lo tanto, todos ellos (activos y de respaldo) se colocarán en el grupo host_lectores.
escritor_es_también_lector=2
mysql> SELECT hostgroup_id, hostname FROM runtime_mysql_servers;
+--------------+------------+
| hostgroup_id | hostname |
+--------------+------------+
| 10 | 10.0.0.103 |
| 20 | 10.0.0.101 |
| 20 | 10.0.0.102 |
| 30 | 10.0.0.101 |
| 30 | 10.0.0.102 |
+--------------+------------+
5 rows in set (0.00 sec)
Esta es una configuración para aquellos que no quieren que su escritor activo maneje las lecturas. En este caso, solo se utilizarán los nodos de backup_writer_hostgroup para las lecturas. También tenga en cuenta que la cantidad de lectores cambiará si establece max_writers en algún otro valor. Si lo configuráramos en 3, no habría escritores de respaldo (todos los nodos terminarían en el grupo de host del escritor), por lo tanto, nuevamente, no habría nodos en el grupo de host del lector.
Por supuesto, querrá configurar las reglas de consulta de acuerdo con la configuración del grupo de host. No pasaremos por este proceso aquí, puede comprobar cómo se puede hacer en el blog de ProxySQL. Si desea probar cómo funciona en un entorno Docker, tenemos un blog que cubre cómo ejecutar el clúster de Galera y ProxySQL 2.0 en Docker.
Otros cambios
Lo que describimos anteriormente son las mejoras más notables en ProxySQL 2.0. Hay muchos otros, según el registro de cambios. Vale la pena mencionar las mejoras en la caché de consultas (por ejemplo, la adición de PROXYSQL FLUSH QUERY CACHE) y el cambio que permite a ProxySQL confiar en super_read_only para determinar el maestro y los esclavos en la configuración de la replicación.
Esperamos que esta breve descripción general de los cambios en ProxySQL 2.0 lo ayude a determinar qué versión de ProxySQL debe usar. Tenga en cuenta que la rama 1.4, incluso si no obtendrá nuevas funciones, aún se mantiene.