实现高可用 MySQL 集群
Published in:2025-09-30 |
Words: 1.4k | Reading time: 6min | reading:

准备阶段:项目结构

首先,在您的服务器上创建一个项目文件夹,结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql_cluster/
├── docker-compose.yml
├── proxysql/
│ └── proxysql.cnf
└── mysql/
├── master/
│ └── conf/
│ └── master.cnf
├── slave1/
│ └── conf/
│ └── slave1.cnf
└── slave2/
└── conf/
└── slave2.cnf

阶段一:编写配置文件

1. 主库配置 (mysql/master/conf/master.cnf)

这个文件定义了主库的特定配置。

1
2
3
4
5
[mysqld]
server-id = 100
log-bin = /var/lib/mysql/mysql-bin
gtid-mode = ON
enforce-gtid-consistency= ON

注意:我们使用了 GTID 模式,这是比传统基于 FilePosition 更现代、更可靠的复制方式。

2. 从库配置 (mysql/slave1/conf/slave1.cnfslave2.cnf)

两个从库的配置类似,只需更改 server-id

slave1.cnf:

1
2
3
4
5
[mysqld]
server-id = 101
gtid-mode = ON
enforce-gtid-consistency= ON
read-only = 1

slave2.cnf:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[mysqld]
server-id = 102
gtid-mode = ON
enforce-gtid-consistency= ON
read-only = 1```

#### 3. ProxySQL 配置 (`proxysql/proxysql.cnf`)

这个文件用于初始化 ProxySQL 的配置。
```ini
admin_variables=
{
admin_credentials="admin:admin"
mysql_ifaces="0.0.0.0:6032"
}

mysql_variables=
{
connect_timeout_server=3000
monitor_username="monitor_user"
monitor_password="monitor_password"
monitor_connect_timeout=2000
monitor_ping_timeout=1000
monitor_read_only_interval=1000
monitor_read_only_timeout=1000
commands_stats="enabled"
connect_timeout_server_max=10000
stacksize=1048576
threads=4
max_connections=2048
}

注意:这里我们定义了 ProxySQL 的管理用户 (admin:admin) 和一个用于监控后端 MySQL 健康状态的监控用户 (monitor_user:monitor_password)。

4. Docker Compose 文件 (docker-compose.yml)

这是整个架构的核心编排文件。它定义了所有的服务、网络和数据卷。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
version: '3.8'

services:
# 主数据库
mysql_master:
image: mysql:8.0
container_name: mysql_master
restart: always
environment:
MYSQL_ROOT_PASSWORD: your_root_password
MYSQL_DATABASE: my_app_db
volumes:
- ./mysql/master/conf:/etc/mysql/conf.d
- mysql_master_data:/var/lib/mysql
networks:
- mysql_cluster_net

# 从数据库1
mysql_slave1:
image: mysql:8.0
container_name: mysql_slave1
restart: always
environment:
MYSQL_ROOT_PASSWORD: your_root_password
volumes:
- ./mysql/slave1/conf:/etc/mysql/conf.d
- mysql_slave1_data:/var/lib/mysql
networks:
- mysql_cluster_net
depends_on:
- mysql_master

# 从数据库2
mysql_slave2:
image: mysql:8.0
container_name: mysql_slave2
restart: always
environment:
MYSQL_ROOT_PASSWORD: your_root_password
volumes:
- ./mysql/slave2/conf:/etc/mysql/conf.d
- mysql_slave2_data:/var/lib/mysql
networks:
- mysql_cluster_net
depends_on:
- mysql_master

# ProxySQL 中间件
proxysql:
image: proxysql/proxysql:2.4.4
container_name: proxysql
restart: always
ports:
- "6032:6032" # 管理端口
- "6033:6033" # 客户端连接端口
volumes:
- ./proxysql/proxysql.cnf:/etc/proxysql.cnf
- proxysql_data:/var/lib/proxysql
networks:
- mysql_cluster_net
depends_on:
- mysql_master
- mysql_slave1
- mysql_slave2

# 定义数据卷
volumes:
mysql_master_data:
mysql_slave1_data:
mysql_slave2_data:
proxysql_data:

# 定义网络
networks:
mysql_cluster_net:
driver: bridge

请务必将 your_root_password 替换为您自己的强密码。


