利用MaxScale实现数据库的高可用性与韧性

关键任务应用需要高可用性。高可用性的目标是确保用户能够持续访问服务或资源,最大限度减少中断的可能性。自动故障转移是实现高可用性的一种特定机制,它能够自动检测系统组件(如服务器、网络或数据库)的故障,并立即切换到备用组件,无需人工干预,从而提升系统的韧性。

MariaDB MaxScale是一款包含高可用性特性的数据库代理。本文将展示如何通过一个采用Java和Svelte实现的在线商店模拟器应用程序来尝试这一功能。

架构

以下图示展示了演示应用的架构:


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.

后端采用Spring Boot构建,并通过R2DBC(响应式)连接到MariaDB数据库集群。后端逻辑简而言之是对在线商店数据库进行读写操作的模拟。该模拟是参数化的,用户可以调整:

  • 每分钟产品访问量:即每分钟对数据库的读取次数。
  • 每分钟订单量:即每分钟对数据库的写入次数。
  • 单次订单产品数量: 写入放大。
  • 超时毫秒数: 数据库请求被视为失败的等待秒数。

数据库集群前端部署了一个名为MaxScale的数据库代理。该代理使得集群对Java后端呈现为一个单一逻辑数据库。MaxScale还执行读写分离(将写操作发送到主MariaDB服务器,读操作发送到副本),并通过一个可配置算法在副本服务器间进行读取负载均衡。数据自动从主服务器复制到副本数据库服务器。

从源代码构建Docker镜像

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:

  • MariaDB部署: 提供定制镜像,便于快速部署带有MaxScale的MariaDB复制拓扑结构。请勿在生产环境中使用这些镜像! 这些镜像仅适用于演示应用。生产部署请使用官方MariaDB Docker镜像
  • 后端应用: 连接到数据库集群的后端应用。
  • 前端应用: 向后台发送模拟配置请求并接收事件以展示模拟结果的前端应用。

每个仓库均包含Dockerfile,供您构建自定义Docker镜像。例如,构建后端应用镜像,请运行:

Shell

 

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

运行模拟

所有服务可通过以下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

切换至包含Docker Compose文件的目录,并以下列方式以分离模式启动服务:

Shell

 

docker compose up -d

配置MaxScale

在启动模拟之前,需为事务回放配置MaxScale,并调整超时设置以增加模拟趣味性。

访问 http://localhost:8989/ 并使用以下凭据登录界面:

  • 用户名:admin
  • 密码:mariadb

。登录后,您将看到一个显示MariaDB集群状态的仪表板。


该集群包括一个主服务器(server-1)和两个副本服务器(server-2server-3)。从server-1(主服务器)到server-2server-3(副本服务器)的复制已经配置完毕。所有服务器应处于运行状态。

点击mdb_monitor,然后点击铅笔图标以启用参数编辑。设置以下参数:

  • auto_failovertrue):此设置启用自动故障转移。当MariaDB服务器宕机时,MaxScale会选出一个副本服务器并将其重新配置为新的主服务器,以确保写操作可以继续进行。
  • auto_rejointrue):此设置启用已恢复服务器的自动重新加入。当故障服务器重新上线时,MaxScale会检测到并将其配置为可用的副本服务器。
  • failcount1):设置监控器(MaxScale中检查服务器状态的组件)迭代次数,以确定服务器宕机并激活故障转移流程。我们设置为1,确保故障发生后立即启动故障转移。
  • backend_connect_timeout1000):监控连接的连接超时时间。我们设置一个较低的值(一秒),以便在演示中快速激活故障转移。
  • backend_read_timeout (1000毫秒): 监控连接的读取超时时间。
  • backend_write_timeout (1000毫秒): 监控连接的写入超时时间。
  • master_failure_timeout (1000毫秒): 主服务器故障超时时间。
  • monitor_interval (1000毫秒): 服务器监控频率。

警告: 这些值适用于本次演示,但很可能不适合生产环境!

设置好参数后,点击完成编辑确认

还需启用事务重放功能,该功能会自动在服务器宕机后重新执行失败的飞行中事务,这对于软件开发者非常有用,因为它避免了编写故障情况和事务重试的代码。

在主菜单中,点击仪表板,然后在服务器列表中选择任意一个查询路由服务链接。按如下方式编辑参数:

  • transaction_replay (true): 激活失败事务的自动重试。
  • transaction_replay_retry_on_deadlock (true): 当发生死锁时,同上。
  • transaction_replay_retry_on_mismatch (true): 当发生校验和不匹配时,同上。

设置好参数后,点击完成编辑确认

开始模拟

配置完成后,即可开始模拟。访问 http://localhost:5173/ 并设置以下参数(希望名称已足够说明):

  • 每分钟产品访问量:6000
  • 每分钟订单量:60
  • 超时时间(毫秒):8000

但在启动模拟前,需为网店创建产品。点击数据 | 创建产品…。保留默认值并点击创建。随着产品在数据库中创建,UI将相应更新。

现在,终于可以点击开始,观察模拟运行。


模拟服务器故障

此时,主服务器正处理写入操作(订单)。若停止该服务器,会发生什么?在命令行中运行:

Shell

 

docker stop server-1

根据多种因素,模拟器中可能会出现一些“失望的访客”或“错失的机会”。也可能完全无此情况!得益于MaxScale,产品访问(读取)和订单(写入)仍能继续。若无自动故障转移,需手动重新配置所有内容,这将导致更多离线时间和大量失望的访客及错失的机会!

启动故障服务器:

Shell

 

docker start server-1

前往MaxScale 仪表板(http://localhost:8989/),确认server-1现已作为正常运行的副本。

您可以执行手动切换操作,使服务器-1再次成为主服务器。点击mdb_monitor,然后将鼠标悬停在MASTER部分上。点击铅笔图标并选择服务器-1。点击交换,并在仪表板中再次检查新的主服务器是否为服务器-1

结论

自动故障转移只是高可用系统中的一个组成部分。您可以使用MaxScale这样的数据库代理来设置自动故障转移,还包括其他组件如负载均衡、查询路由、事务重试、拓扑隔离等。详细信息请查阅此处的文档。

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