Alta Disponibilidad y Resiliencia en Bases de Datos con MaxScale

Las aplicaciones críticas para la misión requieren alta disponibilidad. El objetivo de la alta disponibilidad es proporcionar a los usuarios acceso constante a servicios o recursos, minimizando las posibilidades de interrupción. Conmutación por error automática es un mecanismo específico utilizado para lograr alta disponibilidad. Implica detectar automáticamente la falla de un componente del sistema (como un servidor, red o base de datos) y cambiar inmediatamente las operaciones a un componente de respaldo sin intervención humana. Esto aumenta la resistencia.

MariaDB MaxScale es un proxy de base de datos que incluye características para alta disponibilidad. En este artículo, te mostraré cómo puedes probarlo con una aplicación simulador de tienda online implementada en Java y Svelte.

Arquitectura

El siguiente diagrama muestra la arquitectura de la aplicación de demostración:


A web application developed with JavaScript and the Svelte framework makes HTTP requests to a Java backend. The backend answers with server-sent events that the frontend uses to update the user interface on the browser.

El backend está implementado con Spring Boot y se conecta a un clúster de MariaDB utilizando R2DBC (reactivo). La lógica del backend es, en resumen, una simulación de lecturas y escrituras a una base de datos de una tienda online. La simulación está parametrizada, y el usuario puede ajustar:

  • Visitas de productos por minuto: Cuántas lecturas a la base de datos por minuto.
  • Órdenes por minuto: Cuántas escrituras a la base de datos por minuto.
  • Productos por orden: Escritura de amplificación.
  • Tiempo de espera en milisegundos: Cuántos segundos deben transcurrir para considerar que una solicitud a la base de datos ha fallado.

El clúster de base de datos está front-endeado por un proxy de base de datos llamado MaxScale. Este proxy hace que el clúster parezca una única base de datos lógica para el backend de Java. MaxScale también realiza división lectura/escritura (enviando escrituras al servidor primario de MariaDB y lecturas a las réplicas), así como equilibrio de carga de lecturas entre servidores de réplica utilizando un algoritmo configurable. Los datos se replican automáticamente replicados desde el servidor primario hasta los servidores de base de datos de réplica.

Construcción de las Imágenes de Docker a Partir del Código Fuente

I have prepared custom Docker images for every component in the simulator. You can either build the images from the source (optional) or use the already built and published images from Docker Hub. If you decide to build the images yourself, you can find the source code on GitHub:

  • Implementaciones de MariaDB: Imágenes personalizadas para una fácil implementación de topologías replicadas de MariaDB con MaxScale. ¡NO UTILIZAR ESTAS EN PRODUCCIÓN! Estas imágenes solo son adecuadas para aplicaciones demostrativas. Utilice las imágenes oficiales de MariaDB para Docker para implementaciones en producción.
  • Aplicación de backend: La aplicación de backend que se conecta al clúster de bases de datos.
  • Aplicación de frontend: La aplicación de frontend que realiza solicitudes de configuración de simulación al backend y recibe eventos para mostrar el resultado de la simulación.

Cada repositorio tiene archivos Dockerfile que puedes utilizar para construir tus propias imágenes Docker. Por ejemplo, para construir la imagen de la aplicación de backend, ejecuta:

Shell

 

docker build --tag alejandrodu/online-store-simulator-java-backend .

Ejecutando la Simulación

Todos los servicios pueden iniciarse utilizando el siguiente archivo Docker Compose (docker-compose.yml):

YAML

 

version: "3.9"
services:
  server-1:
    container_name: server-1
    image: alejandrodu/mariadb
    ports:
      - "3306:3306"
    environment:
      - MARIADB_CREATE_DATABASE=demo
      - MARIADB_CREATE_USER=user:Password123!
      - MARIADB_CREATE_REPLICATION_USER=replication_user:ReplicationPassword123!
      - MARIADB_CREATE_MAXSCALE_USER=maxscale_user:MaxScalePassword123!

  server-2:
    container_name: server-2
    image: alejandrodu/mariadb
    ports:
      - "3307:3306"
    environment:
      - MARIADB_REPLICATE_FROM=replication_user:ReplicationPassword123!@server-1:3306

  server-3:
    container_name: server-3
    image: alejandrodu/mariadb
    ports:
      - "3308:3306"
    environment:
      - MARIADB_REPLICATE_FROM=replication_user:ReplicationPassword123!@server-1:3306

  maxscale:
    container_name: maxscale
    image: alejandrodu/mariadb-maxscale
    command: --admin_host 0.0.0.0 --admin_secure_gui false
    ports:
      - "4000:4000"
      - "8989:8989"
      - "27017:27017"
    environment:
      - MAXSCALE_USER=maxscale_user:MaxScalePassword123!
      - MARIADB_HOST_1=server-1 3306
      - MARIADB_HOST_2=server-2 3306
      - MARIADB_HOST_3=server-3 3306
    healthcheck:
      test: ["CMD", "maxctrl", "list", "servers"]
      interval: 5s
      timeout: 10s
      retries: 5

  java-backend:
    container_name: java-backend
    image: alejandrodu/online-store-simulator-java-backend
    ports:
      - "8080:8080"
    environment:
    - spring.r2dbc.url=r2dbc:mariadb://maxscale:4000/demo
    - spring.r2dbc.username=user
    - spring.r2dbc.password=Password123!
    - spring.liquibase.url=jdbc:mariadb://maxscale:4000/demo
    - spring.liquibase.user=user
    - spring.liquibase.password=Password123!
    depends_on:
      maxscale:
        condition: service_healthy

  svelte-frontend:
    container_name: svelte-fronted
    image: alejandrodu/online-store-simulator-svelte-frontend
    ports:
      - "5173:80"
    environment:
      - BACKEND_URL=http://java-backend:8080

