You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何测试MaxScale负载均衡?MariaDB主从查询分发异常排查

MariaDB主从+MaxScale架构下,SELECT查询分发不均的问题排查与测试方案

我搭建了MariaDB主从架构并配置了MaxScale,想测试MaxScale是否能将SELECT查询分发到多个副本库,但当前测试结果显示查询只转发到其中一个副本库,求正确的测试方法。

服务器信息

  • MariaDB 10.11
  • MaxScale 23.02.4
  • masterDB: 192.168.30.140
  • replicaDB1: 192.168.30.141
  • replicaDB2: 192.168.30.142
  • replicaDB3: 192.168.30.143
  • maxscale: 192.168.30.145
  • client: 192.168.30.160
  • 端口映射:3309指向主库,3310指向副本库

MaxScale配置

[maxscale]
threads=auto

[MariaDB-Monitor]
type=monitor
module=mariadbmon
servers=masterDB, replicaDB1, replicaDB2, replicaDB3
user=monitor
password=alj123
monitor_interval=2s

[masterDB]
type=server
address=192.168.30.140
port=3306
protocol=MariaDBBackend
proxy_protocol=true
persistpoolmax=100
persistmaxtime=3600s
monitoruser=monitor
monitorpw=alj123
max_routing_connections=1000

[replicaDB1]
type=server
address=192.168.30.141
port=3306
protocol=MariaDBBackend
proxy_protocol=true
persistpoolmax=100
persistmaxtime=3600s
monitoruser=monitor
monitorpw=alj123
max_routing_connections=1000

[replicaDB2]
type=server
address=192.168.30.142
port=3306
protocol=MariaDBBackend
proxy_protocol=true
persistpoolmax=100
persistmaxtime=3600s
monitoruser=monitor
monitorpw=alj123
max_routing_connections=1000

[replicaDB3]
type=server
address=192.168.30.143
port=3306
protocol=MariaDBBackend
proxy_protocol=true
persistpoolmax=100
persistmaxtime=3600s
monitoruser=monitor
monitorpw=alj123
max_routing_connections=1000

# 写服务定义
[Write-Service]
type=service
router=readconnroute
router_options=master, slave
servers=masterDB
user=maxscale
password=alj123
max_connections=100

# 读服务定义
[Read-Service]
type=service
router=readconnroute
router_options=slave
servers=replicaDB1,
        replicaDB2,
        replicaDB3
user=read
password=alj123
max_connections=100

# 写请求监听器
[Write-Listener]
type=listener
service=Write-Service
protocol=MariaDBClient
port=3309
address=0.0.0.0
proxy_protocol_networks=192.168.30.145/24

# 读请求监听器
[Read-Listener]
type=listener
service=Read-Service
protocol=MariaDBClient
port=3310
address=0.0.0.0
proxy_protocol_networks=192.168.30.145/24

当前测试脚本(PHP)

<?php
$start = (new DateTime())->getTimestamp();
echo "start= $start" . PHP_EOL;

for ($i=0; $i<40000; $i++) {
   $mysqli = new mysqli("p:192.168.30.145", "client", "alj123", "TOPGUN", "3310");

   $mysqli->query("SELECT pilot from TOPGUN.pilots");
   $sql = "SELECT @@hostname";
   $result = $mysqli->query($sql);

   if ($result->num_rows > 0) {
       $row = $result->fetch_assoc();
       echo "DB主机: " . $row['@@hostname'] . PHP_EOL;
   } else {
       echo "无法获取DB主机信息";
   }

   $result->free();
   $mysqli->close();
   unset($tmp, $row, $result, $mysqli);
}
   $end = (new DateTime())->getTimestamp();
   echo '耗时= ' . ($end - $start) . '秒' . PHP_EOL;
?>

问题分析与解决方案

1. 配置问题排查

你的Read-Service使用readconnroute路由器,默认负载均衡策略是轮询(roundrobin),但需确认以下几点:

  • 检查MaxScale监控状态,确保三个副本库都被标记为Slave且处于Running状态:
    执行MaxScale命令:
    maxctrl list servers
    
    输出中每个replicaDB的状态需包含Slave, Running,若副本状态异常,MaxScale不会将请求分发过去。
  • 显式指定负载均衡策略:在Read-Service的router_options中添加roundrobin,确保策略生效,修改后为:
    router_options=slave,roundrobin
    
    修改后重启MaxScale:systemctl restart maxscale

2. 测试脚本的问题

单线程循环创建连接的方式无法模拟真实并发场景,且脚本中使用了持久连接(p:前缀),持久连接会被MaxScale复用,导致同一连接的请求都发到同一个副本。

改进后的测试方法:

  • 多进程/多线程测试:MaxScale的负载均衡是针对不同连接的,多进程能模拟真实并发,示例PHP多进程脚本:
    <?php
    $processCount = 10; // 启动10个测试进程
    $requestsPerProcess = 4000; // 每个进程发起4000次请求
    
    for ($p = 0; $p < $processCount; $p++) {
        $pid = pcntl_fork();
        if ($pid == -1) {
            die("进程创建失败");
        } elseif ($pid == 0) {
            // 子进程逻辑
            for ($i=0; $i<$requestsPerProcess; $i++) {
                $mysqli = new mysqli("192.168.30.145", "client", "alj123", "TOPGUN", "3310");
                if ($mysqli->connect_error) {
                    echo "连接失败: " . $mysqli->connect_error . PHP_EOL;
                    continue;
                }
                $result = $mysqli->query("SELECT @@hostname");
                if ($result) {
                    $row = $result->fetch_assoc();
                    echo "进程{$p} - DB主机: " . $row['@@hostname'] . PHP_EOL;
                    $result->free();
                }
                $mysqli->close();
            }
            exit();
        }
    }
    
    // 等待所有子进程结束
    while (pcntl_waitpid(0, $status) != -1);
    
    echo "所有测试完成" . PHP_EOL;
    ?>
    
  • 移除持久连接前缀:去掉脚本中mysqli连接地址的p:,使用短连接,让每个请求创建独立连接,MaxScale会为新连接分配不同副本。
  • 手动多次测试:用mysql客户端多次执行查询,观察返回的主机名是否轮流切换:
    # 重复执行该命令,查看输出变化
    mysql -h 192.168.30.145 -P 3310 -u client -palj123 -e "SELECT @@hostname"
    

3. 连接池配置调整

persistpoolmax=100和persistmaxtime=3600s会让MaxScale复用连接,若测试时连接未释放,可能导致请求集中在某个副本。可临时降低persistmaxtime,或测试前重启MaxScale清空连接池。

验证步骤

  1. 执行maxctrl list servers确认所有副本状态正常。
  2. 修改Read-Service的router_options为slave,roundrobin,重启MaxScale。
  3. 使用多进程脚本或手动多次执行mysql命令,观察返回的主机名是否均匀分布在三个副本上。

内容的提问来源于stack exchange,提问作者hekke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 23:12:13