MySQL PXC 高可用架构详解
1. PXC 是什么?
Percona XtraDB Cluster(简称 PXC) 是基于 Galera 协议的 MySQL 高可用集群解决方案。它由著名的 MySQL 服务与工具提供商 Percona 实现,核心是通过 Galera 复制插件 实现多节点间的 数据强一致性同步 。
PXC 属于 多主(Multi-Master)架构 ,集群中的每个节点都是对等的,不存在主从之分。客户端可以读写任意节点,写入的数据会自动同步到其他所有节点,从而实现 真正的多点读写 和高可用 。
注意:MariaDB 也有基于 Galera 的实现(MariaDB Galera Cluster),两者底层原理一致 。
2. 为什么需要 PXC?
传统的 MySQL 主从复制(Replication)存在以下痛点:
- 异步复制导致的数据延迟:主库写入成功即返回,从库可能存在秒级甚至更高的延迟。
- 数据一致性问题:主库宕机时,未同步到从库的数据可能丢失。
- 写扩展困难:只能在主库写入,写能力受限于单机性能。
PXC 正是为了解决这些问题而生的,它提供了 强一致性、多主写入、自动故障切换 的高可用能力 。
| 对比项 | PXC | 传统主从复制(Replication) |
|---|---|---|
| 数据同步 | 同步复制(实时,强一致) | 异步/半同步(有延迟,最终一致) |
| 读写能力 | 所有节点均可读写 | 主库写,从库读 |
| 故障切换 | 自动,节点对等,无需人工干预 | 需借助 MHA/Keepalived 等工具 |
| 数据丢失 | 零丢失(事务在所有节点提交才返回成功) | 可能丢失未同步的数据 |
| 扩展性 | 扩展读和写(但写受限于全局验证) | 扩展读,写无法扩展 |
3. PXC 核心原理与工作模式
3.1 数据同步机制(同步复制)
PXC 的数据同步严格遵循 两阶段提交(2PC)变体 的思想,核心流程如下 :
- 本地执行:客户端向节点 A 发起写事务,节点 A 在本地执行 SQL。
- 广播写集 :事务提交前,节点 A 将事务产生的 写集(Write-Set,即变更的行记录) 广播给集群中所有其他节点。
- 全局验证 :其他节点收到写集后,进行 冲突检测,验证是否与其他并发事务冲突。
- 同步提交 :
- 如果所有节点验证通过,则同时提交事务,节点 A 返回成功给客户端。
- 只要有一个节点验证失败(如主键冲突),则整个事务回滚。
关键结论 :PXC 保证了 强一致性(Strong Consistency)------一个事务要么在所有节点都成功,要么都不成功 。
3.2 节点状态流转
PXC 节点在启动、运行、故障过程中会经历不同的状态 :
- OPEN:节点启动,尝试连接集群。
- PRIMARY:集群正常组件状态(通常指已形成法定人数的集群)。
- JOINER:新节点加入,正在等待接收数据。
- DONOR:数据贡献者,正在为 JOINER 节点提供全量或增量数据。
- JOINED:节点已完成数据同步,正在追赶集群进度。
- SYNCED :正常工作状态,数据与集群完全同步,可对外提供服务。
3.3 数据传输方式(SST vs IST)
当新节点加入或故障节点恢复时,需要同步数据,PXC 提供两种传输方式 :
- SST(State Snapshot Transfer)- 全量同步 :
- 方式:
mysqldump、rsync、xtrabackup。 - 场景:新节点数据落后太多,无法通过增量补齐。
- 缺点:速度慢,DONOR 节点在传输期间可能因锁表而阻塞写操作(使用 xtrabackup 可避免锁表)。
- 方式:
- IST(Incremental State Transfer)- 增量同步 :
- 方式:依赖 DONOR 节点的 GCache 缓存。
- 场景:节点短暂离线后重新加入,且落后数据量在 GCache 范围内。
- 优点:速度快,对集群影响极小。
3.4 流控机制(Flow Control)
为了保证数据一致性和节点间延迟可控,PXC 实施了 流控机制 。当某个节点处理事务速度过慢(如硬件性能差、网络抖动),导致待应用的写集队列过长时,集群会 主动限制所有节点的写入速度 ,以等待慢节点追上。这就是所谓的 "短板效应" 。
4. PXC 的优缺点分析
优点
- 强一致性:数据零丢失,适合金融、账务等核心系统 。
- 多主读写:支持在任意节点写入,避免了传统主从的写热点问题。
- 高可用性:无单点故障,任意节点宕机(只要存活节点数 ≥ 法定人数),集群自动重组,应用透明切换 。
- 自动节点克隆:新节点加入时无需人工备份,自动完成数据同步 。
缺点与使用限制(重要!)
- 写入性能受限 :受限于 流控机制 和 全局验证,PXC 的写性能通常低于传统主从架构,不适合超高并发写入场景 。
- 存储引擎限制 :仅支持 InnoDB 引擎。MyISAM 等引擎的表数据无法同步 。
- 表结构限制 :每张表必须有主键,否则无法进行冲突检测和同步。
- 热点更新问题 :多个节点同时更新同一行数据时,容易引发 死锁和冲突回滚。
- 写放大:所有写操作都会在集群所有节点上执行一遍,磁盘 IO 压力较大。
- DDL 操作风险 :执行
ALTER TABLE等 DDL 会阻塞整个集群的写入(建议使用pt-online-schema-change工具)。
5. 典型部署架构与关键配置
5.1 最小部署建议
- 节点数量 :至少 3 个节点 。
- 2 个节点容易发生 脑裂(Split-Brain),无法保证服务可用。
- 3 个节点可以容忍 1 个节点宕机;5 个节点可容忍 2 个节点宕机。
- 网络要求:低延迟、高带宽网络。建议万兆网卡,跨机房部署需评估网络延迟。
5.2 关键配置参数示例
ini
[mysqld]
# 基础设置
binlog_format=ROW # 必须设置为ROW格式
default-storage-engine=innodb # 必须使用InnoDB
innodb_autoinc_lock_mode=2 # 自增锁模式,避免自增ID冲突
# Galera 核心配置
wsrep_on=ON
wsrep_provider=/usr/lib/galera3/libgalera_smm.so
wsrep_cluster_name="pxc-cluster-demo"
wsrep_cluster_address="gcomm://192.168.1.10,192.168.1.11,192.168.1.12"
wsrep_node_name="pxc-node-1"
wsrep_node_address="192.168.1.10"
# SST 同步方式(推荐 xtrabackup,不锁表)
wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth="sst_user:password"
# GCache 优化(缓存写集用于增量同步)
wsrep_provider_options="gcache.size=2G; gcache.mem_size=256M"
5.3 关键端口
| 端口 | 用途 | 说明 |
|---|---|---|
| 3306 | 数据库服务 | 客户端连接与 SQL 执行 |
| 4567 | 集群内部通信 | 写集广播与节点间沟通 |
| 4568 | IST 增量传输 | 增量数据同步 |
| 4444 | SST 全量传输 | 全量数据同步 |
6. PXC 适用场景
- 读多写少的高价值业务:如用户中心、订单查询、金融交易记录等,对数据一致性要求极高。
- 多活数据中心探索:虽不建议跨广域网(延迟太高),但在同城低延迟机房可实现双活/多活。
- 替代传统主从 + MHA:希望简化运维,不再需要手动切主,且需要多节点分担写压力的场景。
7. 总结
| 维度 | 评价 |
|---|---|
| 数据安全 | ⭐⭐⭐⭐⭐(零丢失,强一致) |
| 高可用性 | ⭐⭐⭐⭐⭐(自动切换,透明运维) |
| 写入性能 | ⭐⭐(受限于慢节点和流控) |
| 运维复杂度 | ⭐⭐⭐(需理解流控、SST/IST 机制) |
一句话总结:PXC 牺牲了部分写入性能,换取了数据的绝对安全和架构的极度高可用,是 MySQL 生态中强一致性集群的代表方案之一。
8. 实战
1、环境准备
| 主机名 | IP | 端口 |
|---|---|---|
| pxc1 | 192.168.194.11 | 3306 |
| pxc2 | 192.168.194.12 | 3306 |
| pxc3 | 192.168.194.13 | 3306 |
这是一套标准的 三节点 PXC 集群规划,符合最小部署要求(≥ 3 个节点),可以容忍 1 个节点宕机。
设置主机名
powershell
hostnamectl set-hostname pxc1 && bash
hostnamectl set-hostname pxc2 && bash
hostnamectl set-hostname pxc3 && bash
配置IP
powershell
nmcli c m ens160 ipv4.method manual ipv4.addr 192.168.194.11/24 ipv4.gateway 192.168.194.2 ipv4.dns 223.5.5.5 connection.autoconnect yes
nmcli c up ens160
nmcli c m ens160 ipv4.method manual ipv4.addr 192.168.194.12/24 ipv4.gateway 192.168.194.2 ipv4.dns 223.5.5.5 connection.autoconnect yes
nmcli c up ens160
nmcli c m ens160 ipv4.method manual ipv4.addr 192.168.194.13/24 ipv4.gateway 192.168.194.2 ipv4.dns 223.5.5.5 connection.autoconnect yes
nmcli c up ens160
配置hosts解析,每个节点
powershell
cat >> /etc/hosts << EOF
192.168.194.11 pxc1
192.168.194.12 pxc2
192.168.194.13 pxc3
EOF
为了传输文件方便,可以第一个节点(pxc1)上配置免密登录
powershell
[root@pxc1 ~]# ssh-keygen -t rsa
[root@pxc1 ~]# ssh-copy-id pxc2
[root@pxc1 ~]# ssh-copy-id pxc3
如果是 Redhat 10.x 系统,默认情况下没有 openssl 模块,需要提前安装,否则会导致节点添加不成功。
powershell
dnf install openssl -y
2、安装PXC
RHEL 9 及后续版本使用 dnf 包管理器及其模块系统。必须禁用默认的 mysql 模块,以避免与Percona 的包发生冲突。注意,需要在所有节点上执行。
powershell
dnf module disable mysql -y
2.1 离线安装
所有节点都需要安装
安装 PXC 里面集成了 Percona Server 数据库,所以不需要安装 Percona Server 数据库。
PXC包下载:https://repo.percona.com/pxc-84-lts/yum/release/9/RPMS/x86_64/
telemetry包下载:https://repo.percona.com/telemetry/yum/release/
PXB包下载:https://repo.percona.com/pxb-84-lts/yum/release/9/RPMS/x86_64/
最后上传到服务器
powershell
[root@pxc1 ~]# ls *.rpm
percona-telemetry-agent-1.0.9-1.el10.x86_64.rpm
percona-xtradb-cluster-8.4.7-7.1.el10.x86_64.rpm
percona-xtradb-cluster-client-8.4.7-7.1.el10.x86_64.rpm
percona-xtradb-cluster-icu-data-files-8.4.7-7.1.el10.x86_64.rpm
percona-xtradb-cluster-server-8.4.7-7.1.el10.x86_64.rpm
percona-xtradb-cluster-shared-8.4.7-7.1.el10.x86_64.rpm
qpress-11-4.el10.x86_64.rpm
执行安装命令
powershell
dnf localinstall *.rpm -y
2.2 在线安装
powershell
dnf install https://repo.percona.com/yum/percona-release-latest.noarch.rpm -y
percona-release setup pxc-84-lts
dnf install percona-xtradb-cluster -y
安装好后启动数据库(systemctl start mysqld)或者重启服务后再执行(systemctl stop mysqld)。
如果后续有需要,可安装 percona-xtrabackup
powershell
percona-release enable pxb-84-lts
dnf install percona-xtrabackup-84 -y
ℹ️ Note
如果是 Redhat 10.x 版本,默认没有安装 openssl 模块,会导致数据同步不成功,因此需要在所有节点上安装 openssl 模块。
powershell
# 如果是 Redhat 10.x 版本,默认没有安装 openssl 模块,会导致数据同步不成功,因此需要在所有节点上安装 openssl 模块。
dnf install openssl -y
2.3 启动数据库
powershell
systemctl start mysqld
3、配置 PXC
所有节点都安装好 PXC 环境后,需要修改 /etc/my.cnf 文件。
3.1 pxc1节点配置如下
powershell
[client]
socket=/var/lib/mysql/mysql.sock
[mysqld]
server-id=11 # 配置节点标记,集群唯一
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
binlog_expire_logs_seconds=604800
wsrep_provider=/usr/lib64/galera4/libgalera_smm.so
wsrep_cluster_name=pxc-cluster # 集群名称,所有节点相同
wsrep_cluster_address=gcomm://192.168.194.11,192.168.194.12,192.168.194.13 # 所有节点地址,所有节点相同
binlog_format=ROW
wsrep_slave_threads=8
wsrep_log_conflicts
innodb_autoinc_lock_mode=2
wsrep_provider_options="socket.ssl=no" # 如果是Redhat 9.x版本,添加此项配置
wsrep_node_address=192.168.194.11 # 当前节点地址
wsrep_node_name=pxc1 # 当前节点名称
pxc_strict_mode=ENFORCING
wsrep_sst_method=xtrabackup-v2
# 如果是Redhat 10.x,添加如下配置,并且所有节点相同
[sst]
encrypt=4
ssl-ca=/var/lib/mysql/ca.pem
ssl-cert=/var/lib/mysql/server-cert.pem
ssl-key=/var/lib/mysql/server-key.pem
3.2 pxc2节点配置如下
powershell
[mysqld]
server-id=12
wsrep_node_address=192.168.194.12
wsrep_node_name=pxc2
3.3 pxc3节点配置如下
powershell
[mysqld]
server-id=13
wsrep_node_address=192.168.194.13
wsrep_node_name=pxc3
4、启动 pxc1
配置完所有 PXC 节点后,通过引导第一个节点来初始化集群,初始节点必须包含所有希望复制到其他节点的数据。
引导意味着在没有任何已知集群地址的情况下启动第一个节点:如果 wsrep_cluster_address 变量为空,则 Percona XtraDB Cloud 会假设这是第一个节点并初始化集群。
不要更改配置,而是使用以下命令启动第一个节点:
powershell
[root@pxc1 ~]# systemctl start mysql@bootstrap.service
使用上述命令启动节点时,该节点将以引导模式运行,且 wsrep_cluster_address 设置为gcomm://。这会告诉节点使用设置为 1 的wsrep_cluster_conf_id 变量来初始化集群。在向集群添加其他节点后,您可以像往常一样重新启动此节点,它将再次使用标准配置。
启动成功后,执行如下命令获取初始密码:
powershell
[root@pxc1 ~]# grep -i password /var/log/mysqld.log
2026-04-18T06:55:01.554065Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: jThuN5(aZ30s
[root@pxc1 ~]# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.4.7-7.1
Copyright (c) 2009-2025 Percona LLC and/or its affiliates
Copyright (c) 2000, 2025, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
登录成功后再执行如下命令修改登录密码:
powershell
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'MySQL@123';
Query OK, 0 rows affected (0.01 sec)
# 查看集群的状态
mysql> SHOW STATUS LIKE 'wsrep%';
+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value |
+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
| wsrep_local_state_uuid | 881f52a2-3af3-11f1-b44d-b608ce7e87d4 |
| wsrep_protocol_version | 11 |
| wsrep_last_applied | 2 |
| wsrep_protocol_application | 4 |
| wsrep_protocol_replicator | 11 |
| wsrep_protocol_GCS | 5 |
| wsrep_last_committed | 2 |
| wsrep_monitor_status (L/A/C) | [ (2, 2), (2, 2), (2, 2) ] |
| wsrep_replicated | 0 |
| wsrep_replicated_bytes | 0 |
| wsrep_repl_keys | 0 |
| wsrep_repl_keys_bytes | 0 |
| wsrep_repl_data_bytes | 0 |
| wsrep_repl_other_bytes | 0 |
| wsrep_received | 2 |
| wsrep_received_bytes | 144 |
| wsrep_local_commits | 0 |
| wsrep_local_cert_failures | 0 |
| wsrep_local_replays | 0 |
| wsrep_local_send_queue | 0 |
| wsrep_local_send_queue_max | 1 |
| wsrep_local_send_queue_min | 0 |
| wsrep_local_send_queue_avg | 0 |
| wsrep_local_recv_queue | 0 |
| wsrep_local_recv_queue_max | 2 |
| wsrep_local_recv_queue_min | 0 |
| wsrep_local_recv_queue_avg | 0.5 |
| wsrep_local_cached_downto | 1 |
| wsrep_flow_control_paused_ns | 0 |
| wsrep_flow_control_paused | 0 |
| wsrep_flow_control_sent | 0 |
| wsrep_flow_control_recv | 0 |
| wsrep_flow_control_active | false |
| wsrep_flow_control_requested | false |
| wsrep_flow_control_interval | [ 100, 100 ] |
| wsrep_flow_control_interval_low | 100 |
| wsrep_flow_control_interval_high | 100 |
| wsrep_flow_control_status | OFF |
| wsrep_cert_deps_distance | 0 |
| wsrep_apply_oooe | 0 |
| wsrep_apply_oool | 0 |
| wsrep_apply_window | 0 |
| wsrep_apply_waits | 0 |
| wsrep_commit_oooe | 0 |
| wsrep_commit_oool | 0 |
| wsrep_commit_window | 0 |
| wsrep_local_state | 4 |
| wsrep_local_state_comment | Synced |
| wsrep_cert_index_size | 0 |
| wsrep_cert_bucket_count | 1 |
| wsrep_gcache_pool_size | 1640 |
| wsrep_causal_reads | 0 |
| wsrep_cert_interval | 0 |
| wsrep_open_transactions | 0 |
| wsrep_open_connections | 0 |
| wsrep_ist_receive_status | |
| wsrep_ist_receive_seqno_start | 0 |
| wsrep_ist_receive_seqno_current | 0 |
| wsrep_ist_receive_seqno_end | 0 |
| wsrep_incoming_addresses | 192.168.194.11:3306 |
| wsrep_cluster_weight | 1 |
| wsrep_desync_count | 0 |
| wsrep_evs_delayed | |
| wsrep_evs_evict_list | |
| wsrep_evs_repl_latency | 0/0/0/0/0 |
| wsrep_evs_state | OPERATIONAL |
| wsrep_gcomm_uuid | b0322763-3b22-11f1-b2b5-9a4ba6ca9026 |
| wsrep_gmcast_segment | 0 |
| wsrep_cluster_capabilities | |
| wsrep_cluster_conf_id | 1 |
| wsrep_cluster_size | 1 |
| wsrep_cluster_state_uuid | 881f52a2-3af3-11f1-b44d-b608ce7e87d4 |
| wsrep_cluster_status | Primary |
| wsrep_connected | ON |
| wsrep_local_bf_aborts | 0 |
| wsrep_local_index | 0 |
| wsrep_provider_capabilities | :MULTI_MASTER:CERTIFICATION:PARALLEL_APPLYING:TRX_REPLAY:ISOLATION:PAUSE:CAUSAL_READS:INCREMENTAL_WRITESET:UNORDERED:PREORDERED:STREAMING:NBO: |
| wsrep_provider_name | Galera |
| wsrep_provider_vendor | Codership Oy <info@codership.com> (modified by Percona <https://percona.com/>) |
| wsrep_provider_version | 4.24(a430f07) |
| wsrep_ready | ON |
| wsrep_thread_count | 9 |
+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
82 rows in set (0.00 sec)
查看集群节对应的数据
powershell
-- 查看集群的数量
mysql> SHOW STATUS LIKE 'wsrep_cluster_size';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| wsrep_cluster_size | 1 |
+--------------------+-------+
1 row in set (0.00 sec)
-- 查看集群地址
mysql> SHOW STATUS LIKE 'wsrep_incoming_addresses';
+--------------------------+---------------------+
| Variable_name | Value |
+--------------------------+---------------------+
| wsrep_incoming_addresses | 192.168.194.11:3306 |
+--------------------------+---------------------+
1 row in set (0.00 sec)
-- 通过视图查看工具监控同步状态
mysql> SELECT * FROM performance_schema.pxc_cluster_view;
+-----------+--------------------------------------+--------+-------------+---------+
| HOST_NAME | UUID | STATUS | LOCAL_INDEX | SEGMENT |
+-----------+--------------------------------------+--------+-------------+---------+
| pxc1 | b0322763-3b22-11f1-b2b5-9a4ba6ca9026 | SYNCED | 0 | 0 |
+-----------+--------------------------------------+--------+-------------+---------+
1 row in set (0.01 sec)
-- 检查数据库集群状态
mysql> SHOW STATUS WHERE Variable_name IN ('wsrep_cluster_size','wsrep_cluster_status','wsrep_connected','wsrep_ready');
+----------------------+---------+
| Variable_name | Value |
+----------------------+---------+
| wsrep_cluster_size | 1 |
| wsrep_cluster_status | Primary |
| wsrep_connected | ON |
| wsrep_ready | ON |
+----------------------+---------+
4 rows in set (0.00 sec)
-- 默认开启加密
mysql> SHOW VARIABLES LIKE 'pxc_encrypt_cluster_traffic';
+-----------------------------+-------+
| Variable_name | Value |
+-----------------------------+-------+
| pxc_encrypt_cluster_traffic | ON |
+-----------------------------+-------+
1 row in set (0.00 sec)
输出结果显示,集群规模为一个节点,该节点为主要组件,处于已同步状态,且已完全连接,可进行写集复制。
5、 配置证书
在 PXC 8.4 版本中,所有节点都要使用相同的密钥和证书,否则无法成功同步数据。
首先删除 pxc2 和 pxc3 数据目录下的所有 pem 文件。
powershell
[root@pxc2 ~]# rm -rf /var/lib/mysql/*.pem
[root@pxc3 ~]# rm -rf /var/lib/mysql/*.pem
然后再将 pxc1 数据目录下的所有 pem 文件复制给 pxc2 和 pxc3,从而保证密钥和证书一致。
powershell
[root@pxc1 ~]# scp /var/lib/mysql/*.pem pxc2:/var/lib/mysql/
[root@pxc1 ~]# scp /var/lib/mysql/*.pem pxc3:/var/lib/mysql/
最后再修改 pxc2 和 pxc3 数据目录下所有 pem 文件权限。
powershell
[root@pxc2 ~]# chown mysql:mysql /var/lib/mysql/*.pem
[root@pxc2 ~]# ll /var/lib/mysql/*.pem
-rw------- 1 mysql mysql 1705 Apr 18 20:42 /var/lib/mysql/ca-key.pem
-rw-r--r-- 1 mysql mysql 1112 Apr 18 20:42 /var/lib/mysql/ca.pem
-rw-r--r-- 1 mysql mysql 1116 Apr 18 20:42 /var/lib/mysql/client-cert.pem
-rw------- 1 mysql mysql 1705 Apr 18 20:42 /var/lib/mysql/client-key.pem
-rw------- 1 mysql mysql 1701 Apr 18 20:42 /var/lib/mysql/private_key.pem
-rw-r--r-- 1 mysql mysql 452 Apr 18 20:42 /var/lib/mysql/public_key.pem
-rw-r--r-- 1 mysql mysql 1116 Apr 18 20:42 /var/lib/mysql/server-cert.pem
-rw------- 1 mysql mysql 1705 Apr 18 20:42 /var/lib/mysql/server-key.pem
[root@pxc3 ~]# chown mysql:mysql /var/lib/mysql/*.pem
[root@pxc3 ~]# ll /var/lib/mysql/*.pem
-rw------- 1 mysql mysql 1705 Apr 18 20:43 /var/lib/mysql/ca-key.pem
-rw-r--r-- 1 mysql mysql 1112 Apr 18 20:43 /var/lib/mysql/ca.pem
-rw-r--r-- 1 mysql mysql 1116 Apr 18 20:43 /var/lib/mysql/client-cert.pem
-rw------- 1 mysql mysql 1705 Apr 18 20:43 /var/lib/mysql/client-key.pem
-rw------- 1 mysql mysql 1701 Apr 18 20:43 /var/lib/mysql/private_key.pem
-rw-r--r-- 1 mysql mysql 452 Apr 18 20:43 /var/lib/mysql/public_key.pem
-rw-r--r-- 1 mysql mysql 1116 Apr 18 20:43 /var/lib/mysql/server-cert.pem
-rw------- 1 mysql mysql 1705 Apr 18 20:43 /var/lib/mysql/server-key.pem
6、启动PXC2
添加第二个节点,请在 [root@pxc2 ~]# 提示符下执行如下命令:
powershell
[root@pxc2 ~]# systemctl start mysql
服务器启动后,会自动接收SST。
要检查第二个节点的状态(mysql@pxc2>),请运行以下命令:
注意此时登录MySQL的密码是MySQL@123
powershell
mysql> SHOW STATUS LIKE 'wsrep%';
+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value |
+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
| wsrep_local_state_uuid | 881f52a2-3af3-11f1-b44d-b608ce7e87d4 |
| wsrep_protocol_version | 11 |
| wsrep_last_applied | 3 |
| wsrep_protocol_application | 4 |
| wsrep_protocol_replicator | 11 |
| wsrep_protocol_GCS | 5 |
| wsrep_last_committed | 3 |
| wsrep_monitor_status (L/A/C) | [ (4, 4), (3, 3), (3, 3) ] |
| wsrep_replicated | 0 |
| wsrep_replicated_bytes | 0 |
| wsrep_repl_keys | 0 |
| wsrep_repl_keys_bytes | 0 |
| wsrep_repl_data_bytes | 0 |
| wsrep_repl_other_bytes | 0 |
| wsrep_received | 3 |
| wsrep_received_bytes | 224 |
| wsrep_local_commits | 0 |
| wsrep_local_cert_failures | 0 |
| wsrep_local_replays | 0 |
| wsrep_local_send_queue | 0 |
| wsrep_local_send_queue_max | 1 |
| wsrep_local_send_queue_min | 0 |
| wsrep_local_send_queue_avg | 0 |
| wsrep_local_recv_queue | 0 |
| wsrep_local_recv_queue_max | 1 |
| wsrep_local_recv_queue_min | 0 |
| wsrep_local_recv_queue_avg | 0 |
| wsrep_local_cached_downto | 3 |
| wsrep_flow_control_paused_ns | 0 |
| wsrep_flow_control_paused | 0 |
| wsrep_flow_control_sent | 0 |
| wsrep_flow_control_recv | 0 |
| wsrep_flow_control_active | false |
| wsrep_flow_control_requested | false |
| wsrep_flow_control_interval | [ 141, 141 ] |
| wsrep_flow_control_interval_low | 141 |
| wsrep_flow_control_interval_high | 141 |
| wsrep_flow_control_status | OFF |
| wsrep_cert_deps_distance | 0 |
| wsrep_apply_oooe | 0 |
| wsrep_apply_oool | 0 |
| wsrep_apply_window | 0 |
| wsrep_apply_waits | 0 |
| wsrep_commit_oooe | 0 |
| wsrep_commit_oool | 0 |
| wsrep_commit_window | 0 |
| wsrep_local_state | 4 |
| wsrep_local_state_comment | Synced |
| wsrep_cert_index_size | 0 |
| wsrep_cert_bucket_count | 1 |
| wsrep_gcache_pool_size | 2136 |
| wsrep_causal_reads | 0 |
| wsrep_cert_interval | 0 |
| wsrep_open_transactions | 0 |
| wsrep_open_connections | 0 |
| wsrep_ist_receive_status | |
| wsrep_ist_receive_seqno_start | 0 |
| wsrep_ist_receive_seqno_current | 0 |
| wsrep_ist_receive_seqno_end | 0 |
| wsrep_incoming_addresses | 192.168.194.11:3306,192.168.194.12:3306 |
| wsrep_cluster_weight | 2 |
| wsrep_desync_count | 0 |
| wsrep_evs_delayed | |
| wsrep_evs_evict_list | |
| wsrep_evs_repl_latency | 0/0/0/0/0 |
| wsrep_evs_state | OPERATIONAL |
| wsrep_gcomm_uuid | fd2418fd-3b24-11f1-840e-aa56b5d5a15e |
| wsrep_gmcast_segment | 0 |
| wsrep_cluster_capabilities | |
| wsrep_cluster_conf_id | 2 |
| wsrep_cluster_size | 2 |
| wsrep_cluster_state_uuid | 881f52a2-3af3-11f1-b44d-b608ce7e87d4 |
| wsrep_cluster_status | Primary |
| wsrep_connected | ON |
| wsrep_local_bf_aborts | 0 |
| wsrep_local_index | 1 |
| wsrep_provider_capabilities | :MULTI_MASTER:CERTIFICATION:PARALLEL_APPLYING:TRX_REPLAY:ISOLATION:PAUSE:CAUSAL_READS:INCREMENTAL_WRITESET:UNORDERED:PREORDERED:STREAMING:NBO: |
| wsrep_provider_name | Galera |
| wsrep_provider_vendor | Codership Oy <info@codership.com> (modified by Percona <https://percona.com/>) |
| wsrep_provider_version | 4.24(a430f07) |
| wsrep_ready | ON |
| wsrep_thread_count | 9 |
+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
82 rows in set (0.01 sec)
SHOW STATUS 的输出显示,新节点已成功添加到集群中。现在集群规模为两个节点,该节点是主组件,已完全连接并准备好接收写集复制。
如果第二个节点的状态如前例所示为" Synced ",则表示该节点已接收到完整的 SST 并与集群同步,此时您可以继续添加下一个节点。

7、启动PXC3
要添加第三个节点,请在 [root@pxc3 ~]# 提示符下,像往常一样启动它:
powershell
[root@pxc3 ~]# systemctl start mysql
要检查第三个节点的状态(mysql@pxc3>),请运行以下命令:
注意此时登录MySQL的密码也是MySQL@123
powershell
mysql> SHOW STATUS LIKE 'wsrep%';
+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value |
+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
| wsrep_local_state_uuid | 881f52a2-3af3-11f1-b44d-b608ce7e87d4 |
| wsrep_protocol_version | 11 |
| wsrep_last_applied | 4 |
| wsrep_protocol_application | 4 |
| wsrep_protocol_replicator | 11 |
| wsrep_protocol_GCS | 5 |
| wsrep_last_committed | 4 |
| wsrep_monitor_status (L/A/C) | [ (4, 4), (4, 4), (4, 4) ] |
| wsrep_replicated | 0 |
| wsrep_replicated_bytes | 0 |
| wsrep_repl_keys | 0 |
| wsrep_repl_keys_bytes | 0 |
| wsrep_repl_data_bytes | 0 |
| wsrep_repl_other_bytes | 0 |
| wsrep_received | 3 |
| wsrep_received_bytes | 296 |
| wsrep_local_commits | 0 |
| wsrep_local_cert_failures | 0 |
| wsrep_local_replays | 0 |
| wsrep_local_send_queue | 0 |
| wsrep_local_send_queue_max | 1 |
| wsrep_local_send_queue_min | 0 |
| wsrep_local_send_queue_avg | 0 |
| wsrep_local_recv_queue | 0 |
| wsrep_local_recv_queue_max | 1 |
| wsrep_local_recv_queue_min | 0 |
| wsrep_local_recv_queue_avg | 0 |
| wsrep_local_cached_downto | 4 |
| wsrep_flow_control_paused_ns | 0 |
| wsrep_flow_control_paused | 0 |
| wsrep_flow_control_sent | 0 |
| wsrep_flow_control_recv | 0 |
| wsrep_flow_control_active | false |
| wsrep_flow_control_requested | false |
| wsrep_flow_control_interval | [ 173, 173 ] |
| wsrep_flow_control_interval_low | 173 |
| wsrep_flow_control_interval_high | 173 |
| wsrep_flow_control_status | OFF |
| wsrep_cert_deps_distance | 0 |
| wsrep_apply_oooe | 0 |
| wsrep_apply_oool | 0 |
| wsrep_apply_window | 0 |
| wsrep_apply_waits | 0 |
| wsrep_commit_oooe | 0 |
| wsrep_commit_oool | 0 |
| wsrep_commit_window | 0 |
| wsrep_local_state | 4 |
| wsrep_local_state_comment | Synced |
| wsrep_cert_index_size | 0 |
| wsrep_cert_bucket_count | 1 |
| wsrep_gcache_pool_size | 2280 |
| wsrep_causal_reads | 0 |
| wsrep_cert_interval | 0 |
| wsrep_open_transactions | 0 |
| wsrep_open_connections | 0 |
| wsrep_ist_receive_status | |
| wsrep_ist_receive_seqno_start | 0 |
| wsrep_ist_receive_seqno_current | 0 |
| wsrep_ist_receive_seqno_end | 0 |
| wsrep_incoming_addresses | 192.168.194.11:3306,192.168.194.13:3306,192.168.194.12:3306 |
| wsrep_cluster_weight | 3 |
| wsrep_desync_count | 0 |
| wsrep_evs_delayed | |
| wsrep_evs_evict_list | |
| wsrep_evs_repl_latency | 0/0/0/0/0 |
| wsrep_evs_state | OPERATIONAL |
| wsrep_gcomm_uuid | d6d0a1cc-3b25-11f1-b184-93f257e02bdf |
| wsrep_gmcast_segment | 0 |
| wsrep_cluster_capabilities | |
| wsrep_cluster_conf_id | 3 |
| wsrep_cluster_size | 3 |
| wsrep_cluster_state_uuid | 881f52a2-3af3-11f1-b44d-b608ce7e87d4 |
| wsrep_cluster_status | Primary |
| wsrep_connected | ON |
| wsrep_local_bf_aborts | 0 |
| wsrep_local_index | 1 |
| wsrep_provider_capabilities | :MULTI_MASTER:CERTIFICATION:PARALLEL_APPLYING:TRX_REPLAY:ISOLATION:PAUSE:CAUSAL_READS:INCREMENTAL_WRITESET:UNORDERED:PREORDERED:STREAMING:NBO: |
| wsrep_provider_name | Galera |
| wsrep_provider_vendor | Codership Oy <info@codership.com> (modified by Percona <https://percona.com/>) |
| wsrep_provider_version | 4.24(a430f07) |
| wsrep_ready | ON |
| wsrep_thread_count | 9 |
+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+
82 rows in set (0.01 sec)

输出结果显示,新节点已成功添加到集群中。现在集群规模为三个节点;该节点是主要组件,已完全连接并准备好接收写集复制。
可通过视图 performance_schema.pxc_cluster_view、dstat 工具监控同步状态。
powershell
mysql> select * from performance_schema.pxc_cluster_view;
+-----------+--------------------------------------+--------+-------------+---------+
| HOST_NAME | UUID | STATUS | LOCAL_INDEX | SEGMENT |
+-----------+--------------------------------------+--------+-------------+---------+
| pxc1 | b0322763-3b22-11f1-b2b5-9a4ba6ca9026 | SYNCED | 0 | 0 |
| pxc3 | d6d0a1cc-3b25-11f1-b184-93f257e02bdf | SYNCED | 1 | 0 |
| pxc2 | fd2418fd-3b24-11f1-840e-aa56b5d5a15e | SYNCED | 2 | 0 |
+-----------+--------------------------------------+--------+-------------+---------+
3 rows in set (0.00 sec)
查看 PXC 集群状态信息,在任意一个节点执行以下命令:
powershell
mysql> show status like 'wsrep_cluster%';
+----------------------------+--------------------------------------+
| Variable_name | Value |
+----------------------------+--------------------------------------+
| wsrep_cluster_weight | 3 |
| wsrep_cluster_capabilities | |
| wsrep_cluster_conf_id | 3 |
| wsrep_cluster_size | 3 |
| wsrep_cluster_state_uuid | 881f52a2-3af3-11f1-b44d-b608ce7e87d4 |
| wsrep_cluster_status | Primary |
+----------------------------+--------------------------------------+
6 rows in set (0.00 sec)
mysql> show status where Variable_name in
-> ('wsrep_cluster_size','wsrep_cluster_status','wsrep_connected','wsrep_ready');
+----------------------+---------+
| Variable_name | Value |
+----------------------+---------+
| wsrep_cluster_size | 3 |
| wsrep_cluster_status | Primary |
| wsrep_connected | ON |
| wsrep_ready | ON |
+----------------------+---------+
4 rows in set (0.00 sec)
8、验证复制
按照以下步骤验证复制情况:在第二个节点上创建一个新数据库,在第三个节点上为该数据库创建一个表,并在第一个节点上向该表添加一些记录。
1、在第二个节点上创建一个新的数据库:
powershell
mysql> CREATE DATABASE percona;
Query OK, 1 row affected (0.01 sec)
2、切换至新创建的数据库(在第三个节点查看):
powershell
mysql> use percona;
Database changed
3、在第三个节点上创建一个表:
powershell
mysql> CREATE TABLE example (node_id INT PRIMARY KEY, node_name VARCHAR(30));
Query OK, 0 rows affected (0.02 sec)
4、在第一个节点上插入记录:
powershell
mysql> INSERT INTO percona.example VALUES (1, 'percona1');
Query OK, 1 row affected (0.00 sec)
5、从第二个节点的那个表中检索行:
powershell
mysql> SELECT * FROM percona.example;
+---------+-----------+
| node_id | node_name |
+---------+-----------+
| 1 | percona1 |
+---------+-----------+
1 row in set (0.00 sec)
9、节点下线
PXC 集群允许动态下线节点,但需要注意的是节点的启动命令和关闭命令必须一致,如以引导模式启动的第一个节点必须以引导模式来进行关闭:
powershell
[root@pxc1 ~]# systemctl stop mysql@bootstrap.service
其他节点则可以按照正常方式关闭:
powershell
[root@pxc2 ~]# systemctl stop mysql
至此,PXC 集群搭建成功。
9、部署PXC高可用
下面使用 HAProxy 让 PXC 集群实现负载均衡,通过 Keepalived 保障 HAProxy 服务高可用。
1、主机规划
| 主机名 | IP地址 | 端口 | 软件 | 节点 | 系统 |
|---|---|---|---|---|---|
| pxc1 | 192.168.194.11 | 3306 | Percona-XtraDB-Cluster-8.4.6-6 | Master节点 | RedHat 10.1 |
| pxc2 | 192.168.194.12 | 3306 | Percona-XtraDB-Cluster-8.4.6-6 | Standby节点 | RedHat 10.1 |
| pxc3 | 192.168.194.13 | 3306 | Percona-XtraDB-Cluster-8.4.6-6 | 备份节点 | RedHat 10.1 |
| lb01 | 192.168.194.14 | haproxy、keepalived | 主节点 | RedHat 10.1 | |
| lb02 | 192.168.194.15 | haproxy、keepalived | 从节点 | RedHat 10.1 | |
| 192.168.194.100 | VIP |
2、搭建PXC
直接使用前面搭建好的PXC集群即可。
3、搭建HAProxy
PXC 安装好后,采用 HAProxy 来分发连接对数据库进行访问。
环境准备,在克隆两个虚拟机,然后在配置IP以及主机等配置
powershell
hostnamectl set-hostname lb01 && bash
hostnamectl set-hostname lb02 && bash
nmcli c m ens160 ipv4.method manual ipv4.addr 192.168.194.14/24 ipv4.gateway 192.168.194.2 ipv4.dns 223.5.5.5 connection.autoconnect yes
nmcli c up ens160
nmcli c m ens160 ipv4.method manual ipv4.addr 192.168.194.15/24 ipv4.gateway 192.168.194.2 ipv4.dns 223.5.5.5 connection.autoconnect yes
nmcli c up ens160
cat >> /etc/hosts << EOF
192.168.194.11 pxc1
192.168.194.12 pxc2
192.168.194.13 pxc3
192.168.194.14 lb01
192.168.194.15 lb02
EOF
3.1 安装HAProxy
首先在 192.168.72.54 和 192.168.72.55 节点上安装 HAProxy 并进行配置。
powershell
dnf install haproxy -y
3.2 修改HAProxy配置
修改 HAProxy 配置文件:
powershell
cp /etc/haproxy/haproxy.cfg{,.bak}
vim /etc/haproxy/haproxy.cfg
文件内容后如下:
powershell
global
log 127.0.0.1 local0 info
log 127.0.0.1 local1 notice
maxconn 4096
uid 99
gid 99
daemon
defaults
log global
mode tcp
option tcplog
option dontlognull
retries 3
# 修正第15行的报错:添加 option 关键字
option redispatch
maxconn 2000
timeout connect 5000
timeout client 50000
timeout server 50000
# Web状态监控配置 (8088端口)
frontend stats-front
bind *:8088
mode http
default_backend stats-back
# PXC数据库前端配置 (3306端口)
frontend pxc-front
bind *:3306
mode tcp
default_backend pxc-cluster
backend stats-back
mode http
balance roundrobin
stats uri /haproxy/stats
stats refresh 5s
stats auth admin:admin
# PXC集群后端配置 - 直接检查3306端口
backend pxc-cluster
mode tcp
balance leastconn
# 按照老师要求:不使用 httpchk (9200),改用 mysql-check
option mysql-check user root
# 移除 check port 9200,直接探测默认的 3306
server pxc1 192.168.194.11:3306 check inter 2000 rise 2 fall 3
server pxc2 192.168.194.12:3306 check inter 2000 rise 2 fall 3
server pxc3 192.168.194.13:3306 check inter 2000 rise 2 fall 3
3.3 配置HAProxy日志
安装并配置完 HAProxy 后,默认情况下 HAProxy 为了节省读写 IO 所消耗的性能没有日志输出,下面是开启日志的过程。
1)打开配置日志文件
powershell
vim /etc/rsyslog.conf
在配置文件中打开 UDP 协议:
powershell
.....
# Provides UDP syslog reception
# for parameters see http://www.rsyslog.com/doc/imudp.html
module(load="imudp") # needs to be done just once
imput(type="imudb" port="514")

2)然后在该文件后面配置 haproxy 日志位置:
powershell
# Save boot messages also to boot.log
local7.* /var/log/boot.log
local0.* /var/log/haproxy.log # 和haproxy的配置文件中定义的log level一致

3)接着配置好后执行如下命令重启日志系统:
powershell
systemctl restart rsyslog
3.4 启动HAProxy服务
powershell
# 永久关闭(修改配置文件,防止下次重启失效)
sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
# 然后打开 /etc/haproxy/haproxy.cfg,将 uid 99 和 gid 99 这两行注释掉(在前面加 #),让它默认以 root 启动,或者确保 setenforce 0 已经执行。
uid 99
gid 99
以上两行注释掉haproxy才能正常启动
systemctl restart haproxy
systemctl is-active haproxy
3.5 测试HAProxy功能
添加用于测试的mysql用户
powershell
mysql> CREATE USER IF NOT EXISTS 'root'@'192.168.194.%' IDENTIFIED BY 'MySQL@123';
Query OK, 0 rows affected (0.01 sec)
mysql> GRANT USAGE ON *.* TO 'root'@'192.168.194.%';
Query OK, 0 rows affected (0.00 sec)
mysql> GRANT ALL PRIVILEGES ON *.* TO 'chengke'@'192.168.194.%';
Query OK, 0 rows affected (0.01 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)
注:其实可以只允许haproxy侧的IP访问即可,因用户通过vip访问mysql集群,haproxy根据调度策略使
用自己的ip创建与后端mysql服务器的连接。
查看Haproxy状态:
http://192.168.194.14:8088/haproxy/stats
输入用户密码: 用户--->admin,密码----->admin

4、搭建Keepalived
接着在 192.168.194.14 和 192.168.194.15 节点上安装配置 Keepalived,防止是 HAProxy 单点故障对数据库的访问产生影响,服务器之间通过 Keepalived 进行心跳检测,如果其中的某个机器出现问题,其中的一台将会接管,对用户来说整个过程透明。
1、安装Keepalived
bash
dnf install keepalived -y
2、配置Keepalived
bash
cp /etc/keepalived/keepalived.conf{,.bak}
vim /etc/keepalived/keepalived.conf
文件内容如下:
lb01主机
powershell
global_defs {
router_id haproxy_ha # keepalived组的名称
log_facility local6 # 使用syslog的local6设施来记录日志
log_level warning # 设置日志级别为warning及以上
}
vrrp_script chk_haproxy {
script "/etc/keepalived/check_haproxy.sh"
interval 2
weight 2
}
vrrp_instance VI_HAPROXY {
state BACKUP # 备份机是BACKUP
nopreempt # 非抢占模式
interface ens160
virtual_router_id 51 # 同一集群中该数值要相同,只能从1-255
priority 100 # 备库可以90
advert_int 1
authentication {
auth_type PASS # Auth 用密码,但密码不要超过8位
auth_pass 1111
}
track_script {
chk_haproxy
}
virtual_ipaddress {
192.168.194.100
}
}
lb02主机
powershell
global_defs {
router_id haproxy_ha # keepalived组的名称
log_facility local6 # 使用syslog的local6设施来记录日志
log_level warning # 设置日志级别为warning及以上
}
vrrp_script chk_haproxy {
script "/etc/keepalived/check_haproxy.sh"
interval 2
weight 2
}
vrrp_instance VI_HAPROXY {
state BACKUP # 备份机是BACKUP
nopreempt # 非抢占模式
interface ens160
virtual_router_id 51 # 同一集群中该数值要相同,只能从1-255
priority 90 # 备库可以90
advert_int 1
authentication {
auth_type PASS # Auth 用密码,但密码不要超过8位
auth_pass 1111
}
track_script {
chk_haproxy
}
virtual_ipaddress {
192.168.194.100
}
}
Note
这里 state 不配置 MASTER,是期望在 MASTER 宕机后再恢复时,不主动将 MASTER 状态抢过来,避免 MySQL 服务的波动。
由于不存在使用 lvs 进行负载均衡,不需要配置虚拟服务器 virtual server。
3、编写健康检查脚本
bash
[root@lb01 ~]# vim /etc/keepalived/check_haproxy.sh
脚本内容如下:
bash
#!/bin/bash
stat=$(ps -C haproxy --no-header | wc -l)
if [ $stat -eq 0 ]; then
/usr/bin/systemctl start haproxy
sleep 3
if [ $(ps -C haproxy --no-header | wc -l) -eq 0 ]; then
/usr/bin/systemctl stop keepalived
fi
fi
保存退出后修改脚本权限:
bash
[root@lb01 ~]# chmod a+x /etc/keepalived/check_haproxy.sh
4、复制配置文件
将主机 lb01(192.168.194.14)中 Keepalived 配置文件复制到 lb02(192.168.194.15)上:
bash
[root@lb01 ~]# scp -p /etc/keepalived/ lb02:/etc/keepalived/
5、配置日志功能
1)设置日志输出的设施
bash
[root@lb01 ~]# vim /etc/sysconfig/keepalived
# Options for keepalived. See `keepalived --help' output and keepalived(8) and
# keepalived.conf(5) man pages for a list of all options. Here are the most
# common ones :
#
# --vrrp -P Only run with VRRP subsystem.
# --check -C Only run with Health-checker subsystem.
# --dont-release-vrrp -V Dont remove VRRP VIPs & VROUTES on daemon stop.
# --dont-release-ipvs -I Dont remove IPVS topology on daemon stop.
# --dump-conf -d Dump the configuration data.
# --log-detail -D Detailed log messages.
# --log-facility -S 0-7 Set local syslog facility (default=LOG_DAEMON)
#
KEEPALIVED_OPTIONS="-D -S 6"

2)将local6设备的所有日志消息重定向到/data/keepalived.log文件中
bash
[root@master ~]# vim /etc/rsyslog.conf
local6.* /var/log/keepalived.log
[root@master ~]# systemctl restart rsyslog

6、启动Keepalived
bash
[root@lb01 ~]# systemctl enable --now keepalived
7、测试HProxy高可用
关闭当前 VIP 所在 HAProxy 服务,然后查看 VIP 是否成功漂移。
这里VIP已经出来了

至此,PXC高可用架构搭建完毕
注意本教程只适合学习环境使用,不适合生产环境使用。