Dirígete al directorio donde se encuentra el archivo Docker Compose y comienza los servicios en modo desacoplado de la siguiente manera:

Shell

 

docker compose up -d

Configurando MaxScale

Antes de iniciar la simulación, configura MaxScale para la reproducción de transacciones. Además, ajusta los tiempos de espera para hacer la simulación más interesante.

Navega a http://localhost:8989/ y accede a la interfaz de usuario usando:

  • Nombre de usuario:admin
  • Contraseña:mariadb

Verás un panel de control con el estado del clúster de MariaDB.


Hay un servidor primario (server-1), y dos réplicas (server-2 y server-3). La replicación ya está configurada desde server-1 (primario) a server-2 y server-3 (réplicas). Todos los servidores deberían estar en funcionamiento.

Haz clic en mdb_monitor y luego en el icono lápiz para habilitar la edición de parámetros. Establece los siguientes parámetros:

  • auto_failover (true): Esto habilita el fallover automático. Cuando un servidor de MariaDB está inactivo, MaxScale selecciona un servidor de réplica y lo reconfigura como el nuevo primario para que las escrituras puedan continuar.
  • auto_rejoin (true): Esto habilita la reincorporación automática de servidores recuperados. Cuando un servidor fallido está de nuevo en línea, MaxScale lo detecta y lo configura como un servidor de réplica disponible.
  • failcount (1): Establece el número de iteraciones del monitor (un componente en MaxScale que verifica el estado del servidor) necesarias para que un servidor esté inactivo y activar el proceso de fallover. Establecemos un valor de 1 para asegurarnos de que el fallover comience inmediatamente después de un fallo.
  • backend_connect_timeout (1000): Tiempo de espera de conexión para las conexiones del monitor. Establecemos un valor bajo (un segundo) para activar rápidamente el fallover para esta demostración.
  • backend_read_timeout (1000): Tiempo de espera para la lectura de conexiones de monitorización.
  • backend_write_timeout (1000): Tiempo de espera para la escritura de conexiones de monitorización.
  • master_failure_timeout (1000): Tiempo de espera por fallo primario.
  • monitor_interval (1000): Frecuencia con la que se monitorizan los servidores.

ADVERTENCIA: Estos valores son adecuados para esta demostración pero muy probablemente no sean los mejores para entornos de producción!

Una vez establecidos los parámetros, haga clic en Hecho editando y Confirmar.

También necesita habilitar la reproducción de transacciones que reejecuta automáticamente las transacciones en curso fallidas en servidores que se han caído justo después de que se enrutara una declaración SQL. Esta es una característica útil para los desarrolladores de software ya que evita la necesidad de codificar casos de fallo y reintento de transacciones.

En el menú principal, haga clic en Panel de control y luego en cualquiera de los enlaces servicio_enrutador_de_consultas en la lista de servidores. Edite los parámetros de la siguiente manera:

  • transaction_replay (true): Activa el reintento automático de transacciones fallidas.
  • transaction_replay_retry_on_deadlock (true): Igual que el anterior cuando ocurre un bloqueo.
  • transaction_replay_retry_on_mismatch (true): Igual que el anterior cuando ocurre una discrepancia de suma de verificación.

Una vez establecidos los parámetros, haga clic en Hecho editando y Confirmar.

Empezando la Simulación

Con todo configurado, puedes comenzar la simulación. Dirígete a http://localhost:5173/ y configura los siguientes parámetros (los nombres, espero, son autoexplicativos):

  • Visitas de productos por minuto:6000
  • Órdenes por minuto:60
  • Tiempo de espera en milisegundos:8000

Pero antes de comenzar la simulación, necesitas crear los productos para la tienda en línea. Haz clic en Datos | Crear productos…. Deja los valores predeterminados y haz clic en Crear. Deberías ver la IU actualizándose a medida que se crean productos en la base de datos.

Ahora finalmente puedes hacer clic en Iniciar y ver la simulación en acción.


Simulando una Falla del Servidor

En este punto, el servidor principal está manejando escrituras (órdenes). ¿Qué sucede si detienes ese servidor? En la línea de comandos ejecuta:

Shell

 

docker stop server-1

Dependiendo de varios factores, podrías obtener algunos “visitantes decepcionados” o incluso algunas “oportunidades perdidas” en el simulador. O tal vez no obtengas ninguna en absoluto! Las visitas de productos (lecturas) y las órdenes (escrituras) continúan gracias a MaxScale. Sin conmutación por error automática, tienes que reconfigurar todo manualmente, lo que resulta en más tiempo fuera de línea y en muchos visitantes decepcionados y oportunidades perdidas!

Inicia el servidor fallido:

Shell

 

docker start server-1

Ve al Panel de control de MaxScale (http://localhost:8989/) y comprueba que server-1 ahora es una réplica funcional.

Puedes realizar un cambio manual para volver a hacer que servidor-1 sea el servidor principal. Haz clic en mdb_monitor y luego pasa el mouse sobre la sección MASTER. Haz clic en el icono lápiz y selecciona servidor-1. Haz clic en Intercambiar y verifica nuevamente en el Panel de control que el nuevo servidor principal es servidor-1.

Conclusión

El failover automático es solo uno de los componentes en sistemas altamente disponibles. Puedes utilizar un proxy de base de datos como MaxScale para configurar el failover automático, pero también otros componentes como equilibrio de carga, enrutamiento de consultas, reintento de transacciones, aislamiento de topología y más. Echa un vistazo a la documentación aquí.

Source:
https://dzone.com/articles/high-availability-and-resiliency-in-databases