阶段二:启动和配置集群

  1. 启动所有服务
    mysql_cluster 文件夹下,运行命令:

    1
    docker-compose up -d

    Docker 会自动拉取镜像并按顺序启动所有容器。

  2. 配置主从复制
    我们需要进入主库容器,创建复制用户和 ProxySQL 的监控用户。

    1
    2
    3
    4
    5
    6
    # 进入主库容器
    docker exec -it mysql_master bash

    # 登录MySQL
    mysql -u root -p
    # (输入您在docker-compose中设置的密码)

    在MySQL命令行中执行:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    -- 创建复制用户
    CREATE USER 'repl_user'@'%' IDENTIFIED BY 'repl_password';
    GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'%';

    -- 创建ProxySQL监控用户
    CREATE USER 'monitor_user'@'%' IDENTIFIED BY 'monitor_password';
    GRANT USAGE ON *.* TO 'monitor_user'@'%';

    FLUSH PRIVILEGES;

    现在,配置两个从库。进入每个从库容器,执行 CHANGE MASTER TO 命令。

    1
    2
    3
    # 进入从库1容器
    docker exec -it mysql_slave1 bash
    mysql -u root -p

    在从库1的MySQL命令行中执行(对从库2重复此操作):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    -- 使用GTID自动定位,比File/Position更简单
    CHANGE MASTER TO
    MASTER_HOST='mysql_master', -- 使用Docker的服务名
    MASTER_USER='repl_user',
    MASTER_PASSWORD='repl_password',
    MASTER_AUTO_POSITION=1;

    START SLAVE;
    -- 验证状态
    SHOW SLAVE STATUS\G;

    在从库2上重复以上 CHANGE MASTER TOSTART SLAVE 的步骤。

  3. 配置 ProxySQL
    连接到 ProxySQL 的管理后台。

    1
    2
    # 注意,是从您的宿主机连接,不是在容器里
    mysql -u admin -padmin -h 127.0.0.1 -P 6032

    在 ProxySQL 管理后台执行以下命令:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    -- 设置监控用户凭证(与proxysql.cnf和MySQL中创建的一致)
    UPDATE global_variables SET variable_value='monitor_user' WHERE variable_name='mysql-monitor_username';
    UPDATE global_variables SET variable_value='monitor_password' WHERE variable_name='mysql-monitor_password';
    LOAD MYSQL VARIABLES TO RUNTIME;

    -- 配置后端MySQL服务器
    INSERT INTO mysql_servers(hostgroup_id, hostname, port) VALUES
    (10, 'mysql_master', 3306), -- 写入组 (主库)
    (20, 'mysql_slave1', 3306), -- 读取组 (从库1)
    (20, 'mysql_slave2', 3306); -- 读取组 (从库2)

    -- 配置应用连接用户
    INSERT INTO mysql_users(username, password, default_hostgroup) VALUES
    ('app_user', 'app_password', 10);

    -- 定义读写分离规则
    INSERT INTO mysql_query_rules(rule_id, active, match_digest, destination_hostgroup, apply) VALUES
    (1, 1, '^SELECT.*', 20, 1),
    (2, 1, '.*', 10, 1); -- 一个更简单的规则:匹配SELECT的去读取组,其他所有都去写入组

    -- 加载并保存配置
    LOAD MYSQL SERVERS TO RUNTIME;
    LOAD MYSQL USERS TO RUNTIME;
    LOAD MYSQL QUERY RULES TO RUNTIME;
    SAVE MYSQL SERVERS TO DISK;
    SAVE MYSQL USERS TO DISK;
    SAVE MYSQL QUERY RULES TO DISK;

proxy-sql-web

  • docker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
version: '3.8'

services:
proxysql-web:
# --- 修改点在这里 ---
# 使用一个在 Docker Hub 上公开可用的镜像
image: kishorj/proxysql-web:latest
# ------------------
container_name: proxysql-web
restart: always
ports:
- "8080:80"
environment:
- DB_HOST=192.168.10.158 # 您的 ProxySQL 服务器 IP
- DB_PORT=6032 # ProxySQL 管理端口
- DB_USER=admin # ProxySQL 管理用户名
- DB_PASS=admin # ProxySQL 管理密码
  • run
1
sudo docker-compose up -d

阶段三:切换应用

现在,您的整个高可用集群已经在 Docker 中运行起来了。最后一步就是将您所有200多台电脑上的应用程序的数据库连接配置,指向 ProxySQL 容器暴露的端口。

  • Host: 运行 Docker 的那台服务器的 IP 地址。
  • Port: 6033
  • User: app_user
  • Password: app_password

优点总结

  • 环境一致性:无论部署到哪台机器,整个集群的环境都是完全一致的。
  • 快速部署与销毁:使用 docker-compose up -ddocker-compose down -v 可以秒级创建和彻底销毁整套环境,非常适合测试和开发。
  • 简化管理:服务之间的网络和依赖关系由 Docker Compose 管理,比手动配置网络和防火墙简单得多。
  • 资源隔离:每个服务都在自己的容器中运行,互不干扰。

这个 Docker 化的方案为您提供了一个可移植、可复现、高度自动化的方式来部署和管理您的MySQL读写分离集群。

Next:
使用Devpi与Nginx构建高可用PyPI镜像源