Rocky Linux 9.5 部署 Percona XtraDB Cluster (PXC) 集群

1. 环境需求与节点规划

1.1 节点规划(示例)

|--------|-----------------|-----------|--------|
| 节点 | IP 地址 | 主机名 | 角色 |
| Node1 | 192.168.106.178 | pxc-node1 | 主节点 |
| Node2 | 192.168.106.179 | pxc-node2 | 从节点 |
| Node3 | 192.168.106.180 | pxc-node3 | 从节点 |

1.2 系统环境配置(所有节点执行)

1.2.1 配置主机名和 Hosts 解析
bash 复制代码
# 按节点分别设置主机名
hostnamectl set-hostname pxc-node1  # 192.168.106.178
hostnamectl set-hostname pxc-node2  # 192.168.106.179
hostnamectl set-hostname pxc-node3  # 192.168.106.180

# 统一添加 hosts 解析
cat >> /etc/hosts << EOF
192.168.106.178 pxc-node1
192.168.106.179 pxc-node2
192.168.106.180 pxc-node3
EOF
1.2.2 关闭 SELinux 和防火墙
bash 复制代码
# 临时关闭 SELinux
setenforce 0

# 永久关闭 SELinux
sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config

# 关闭防火墙(Rocky 9 默认使用 firewalld)
systemctl stop firewalld
systemctl disable firewalld

# 如果使用 nftables(可选检查)
systemctl disable --now nftables 2>/dev/null || true
1.2.3 配置系统内核参数
bash 复制代码
cat >> /etc/sysctl.conf << EOF
# PXC 优化参数
net.ipv4.tcp_syncookies = 1
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_reuse = 1
net.core.netdev_max_backlog = 2000
net.ipv4.ip_local_port_range = 1024 65535

# 内存与脏页优化
vm.swappiness = 0
vm.dirty_ratio = 80
vm.dirty_background_ratio = 5
EOF

sysctl -p

# 禁用透明大页(THP)
cat > /etc/systemd/system/disable-thp.service << EOF
[Unit]
Description=Disable Transparent Huge Pages

[Service]
Type=oneshot
ExecStart=/bin/sh -c "echo never > /sys/kernel/mm/transparent_hugepage/enabled"
ExecStart=/bin/sh -c "echo never > /sys/kernel/mm/transparent_hugepage/defrag"

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now disable-thp
1.2.4 配置资源限制
bash 复制代码
# 全局限制
cat >> /etc/security/limits.conf << EOF
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
* soft core unlimited
* hard core unlimited
EOF

# PXC 专用用户限制
cat > /etc/security/limits.d/99-pxc.conf << EOF
mysql soft nofile 65535
mysql hard nofile 65535
mysql soft nproc 65535
mysql hard nproc 65535
EOF

# 立即生效(需重新登录)
ulimit -n 65535
1.2.5 安装依赖软件包
bash 复制代码
# 启用 CRB 仓库(部分依赖在 EPEL 中)
dnf config-manager --set-enabled crb
dnf install -y epel-release

# 卸载冲突包
dnf remove -y mariadb* postfix 2>/dev/null || true

# 安装依赖(适配 Rocky 9 包名)
dnf install -y gcc gcc-c++ ncurses-devel cmake \
    libaio libaio-devel bind-utils wget curl \
    perl openssh-clients sysstat make libev \
    lrzsz perl-DBD-MySQL perl-IO-Socket-SSL \
    git scons check boost-devel asio-devel \
    readline-devel numactl-libs socat \
    openssl-devel zlib-devel pam-devel

# 安装 Red Hat 兼容层(部分工具需要)
dnf install -y redhat-lsb-core

2. 安装 Percona XtraDB Cluster

下载地址:Downloads - Percona

这里我将下载好的软件包上传到三个节点的/opt/pxc下,并解压:

2.1 安装依赖

bash 复制代码
dnf install -y epel-release
dnf config-manager --set-enabled crb

dnf install -y openssl-devel zlib-devel pam-devel \
               socat numactl-libs libev perl-DBD-MySQL \
               perl-IO-Socket-SSL rsync

2.2 安装 PXC & XtraBackup

bash 复制代码
cd /opt/pxc

dnf localinstall -y \
  Percona-XtraDB-Cluster-57-5.7.44-31.65.1.el9.x86_64.rpm \
  Percona-XtraDB-Cluster-server-57-5.7.44-31.65.1.el9.x86_64.rpm \
  Percona-XtraDB-Cluster-client-57-5.7.44-31.65.1.el9.x86_64.rpm \
  Percona-XtraDB-Cluster-shared-57-5.7.44-31.65.1.el9.x86_64.rpm \
  percona-xtrabackup-24-2.4.29-1.el9.x86_64.rpm

3. 配置 PXC 节点

