单机MySQL在业务量增长后,很容易碰到写入吞吐到顶、读查询阻塞写入、连接数居高不下的问题。把这些压力拆开,比较直接的做法是让多个MySQL节点组成集群,各自分担一部分职责。本文会从主从复制和组复制两条路线出发,给出完整的配置代码和启动命令,同时把搭建过程中容易忽略的细节标注清楚,方便你直接在三台Linux主机上复现。

一、主从复制与组复制怎么选
主从复制是MySQL最经典的集群化方式。主库把数据变更写入二进制日志,从库通过IO线程把日志拉取到本地,再由SQL线程回放,最终形成一份数据副本。这种方案结构简单,运维成本低,加上ProxySQL这类中间件就能实现读写分离,把大量SELECT请求导到从库。但它也有明显短板:异步复制存在数据延迟,主库突然宕机时可能丢失一小部分已提交事务;即使配置半同步复制,也只是缩小丢失窗口,无法做到零丢失。故障切换通常需要人工介入,把从库提升为主库,再修改应用连接地址,中间过程容易出错。
组复制(Group Replication)则更适合对数据一致性和高可用有强烈要求的场景。它基于Paxos协议在节点之间做状态机复制,事务提交前必须得到多数派节点的确认,所以不会出现主库崩溃后已提交事务丢失的情况。单主模式下,组复制会自动选主,主节点故障后剩余节点可以在几秒内选出新主,应用侧无需手工改地址。代价是配置更复杂,并且对节点间网络质量要求更高,最好部署在同一个低延迟内网中。
如果业务读多写少、对秒级切换不敏感,主从复制完全够用;如果核心交易不能接受数据丢失,或者希望减少人工干预,组复制是更合适的选择。下文会分别演示两套方案的完整搭建步骤。
二、环境准备:三台主机与MySQL安装
集群节点应尽量使用相同版本的MySQL和相近的硬件配置,否则容易出现复制延迟或选主不稳定。本文假设三台主机IP分别为192.168.10.11、192.168.10.12、192.168.10.13,主机名对应node1、node2、node3。操作系统以CentOS 7为例,先关闭防火墙和SELinux,避免后续节点间通信被拦截。
# 每台节点执行 systemctl stop firewalld && systemctl disable firewalld setenforce 0 sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
接下来安装MySQL 8.0。可以通过官方Yum仓库安装,也可以直接使用二进制包。安装完成后启动服务,首次启动会生成一个临时root密码,通过mysql_secure_installation可以修改密码并清理匿名用户。三台节点都需要执行相同操作,确保基础环境一致。
# 添加MySQL官方仓库 rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm # 安装MySQL服务 yum install mysql-community-server -y # 启动并设置开机自启 systemctl start mysqld && systemctl enable mysqld # 查看临时密码 grep 'temporary password' /var/log/mysqld.log
基础配置中最重要的一点是给每个节点设置不同的server-id,否则主从复制或组复制会直接报错。二进制日志也必须开启,因为两种方案都依赖binlog。可以将以下配置写入/etc/my.cnf的[mysqld]段落,并根据节点IP调整server-id和report_host。
[mysqld] server-id=1 log_bin=mysql-bin binlog_format=ROW gtid_mode=ON enforce_gtid_consistency=ON binlog_checksum=NONE report_host=192.168.10.11
node2和node3的server-id分别改成2和3,report_host也要对应修改。修改完重启MySQL使配置生效。到这里,三台节点的基础环境就准备好了。
三、主从复制集群搭建:完整代码步骤
主从复制的配置从主库开始。主库需要创建专用复制账号,该账号只需要REPLICATION SLAVE权限,不建议直接使用root。如果计划使用GTID模式,从库可以自动定位日志位置,避免手动记录file和position带来的错误。创建账号的SQL如下。
-- 在主库执行 CREATE USER 'repl'@'%' IDENTIFIED BY 'Repl@123456'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; FLUSH PRIVILEGES;
接下来配置从库。从库需要指定主库的连接信息。如果使用MySQL 8.0.23以上版本,推荐使用CHANGE REPLICATION SOURCE TO命令;旧版本使用CHANGE MASTER TO。GTID模式下无需指定二进制日志文件和位置,MySQL会自动协商。执行完成后启动复制线程并检查状态。
-- 在从库执行,MySQL 8.0.23以上 CHANGE REPLICATION SOURCE TO SOURCE_HOST='192.168.10.11', SOURCE_USER='repl', SOURCE_PASSWORD='Repl@123456', SOURCE_AUTO_POSITION=1; START REPLICA;
复制是否正常,可以通过SHOW REPLICA STATUS查看。重点看两个字段:Replica_IO_Running和Replica_SQL_Running都为Yes,Seconds_Behind_Source为0或很小的值,说明复制没有延迟。如果IO线程报错,先检查网络连通性、复制账号密码以及主库的bind_address是否监听在对外网卡上。
主从复制搭建完成后,还可以增加多个从库,只需重复从库配置并修改server-id即可。这种一主多从结构配合ProxySQL或读写分离中间件,可以把查询请求均匀分到多个从库。但要注意,从库数据存在延迟,对于强一致业务需要显式指定读主库,否则可能读到旧数据。
四、Group Replication集群搭建:代码步骤
组复制需要在主从复制配置的基础上,额外加载group_replication插件并设置通信地址。三台节点在安装MySQL 8.0时已经内置该插件,不需要单独下载。先在每台节点的配置文件中加入组复制参数,其中group_replication_local_address使用本机IP加33061端口,group_replication_group_seeds列出所有节点的通信地址。group_replication_group_name是一个UUID,三台节点必须完全一致,可以使用uuidgen命令生成。
[mysqld] plugin_load_add='group_replication.so' group_replication_group_name='aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' group_replication_start_on_boot=OFF group_replication_local_address='192.168.10.11:33061' group_replication_group_seeds='192.168.10.11:33061,192.168.10.12:33061,192.168.10.13:33061' group_replication_bootstrap_group=OFF group_replication_single_primary_mode=ON group_replication_enforce_update_everywhere_checks=OFF
节点加入组复制前,还需要创建用于组复制的账号。该账号需要具备REPLICATION SLAVE权限,并且需要在每个节点上执行,因为组复制节点之间的连接也依赖此账号。MySQL 8.0默认会使用caching_sha2_password插件,如果网络中有中间设备不支持,可以改为mysql_native_password。下面的SQL在每个节点执行,创建账号并授权。
SET SQL_LOG_BIN=0; CREATE USER 'repl'@'%' IDENTIFIED BY 'Repl@123456'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; SET SQL_LOG_BIN=1;
所有节点配置完成后,先启动第一个节点作为引导节点。引导节点的group_replication_bootstrap_group需要临时开启,等集群建立后再关闭。执行下面的SQL,然后查看成员状态,确认只有自己在线。
-- 仅在第一个节点执行 SET GLOBAL group_replication_bootstrap_group=ON; START GROUP_REPLICATION; SET GLOBAL group_replication_bootstrap_group=OFF; SELECT * FROM performance_schema.replication_group_members;
第二个和第三个节点直接执行START GROUP_REPLICATION即可,它们会通过种子列表找到现有集群并加入。如果加入失败,最常见的错误是白名单未放通,需要设置group_replication_ip_whitelist或group_replication_ip_allowlist参数,允许内网网段通信。加入完成后,再次查询replication_group_members,应该看到三行记录,状态均为ONLINE。
五、验证集群与故障切换
集群建成后,首要任务是验证数据同步和故障切换能力。对于主从复制,可以在主库写入测试数据,然后在从库查询。注意使用普通SELECT时,从库可能读到旧值,可打开只读模式防止误写。主从方案下如果主库宕机,需要手动执行提升操作,例如在从库执行STOP REPLICA和RESET REPLICA ALL,然后将应用指向该节点。这个过程容易出错,建议提前准备切换脚本。
组复制则具备自动切换能力。模拟主节点故障可以使用kill -9命令直接杀掉mysqld进程,或者在主节点执行STOP GROUP_REPLICATION。等待几秒后,在剩余节点查询成员状态,可以看到某个节点成为新的PRIMARY。组复制单主模式下,非主节点默认只读,应用侧可以通过内置的mysqlrouter或选择支持组复制的客户端来自动识别主库。
# 在主节点模拟宕机 kill -9 $(pidof mysqld)
切换完成后,执行读写测试确认新主库可以正常写入。组复制要求每次事务提交都经过多数派确认,因此恢复后的旧主节点重新加入集群时,需要先从当前主库获取缺失数据。可以通过执行START GROUP_REPLICATION让它自动追赶,不需要手动复制数据。如果节点长时间离线,建议先删除数据目录并重新初始化,否则增量日志可能已经清理。
上线前还需要关注性能参数。不管是主从复制还是组复制,都建议开启半同步复制降低数据丢失风险,但组复制已经内置了事务确认机制,不必额外配置。读写分离场景下,可以用ProxySQL或MySQL Router统一入口,并在连接池中设置从库延迟阈值。集群不是终点,配置好监控告警和备份策略,才能让优化过程形成闭环。

