数据库读写分离高并发外贸站点完整方案
外贸站点高并发扛不住?数据库读写分离完整部署方案(零基础版)
做外贸独立站的站长应该都有体会:一到促销或者流量高峰,网站加载慢、数据库连接超时、订单无法提交。
这些问题背后的根因往往是数据库读写压力过大。数据库读写分离就是把你网站里的“读请求”(浏览商品、查看订单)和“写请求”(下单、评论)分散到不同的数据库服务器上,让主库专心写,从库分担读,从而扛住高并发。
今天这篇文章就手把手教你从零部署一套完整方案,使用 MySQL 主从复制 + ProxySQL 实现读写分离,全程不依赖任何面板插件,适合所有 VPS 或云服务器。
为什么外贸站点必须做读写分离?
外贸站点面向全球用户,访问量随时可能从几十人飙到几千人。
如果所有读写都压在同一台 MySQL 上,数据库很快会成为瓶颈。
读写分离的好处非常直接:
- 主库只处理写操作(INSERT/UPDATE/DELETE),压力骤降;
- 从库负责所有查询(SELECT),能水平扩展(增加更多从库);
- 组合效果:网站响应速度提升 3-5 倍,订单不丢失。
这套方案不依赖阿里云 RDS 等付费服务,使用开源工具,成本可控。
下面开始动手。
准备工作:你需要这些东西
- 两台或以上服务器(可以是 VPS 或本地虚拟机),一台做主库(Master),一台做从库(Slave)。系统建议 CentOS 7/8 或 Ubuntu 20.04。
- 服务器之间网络互通,并保证 3306、6032、6033 等端口开放(防火墙和安全组)。
- MySQL 已安装(版本 5.7 或 8.0 均可)。如果还没安装,用以下命令快速安装(以 CentOS 为例):
yum install -y mysql-server
systemctl start mysqld
systemctl enable mysqld
- 远程连接工具(如 Navicat 或命令行)和 root 权限。
第一步:搭建 MySQL 主从复制
主从复制是读写分离的基础。
先配置主库,再配置从库。
配置主库(Master)
- 编辑 MySQL 配置文件
/etc/my.cnf(或/etc/mysql/mysql.conf.d/mysqld.cnf),在[mysqld]段添加:
server-id = 1
log_bin = mysql-bin
binlog_do_db = yourdb # 要同步的数据库名,可以写多个,空格分隔
- 重启 MySQL:
systemctl restart mysqld。 - 登录 MySQL 创建用于复制的用户(替换
your_password):
CREATE USER 'repl'@'%' IDENTIFIED BY 'your_password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
- 查看主库状态,记录
File和Position:
SHOW MASTER STATUS;
配置从库(Slave)
- 在从库的
/etc/my.cnf中添加:
server-id = 2
relay-log = relay-bin
read_only = 1
- 重启从库 MySQL。
- 登录从库 MySQL,执行以下命令(替换
MASTER_LOG_FILE和MASTER_LOG_POS为主库状态值):
CHANGE MASTER TO
MASTER_HOST='主库IP',
MASTER_USER='repl',
MASTER_PASSWORD='your_password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
START SLAVE;
- 检查从库状态:
SHOW SLAVE STATUS\G。看到Slave_IO_Running: Yes和Slave_SQL_Running: Yes表示主从正常。
第二步:安装并配置 ProxySQL 实现读写分离
ProxySQL 是一个高性能的数据库代理,接收应用发来的 SQL 请求,自动把读请求转发给从库,写请求转发给主库。
安装 ProxySQL
推荐直接从官方仓库安装(以 CentOS 为例):
cat > /etc/yum.repos.d/proxysql.repo <
安装后,ProxySQL 的默认管理端口是 6032(用于配置),数据库端口是 6033(应用连接)。
配置 ProxySQL
- 使用 MySQL 客户端连接到 ProxySQL 管理端口(密码默认为空):
mysql -u admin -p -h 127.0.0.1 -P 6032
- 添加你的 MySQL 主从服务器到 ProxySQL 后端:
INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES (0, '主库IP', 3306);
INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES (1, '从库IP', 3306);
hostgroup_id 0 代表写组(主库),hostgroup_id 1 代表读组(从库)。
- 设置读写分离规则:将
SELECT语句路由到读组,其他语句路由到写组:
INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply) VALUES (1, 1, '^SELECT', 1, 1);
INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply) VALUES (2, 1, '.*', 0, 1);
注意:如果你的查询使用了 SELECT ... FOR UPDATE(锁行),它属于写操作,需要单独添加规则,或者调整优先级。
新手可以先保持简单,后续再细化。
- 配置监控用户(ProxySQL 需要登录后端库检查健康状态):
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';
这个用户需要在主库和从库上创建并授予权限(例如 CREATE USER 'monitor'@'%' IDENTIFIED BY 'xxx'; GRANT USAGE ON *.* TO 'monitor'@'%';)。
- 加载配置并持久化:
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
第三步:验证读写分离是否生效
- 让你的应用连接 ProxySQL 的 6033 端口(而不是直接连接 MySQL 3306)。例如,PHP 连接配置改为:
$host = 'ProxySQL服务器IP';
$port = 6033;
- 重启应用后,在从库上开启通用查询日志,观察是否有 SELECT 请求到来。也可以通过 ProxySQL 的统计表查看:
SELECT * FROM stats_mysql_query_digest;
如果看到读组的命中数大于 0,说明读写分离生效。
- 用
sysbench或简单脚测试压力:搭配多个并发请求,观察主库写负载和从库读负载是否分离。
常见的坑与解决方案
- 主从延迟导致读到旧数据:外贸站点有些即时性要求高的页面(如库存查询)可以从主库读。你可以在规则中灵活加例外,例如用注释
/* read_from_master */ SELECT ...来绕过。 - 事务内的读必须走主库:ProxySQL 默认无法感知事务上下文。可以在应用层对事务内所有 SQL 强制使用主库连接,或者升级到 ProxySQL 企业版支持事务绑定。
- 连接池耗尽:ProxySQL 本身有连接池,默认最大连接数 1000,根据你的并发调整:
UPDATE global_variables SET variable_value='2000' WHERE variable_name='mysql-max_connections'; - 忘记放行 ProxySQL 管理端口:安全组需要放行 6032(管理)、6033(代理)、以及后端 MySQL 的 3306 端口。
总结
读写分离并不复杂,关键是按步骤来。
我们先打通主从复制,再通过 ProxySQL 把流量分成读和写两个通道。
这套方案跑通后,你的外贸站点就能轻松应对平时几十倍甚至上百倍的流量。
如果并发需求更高,还可以继续增加从库(在 ProxySQL 的读组中添加新服务器),真正做到水平扩展。
如果你后续遇到主从延迟、事务一致性等问题,本博后续还会出进阶调优教程。
建议先按本文步骤完整部署,遇到报错先检查网络、端口和 MySQL 日志,一般都能解决。