3.1 节点1 配置文件 (/etc/my.cnf)

bash 复制代码
[mysqld]
server-id=1
wsrep_node_name=pxc-node1
wsrep_node_address=192.168.106.178
wsrep_cluster_address=gcomm://
# ===== 基础 =====
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

# ===== 网络 =====
bind-address=0.0.0.0
port=3306

# ===== InnoDB =====
default_storage_engine=InnoDB
innodb_autoinc_lock_mode=2
innodb_flush_log_at_trx_commit=0
innodb_buffer_pool_size=2G
innodb_log_file_size=1G
innodb_file_per_table=1
innodb_flush_method=O_DIRECT

# ===== Binlog =====
binlog_format=ROW

# ===== PXC / Galera =====
wsrep_provider=/usr/lib64/galera3/libgalera_smm.so
wsrep_cluster_name=pxc-cluster
wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth=sstuser:s3cretPass
wsrep_slave_threads=4
pxc_strict_mode=ENFORCING

[sst]
streamfmt=xbstream

[client]
socket=/var/lib/mysql/mysql.sock

节点2和节点3的区别:

bash 复制代码
server-id=2
wsrep_node_name=pxc-node2
wsrep_node_address=192.168.106.179
wsrep_cluster_address=gcomm://192.168.106.178,192.168.106.179,192.168.106.180

server-id=3
wsrep_node_name=pxc-node3
wsrep_node_address=192.168.106.180
wsrep_cluster_address=gcomm://192.168.106.178,192.168.106.179,192.168.106.180

3.2 创建数据目录

bash 复制代码
mkdir -p /var/lib/mysql
chown mysql:mysql /var/lib/mysql
chmod 750 /var/lib/mysql

mkdir -p /var/run/mysqld
chown mysql:mysql /var/run/mysqld

4.第 1 节点引导启动(仅 node1)

bash 复制代码
systemctl start mysql@bootstrap.service
systemctl status mysql@bootstrap.service
tail -f /var/log/mysqld.log

使用mysql -uroot -p,若找不到临时密码按照以下步骤操作:

bash 复制代码
#停掉 bootstrap 节点
systemctl stop mysql@bootstrap.service

#以跳过权限表方式启动 MySQL
mysqld --defaults-file=/etc/my.cnf \
       --skip-grant-tables \
       --skip-networking \
       --user=mysql &

#确认已启动
ps -ef | grep mysqld | grep -v grep

#无密码登录
mysql -uroot


-- 重新加载权限表(5.7 必须)
FLUSH PRIVILEGES;

-- 重置 root@localhost 密码
ALTER USER 'root'@'localhost'
IDENTIFIED BY 'YourStrongRootPassword';

-- 创建 SST 用户(与 my.cnf 保持一致)
CREATE USER 'sstuser'@'localhost'
IDENTIFIED BY 's3cretPass';

GRANT RELOAD, LOCK TABLES, PROCESS, REPLICATION CLIENT
ON *.* TO 'sstuser'@'localhost';

-- 可选:远程 root
CREATE USER 'root'@'%'
IDENTIFIED BY 'YourStrongRootPassword';

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'
WITH GRANT OPTION;

FLUSH PRIVILEGES;
EXIT;


# 停掉跳过权限表的 mysqld
mysqladmin -uroot -p'YourStrongRootPassword' shutdown

# 用 systemd 正常启动 bootstrap
systemctl start mysql@bootstrap.service


mysql -uroot -p'YourStrongRootPassword' -e "SELECT @@hostname;"

5.Node2 加入(Node3 同理)

1) SST 用户必须存在且认证方式可用(5.7 一般没问题)

bash 复制代码
mysql -uroot -p'YourStrongRootPassword' -e "
SELECT user,host,plugin FROM mysql.user WHERE user IN ('root','sstuser');
SHOW STATUS LIKE 'wsrep_cluster_size';
"

2) 安装SST 运行期依赖

bash 复制代码
dnf install -y socat rsync openssl

Node2:正常启动(⚠️ 不要用 bootstrap)

bash 复制代码
systemctl start mysql

3)在Node1上验证:

bash 复制代码
mysql -uroot -p'YourStrongRootPassword' -e "
SHOW STATUS LIKE 'wsrep_cluster_size';
SHOW STATUS LIKE 'wsrep_cluster_status';
SHOW STATUS LIKE 'wsrep_ready';
"
# wsrep_cluster_size = 2 就对了

Node3加入后wsrep_cluster_size = 3:

附:pxc-healthcheck.sh

bash 复制代码
#!/bin/bash
# PXC 集群健康检查脚本


# ============ 配置区 ============
MYSQL_USER="${MYSQL_USER:-root}"
MYSQL_PASS="${MYSQL_PASS:-YourStrongRootPassword}"
MYSQL_HOST="${MYSQL_HOST:-localhost}"
MYSQL_PORT="${MYSQL_PORT:-3306}"
MIN_CLUSTER_SIZE="${MIN_CLUSTER_SIZE:-2}"
# =================================

# ============ 函数定义 ============
log_message() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

check_mysql_connection() {
    if ! mysql -u"${MYSQL_USER}" -p"${MYSQL_PASS}" \
         -h"${MYSQL_HOST}" -P"${MYSQL_PORT}" \
         -e "SELECT 1;" >/dev/null 2>&1; then
        log_message "ERROR: 无法连接到 MySQL 服务器"
        return 1
    fi
    return 0
}

get_wsrep_status() {
    mysql -u"${MYSQL_USER}" -p"${MYSQL_PASS}" \
          -h"${MYSQL_HOST}" -P"${MYSQL_PORT}" \
          -e "SHOW STATUS LIKE 'wsrep_%';" 2>/dev/null
}

check_cluster_health() {
    local cluster_status cluster_size wsrep_ready
    local exit_code=0
    
    # 获取集群状态
    local status_output
    status_output=$(get_wsrep_status)
    
    # 提取关键指标
    cluster_status=$(echo "${status_output}" | awk '/wsrep_cluster_status/{print $2}')
    cluster_size=$(echo "${status_output}" | awk '/wsrep_cluster_size/{print $2}')
    wsrep_ready=$(echo "${status_output}" | awk '/wsrep_ready/{print $2}')
    
    # 输出详细信息
    log_message "=== PXC 集群健康检查结果 ==="
    log_message "节点: ${MYSQL_HOST}:${MYSQL_PORT}"
    log_message "集群状态: ${cluster_status:-N/A}"
    log_message "集群节点数: ${cluster_size:-0} (最小要求: ${MIN_CLUSTER_SIZE})"
    log_message "WSREP 就绪: ${wsrep_ready:-N/A}"
    
    # 检查各项指标
    if [[ "${cluster_status}" != "Primary" ]]; then
        log_message "CRITICAL: 集群状态异常 (非 Primary)"
        exit_code=2
    fi
    
    if [[ -z "${cluster_size}" ]] || (( cluster_size < MIN_CLUSTER_SIZE )); then
        log_message "CRITICAL: 集群节点数不足 (当前: ${cluster_size}, 要求: >=${MIN_CLUSTER_SIZE})"
        exit_code=2
    fi
    
    if [[ "${wsrep_ready}" != "ON" ]]; then
        log_message "CRITICAL: WSREP 未就绪"
        exit_code=2
    fi
    
    # 额外检查(可选)
    local local_state
    local_state=$(echo "${status_output}" | awk '/wsrep_local_state_comment/{print $2}')
    log_message "本地状态: ${local_state:-N/A}"
    
    if [[ "${local_state}" != "Synced" ]]; then
        log_message "WARNING: 本地节点未同步 (状态: ${local_state})"
        (( exit_code < 1 )) && exit_code=1
    fi
    
    return ${exit_code}
}
# =================================

# ============ 主流程 ============
main() {
    # 检查 MySQL 连接
    if ! check_mysql_connection; then
        exit 2
    fi
    
    # 执行健康检查
    if check_cluster_health; then
        log_message "OK: 集群运行正常"
        exit 0
    else
        local ret=$?
        log_message "CRITICAL: 检测到集群问题"
        exit ${ret}
    fi
}
# =================================

# 执行主函数
main
bash 复制代码
# 设置环境变量(推荐)
export MYSQL_PASS="YourStrongRootPassword"
./pxc-healthcheck.sh
相关推荐
zincsweet1 小时前
Linux 命名管道(FIFO)详解:原理分析、源码封装与通信流程图解
linux·服务器·c++·流程图
linux修理工1 小时前
使用 virt-install 命令行快速创建 KVM 虚拟机(以 CentOS 7 为例)
linux·运维·centos
|_⊙1 小时前
进程间通信(System V 标准下的多种通信方式)
linux·运维·服务器
云登指纹浏览器1 小时前
指纹浏览器自动化API对接实战总结:技术方案选型 + 避坑指南
运维·后端·自动化
蹉跎岁月新2 小时前
Jenkins创建一个maven-project
运维·jenkins·maven
zincsweet2 小时前
C++ 实现进程池:主从架构、管道通信与任务调度
linux·c++
草莓熊Lotso2 小时前
【CMake】静态库的编译、链接与引用全解析
linux·c语言·数据库·c++·软件工程·cmake
原来是猿2 小时前
性能测试(1)
运维·服务器·python·压力测试
郝学胜-神的一滴2 小时前
CMake 012:Linux 下动态库与可执行程序的单文件构建
linux·服务器·开发语言·c++·软件构建·cmake